diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index ebc7588a4026452da86133780f62e9369dff4961..7bffc14cb5f748d0fb32420cc232752f17ecbe96 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -800,6 +800,18 @@ split-rendering-smoke-test:
junit:
- report-junit.xml
+lc3-wrapper-unit-test:
+ extends:
+ - .test-job-linux
+ - .rules-merge-request
+ needs: ["build-codec-linux-cmake"]
+ stage: test
+ script:
+ - *enable-split-rendering
+ - cmake -B cmake-build -G "Unix Makefiles" -DCOPY_EXECUTABLES_FROM_BUILD_DIR=true
+ - cmake --build cmake-build -- -j
+ - scripts/split_rendering/lc3plus/ivas_lc3plus_unit_test
+
# compare split-rendering bitexactness between target and source branch
split-rendering-pytest-on-merge-request:
extends:
diff --git a/Workspace_msvc/lib_isar.vcxproj b/Workspace_msvc/lib_isar.vcxproj
index d50581fbee17aba89cfa3067805fa2bf7d62a68e..fceeb731ced2445a5434805d422d30654718782a 100644
--- a/Workspace_msvc/lib_isar.vcxproj
+++ b/Workspace_msvc/lib_isar.vcxproj
@@ -146,6 +146,7 @@
+
@@ -169,6 +170,7 @@
+
@@ -195,4 +197,4 @@
-
\ No newline at end of file
+
diff --git a/apps/decoder.c b/apps/decoder.c
index eeb2a19f20c1baba67e96b140f4beb1712e0a3ce..5a770f4d0a3a5549fa7f2769337cdc736ae3d92d 100644
--- a/apps/decoder.c
+++ b/apps/decoder.c
@@ -713,6 +713,13 @@ int main(
}
renderConfig.roomAcoustics.override = true;
}
+#ifdef SPLIT_REND_WITH_HEAD_ROT
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ /* ISAR frame size is set from command line, not renderer config file.
+ * This will be ignored if output format is not split rendering. */
+ renderConfig.split_rend_config.isar_frame_size_ms = (int16_t) arg.renderFramesize /* given in number of 5ms subframes */ * 5;
+#endif
+#endif
if ( ( error = IVAS_DEC_FeedRenderConfig( hIvasDec, renderConfig ) ) != IVAS_ERR_OK )
{
@@ -1976,6 +1983,10 @@ static ivas_error initOnFirstGoodFrame(
ISAR_SPLIT_REND_CODEC splitRendCodec;
int16_t splitRendCodecFrameSizeMs;
ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrection;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ int16_t splitRendIsarFrameSizeMs;
+ int16_t lc3plusHighRes;
+#endif
if ( ( error = IVAS_DEC_GetDelay( hIvasDec, delayNumSamples_temp, &delayTimeScale_temp ) ) != IVAS_ERR_OK )
{
@@ -1983,7 +1994,18 @@ static ivas_error initOnFirstGoodFrame(
return error;
}
- if ( ( error = IVAS_DEC_GetSplitRendBitstreamHeader( hIvasDec, &splitRendCodec, &poseCorrection, &splitRendCodecFrameSizeMs ) ) != IVAS_ERR_OK )
+ if ( ( error = IVAS_DEC_GetSplitRendBitstreamHeader( hIvasDec,
+ &splitRendCodec,
+ &poseCorrection,
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ &splitRendIsarFrameSizeMs,
+#endif
+ &splitRendCodecFrameSizeMs
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ,
+ &lc3plusHighRes
+#endif
+ ) ) != IVAS_ERR_OK )
{
fprintf( stderr, "\nUnable to get split renderer bitstream header: %s\n", ivas_error_to_string( error ) );
return error;
@@ -1991,7 +2013,20 @@ static ivas_error initOnFirstGoodFrame(
if ( IVAS_DEC_is_split_rendering_coded_out( hIvasDec ) )
{
- if ( ( error = split_rend_writer_open( splitRendWriter, arg.outputWavFilename, delayNumSamples_temp[0], delayTimeScale_temp, splitRendCodec, poseCorrection, splitRendCodecFrameSizeMs ) ) != IVAS_ERR_OK )
+ if ( ( error = split_rend_writer_open( splitRendWriter,
+ arg.outputWavFilename,
+ delayNumSamples_temp[0],
+ delayTimeScale_temp,
+ splitRendCodec,
+ poseCorrection,
+ splitRendCodecFrameSizeMs
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ,
+ splitRendIsarFrameSizeMs,
+ arg.output_Fs,
+ lc3plusHighRes
+#endif
+ ) ) != IVAS_ERR_OK )
{
fprintf( stderr, "\nUnable to open output split rendering metadata file %s\n", arg.outputWavFilename );
return error;
@@ -2007,7 +2042,20 @@ static ivas_error initOnFirstGoodFrame(
}
#endif
- if ( ( error = split_rend_writer_open( splitRendWriter, arg.outputMdFilename, delayNumSamples_temp[0], delayTimeScale_temp, splitRendCodec, poseCorrection, splitRendCodecFrameSizeMs ) ) != IVAS_ERR_OK )
+ if ( ( error = split_rend_writer_open( splitRendWriter,
+ arg.outputMdFilename,
+ delayNumSamples_temp[0],
+ delayTimeScale_temp,
+ splitRendCodec,
+ poseCorrection,
+ splitRendCodecFrameSizeMs
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ,
+ splitRendIsarFrameSizeMs,
+ arg.output_Fs,
+ lc3plusHighRes
+#endif
+ ) ) != IVAS_ERR_OK )
{
fprintf( stderr, "\nUnable to open output split rendering metadata file %s\n", arg.outputWavFilename );
return error;
@@ -2043,7 +2091,12 @@ static ivas_error initOnFirstGoodFrame(
splitRendBitsZero.buf_len = 0;
splitRendBitsZero.codec = ISAR_SPLIT_REND_CODEC_DEFAULT;
splitRendBitsZero.pose_correction = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ splitRendBitsZero.codec_frame_size_ms = 0;
+ splitRendBitsZero.isar_frame_size_ms = 20;
+#else
splitRendBitsZero.codec_frame_size_ms = 20;
+#endif
if ( split_rend_write_bitstream_to_file( *splitRendWriter, splitRendBitsZero.bits_buf, &splitRendBitsZero.bits_read, &splitRendBitsZero.bits_written ) != IVAS_ERR_OK )
{
diff --git a/apps/isar_post_rend.c b/apps/isar_post_rend.c
index 9060ed9c4c73cfaf58b6c8f8a4ffcde3474443b5..4113ea494f59876b042cf7aa3e1a16f588f52adc 100644
--- a/apps/isar_post_rend.c
+++ b/apps/isar_post_rend.c
@@ -730,7 +730,13 @@ int main(
bitsBuffer.config.bufLenInBytes = 0;
bitsBuffer.config.codec = ISAR_SPLIT_REND_CODEC_DEFAULT;
bitsBuffer.config.poseCorrection = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ bitsBuffer.config.codec_frame_size_ms = 5;
+ bitsBuffer.config.isar_frame_size_ms = 20;
+ bitsBuffer.config.lc3plusHighRes = 0;
+#else
bitsBuffer.config.codec_frame_size_ms = 20;
+#endif
CmdlnArgs args = parseCmdlnArgs( argc, argv );
@@ -754,11 +760,25 @@ int main(
SplitRendBFIFileReader_open( args.splitRendBFIFilePath, &splitRendBFIReader );
}
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ int32_t inFileSampleRate = 0;
+#endif
strncpy( audioFilePath, args.inputFilePath, FILENAME_MAX - 1 );
hSplitRendFileReadWrite = NULL;
if ( ( args.inConfig.numBinBuses > 0 ) && ( args.inConfig.binBuses[0].audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) )
{
- error = split_rend_reader_open( &hSplitRendFileReadWrite, args.inMetadataFilePaths[0], &bitsBuffer.config.codec, &bitsBuffer.config.poseCorrection, &bitsBuffer.config.codec_frame_size_ms );
+ error = split_rend_reader_open( &hSplitRendFileReadWrite,
+ args.inMetadataFilePaths[0],
+ &bitsBuffer.config.codec,
+ &bitsBuffer.config.poseCorrection,
+ &bitsBuffer.config.codec_frame_size_ms
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ,
+ &bitsBuffer.config.isar_frame_size_ms,
+ &inFileSampleRate,
+ &bitsBuffer.config.lc3plusHighRes
+#endif
+ );
if ( error != IVAS_ERR_OK )
{
fprintf( stderr, "Could not open split rend metadata file %s\n", args.inMetadataFilePaths[0] );
@@ -775,7 +795,18 @@ int main(
/*if split renderer is running in post renderer mode*/
if ( ( args.inConfig.numBinBuses > 0 ) && ( args.inConfig.binBuses[0].audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) )
{
- error = split_rend_reader_open( &hSplitRendFileReadWrite, args.inputFilePath, &bitsBuffer.config.codec, &bitsBuffer.config.poseCorrection, &bitsBuffer.config.codec_frame_size_ms );
+ error = split_rend_reader_open( &hSplitRendFileReadWrite,
+ args.inputFilePath,
+ &bitsBuffer.config.codec,
+ &bitsBuffer.config.poseCorrection,
+ &bitsBuffer.config.codec_frame_size_ms
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ,
+ &bitsBuffer.config.isar_frame_size_ms,
+ &inFileSampleRate,
+ &bitsBuffer.config.lc3plusHighRes
+#endif
+ );
if ( error != IVAS_ERR_OK )
{
fprintf( stderr, "Could not open split rend metadata file %s\n", args.inputFilePath );
@@ -784,12 +815,17 @@ int main(
audioReader = NULL;
}
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
int32_t inFileSampleRate = 0;
+#endif
if ( audioReader != NULL )
{
error = AudioFileReader_getSamplingRate( audioReader, &inFileSampleRate );
}
else
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ if ( hSplitRendFileReadWrite == NULL )
+#endif
{
inFileSampleRate = args.sampleRate;
}
@@ -797,7 +833,7 @@ int main(
switch ( error )
{
case IVAS_ERR_OK:
- /* If sampling rate not given on command line, use the one from wav file */
+ /* If sampling rate not given on command line, use the one from SR file */
if ( args.sampleRate == 0 )
{
args.sampleRate = inFileSampleRate;
@@ -848,8 +884,16 @@ int main(
if ( args.inConfig.numBinBuses > 0 )
{
- if ( ( error = ISAR_REND_SetSplitRendBitstreamHeader( hIsarPostRend, bitsBuffer.config.codec, bitsBuffer.config.poseCorrection,
- bitsBuffer.config.codec_frame_size_ms ) ) != IVAS_ERR_OK )
+ if ( ( error = ISAR_REND_SetSplitRendBitstreamHeader( hIsarPostRend,
+ bitsBuffer.config.codec,
+ bitsBuffer.config.poseCorrection,
+ bitsBuffer.config.codec_frame_size_ms
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ,
+ bitsBuffer.config.isar_frame_size_ms,
+ bitsBuffer.config.lc3plusHighRes
+#endif
+ ) ) != IVAS_ERR_OK )
{
fprintf( stderr, "Error in getting split renderer bitstream header: %s\n", ivas_error_to_string( error ) );
exit( -1 );
diff --git a/apps/renderer.c b/apps/renderer.c
index d6123d53cabfd9ef6a5720310fce189c7292edbc..f8c53320d1ca65ed22823cf907f90b58445c0642 100644
--- a/apps/renderer.c
+++ b/apps/renderer.c
@@ -762,7 +762,13 @@ int main(
bitsBuffer.config.bufLenInBytes = 0;
bitsBuffer.config.codec = ISAR_SPLIT_REND_CODEC_DEFAULT;
bitsBuffer.config.poseCorrection = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ bitsBuffer.config.codec_frame_size_ms = 5;
+ bitsBuffer.config.isar_frame_size_ms = 20;
+ bitsBuffer.config.lc3plus_highres = 0;
+#else
bitsBuffer.config.codec_frame_size_ms = 20;
+#endif
#endif
for ( i = 0; i < RENDERER_MAX_MC_INPUTS; ++i )
{
@@ -1106,6 +1112,14 @@ int main(
renderConfig.roomAcoustics.override = 1;
}
+#ifdef SPLIT_REND_WITH_HEAD_ROT
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ /* ISAR frame size is set from command line, not renderer config file.
+ * This will be ignored if output format is not split rendering. */
+ renderConfig.split_rend_config.isar_frame_size_ms = (int16_t) args.render_framesize /* given in number of 5ms subframes */ * 5;
+#endif
+#endif
+
if ( ( error = IVAS_REND_FeedRenderConfig( hIvasRend, renderConfig ) ) != IVAS_ERR_OK )
{
#ifdef SPLIT_REND_WITH_HEAD_ROT
@@ -1366,7 +1380,15 @@ int main(
if ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED )
{
- IVAS_REND_GetSplitRendBitstreamHeader( hIvasRend, &bitsBuffer.config.codec, &bitsBuffer.config.poseCorrection, &bitsBuffer.config.codec_frame_size_ms );
+ IVAS_REND_GetSplitRendBitstreamHeader( hIvasRend,
+ &bitsBuffer.config.codec,
+ &bitsBuffer.config.poseCorrection,
+ &bitsBuffer.config.codec_frame_size_ms
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ,
+ &bitsBuffer.config.isar_frame_size_ms
+#endif
+ );
if ( IVAS_REND_GetDelay( hIvasRend, &delayNumSamples_temp, &delayTimeScale_temp ) != IVAS_ERR_OK )
{
@@ -1374,7 +1396,20 @@ int main(
exit( -1 );
}
- if ( ( error = split_rend_writer_open( &hSplitRendFileReadWrite, args.outputFilePath, delayNumSamples_temp, delayTimeScale_temp, bitsBuffer.config.codec, bitsBuffer.config.poseCorrection, bitsBuffer.config.codec_frame_size_ms ) ) != IVAS_ERR_OK )
+ if ( ( error = split_rend_writer_open( &hSplitRendFileReadWrite,
+ args.outputFilePath,
+ delayNumSamples_temp,
+ delayTimeScale_temp,
+ bitsBuffer.config.codec,
+ bitsBuffer.config.poseCorrection,
+ bitsBuffer.config.codec_frame_size_ms
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ,
+ bitsBuffer.config.isar_frame_size_ms,
+ args.sampleRate,
+ bitsBuffer.config.lc3plus_highres
+#endif
+ ) ) != IVAS_ERR_OK )
{
fprintf( stderr, "Could not open split rend metadata file %s\n", args.outputFilePath );
exit( -1 );
@@ -1386,7 +1421,15 @@ int main(
if ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM )
{
- IVAS_REND_GetSplitRendBitstreamHeader( hIvasRend, &bitsBuffer.config.codec, &bitsBuffer.config.poseCorrection, &bitsBuffer.config.codec_frame_size_ms );
+ IVAS_REND_GetSplitRendBitstreamHeader( hIvasRend,
+ &bitsBuffer.config.codec,
+ &bitsBuffer.config.poseCorrection,
+ &bitsBuffer.config.codec_frame_size_ms
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ,
+ &bitsBuffer.config.isar_frame_size_ms
+#endif
+ );
if ( IVAS_REND_GetDelay( hIvasRend, &delayNumSamples_temp, &delayTimeScale_temp ) != IVAS_ERR_OK )
{
@@ -1394,7 +1437,20 @@ int main(
exit( -1 );
}
- if ( ( error = split_rend_writer_open( &hSplitRendFileReadWrite, args.outMetadataFilePath, delayNumSamples_temp, delayTimeScale_temp, bitsBuffer.config.codec, bitsBuffer.config.poseCorrection, bitsBuffer.config.codec_frame_size_ms ) ) != IVAS_ERR_OK )
+ if ( ( error = split_rend_writer_open( &hSplitRendFileReadWrite,
+ args.outMetadataFilePath,
+ delayNumSamples_temp,
+ delayTimeScale_temp,
+ bitsBuffer.config.codec,
+ bitsBuffer.config.poseCorrection,
+ bitsBuffer.config.codec_frame_size_ms
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ,
+ bitsBuffer.config.isar_frame_size_ms,
+ args.sampleRate,
+ bitsBuffer.config.lc3plus_highres
+#endif
+ ) ) != IVAS_ERR_OK )
{
fprintf( stderr, "Could not open split rend metadata file %s\n", args.outMetadataFilePath );
exit( -1 );
diff --git a/lib_com/common_api_types.h b/lib_com/common_api_types.h
index 1d4cde968052f087cd94d8e37f9d8269de822d2d..bb521f23ccc705c93eca47f4e4092c5b0caa476c 100644
--- a/lib_com/common_api_types.h
+++ b/lib_com/common_api_types.h
@@ -259,25 +259,35 @@ typedef struct _ISAR_SPLIT_REND_BITS_DATA
int16_t codec_frame_size_ms;
ISAR_SPLIT_REND_CODEC codec;
ISAR_SPLIT_REND_POSE_CORRECTION_MODE pose_correction;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ int16_t isar_frame_size_ms;
+ int16_t lc3plus_highres;
+#endif
} ISAR_SPLIT_REND_BITS_DATA, *ISAR_SPLIT_REND_BITS_HANDLE;
typedef struct _ISAR_SPLIT_REND_CONFIG
{
- int32_t splitRendBitRate; /*Bit rate for split rendering mode, if "pcm_out" is set then "splitRendBitRate" is used as a limit for MD bitrate */
- int16_t hq_mode; /*High quality 3DOF mode with additional side information. Requires more pre-renditions. */
- int16_t dof; /*flag to specify if pose correction is needed for 1, 2 or 3 degree of freedoms*/
- /*The axis can be set dynamically per frame based on a file input */
- /*possible values:
- 1 - (1dof correction. By default YAW correction)
- 2 - (2dof correction. By default YAW and PITCH correction)
- 3 - (3dof correction. By default YAW, PITCH and ROLL correction)
- */
- int16_t codec_delay_ms; /*PLACEHOLDER (currently being ignored) : look ahead delay of the codec that is used to code BIN signal output of pre-renderer*/
- int16_t codec_frame_size_ms; /*Codec frame size in milliseconds, only relevant with LC3plus */
+ int32_t splitRendBitRate; /*Bit rate for split rendering mode, if "pcm_out" is set then "splitRendBitRate" is used as a limit for MD bitrate */
+ int16_t hq_mode; /*High quality 3DOF mode with additional side information. Requires more pre-renditions. */
+ int16_t dof; /*flag to specify if pose correction is needed for 1, 2 or 3 degree of freedoms*/
+ /*The axis can be set dynamically per frame based on a file input */
+ /*possible values:
+ 1 - (1dof correction. By default YAW correction)
+ 2 - (2dof correction. By default YAW and PITCH correction)
+ 3 - (3dof correction. By default YAW, PITCH and ROLL correction)
+ */
+ int16_t codec_delay_ms; /*PLACEHOLDER (currently being ignored) : look ahead delay of the codec that is used to code BIN signal output of pre-renderer*/
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ int16_t isar_frame_size_ms; /* ISAR bit stream frame size in milliseconds */
+#endif
+ int16_t codec_frame_size_ms; /* Codec frame size in milliseconds, only relevant with LC3plus */
ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrectionMode;
ISAR_SPLIT_REND_CODEC codec;
ISAR_SPLIT_REND_RENDERER_SELECTION rendererSelection;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ int16_t lc3plus_highres;
+#endif
} ISAR_SPLIT_REND_CONFIG_DATA, *ISAR_SPLIT_REND_CONFIG_HANDLE;
#endif
diff --git a/lib_com/ivas_error.h b/lib_com/ivas_error.h
index d9d6b31138b4ef29c80e63a0f7678749755bfa7f..a5fe2d93489bc23be1f379c829b9d7bd6f8f1a21 100644
--- a/lib_com/ivas_error.h
+++ b/lib_com/ivas_error.h
@@ -104,6 +104,12 @@ typedef enum
* input data errors *
*----------------------------------------*/
IVAS_ERR_INVALID_BITSTREAM = 0x2000,
+#ifdef SPLIT_REND_WITH_HEAD_ROT
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ IVAS_ERR_UNEXPECTED_LC3PLUS_BITSTREAM,
+ IVAS_ERR_UNEXPECTED_LC3PLUS_BITSTREAM_CONFIG,
+#endif
+#endif
/*----------------------------------------*
* hardware errors *
diff --git a/lib_com/ivas_error_utils.h b/lib_com/ivas_error_utils.h
index ff0c96f624afa649d9d3f11e2c4e7dffc0aa5e4a..5bf677820f8bdf3af7e878b207ee6b709ea60c49 100644
--- a/lib_com/ivas_error_utils.h
+++ b/lib_com/ivas_error_utils.h
@@ -30,6 +30,9 @@
*******************************************************************************************************/
+#ifndef IVAS_ERROR_UTILS_H
+#define IVAS_ERROR_UTILS_H
+
#include "options.h"
#include
@@ -42,9 +45,6 @@
#include
#endif
-#ifndef IVAS_ERROR_UTILS_H
-#define IVAS_ERROR_UTILS_H
-
/*
* Usage:
*
@@ -83,7 +83,6 @@ static inline ivas_error ivas_error_wrapper( const ivas_error error_code, const
va_end( args );
fprintf( stderr, "\n\nIn function: %s(), %s:%d\n\n", function, file, line );
- // assert( 0 );
return error_code;
}
diff --git a/lib_com/options.h b/lib_com/options.h
index 7dd0ba57d3ee910d474c827457a4edd6ea2fba2d..dd37e87f03ab866d3156194bb99d899df33d6ba4 100644
--- a/lib_com/options.h
+++ b/lib_com/options.h
@@ -155,6 +155,7 @@
/*#define FIX_I4_OL_PITCH*/ /* fix open-loop pitch used for EVS core switching */
#define SPLIT_REND_WITH_HEAD_ROT /* Dlb,FhG: Split Rendering contributions 21 and 35 */
+#define ISAR_BITSTREAM_UPDATE_LC3PLUS /* FhG: Multiple improvements to the ISAR bitstream when LC3plus is used. See MR 1456 for details. */
#define SPLIT_REND_POSE_CORRECTION_UNUSED_BITS
#define FIX_NUM_SUBFRAME_UPDATE
diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c
index 71f89ea508d9baf17ccb9aa12ed166c08d0a94a2..33e820a9cf88ea2c378c0c1f3c1251f68e669687 100644
--- a/lib_dec/lib_dec.c
+++ b/lib_dec/lib_dec.c
@@ -271,6 +271,10 @@ static ivas_error isar_set_split_rend_setup(
splitRendBits->codec = ISAR_SPLIT_REND_CODEC_DEFAULT;
splitRendBits->pose_correction = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE;
splitRendBits->codec_frame_size_ms = 0;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ splitRendBits->isar_frame_size_ms = 0;
+ splitRendBits->lc3plus_highres = 0;
+#endif
if ( ( hSplitBinRend->hMultiBinCldfbData = (ISAR_DEC_SPLIT_REND_MULTI_BIN_CLDFB_DATA_HANDLE) malloc( sizeof( ISAR_DEC_SPLIT_REND_MULTI_BIN_CLDFB_DATA ) ) ) == NULL )
{
@@ -1230,6 +1234,9 @@ ivas_error IVAS_DEC_GetSplitBinauralBitstream(
Quaternion,
st_ivas->hRenderConfig->split_rend_config.splitRendBitRate,
st_ivas->hRenderConfig->split_rend_config.codec,
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ st_ivas->hRenderConfig->split_rend_config.isar_frame_size_ms,
+#endif
st_ivas->hRenderConfig->split_rend_config.codec_frame_size_ms,
splitRendBits,
Cldfb_RealBuffer_Binaural,
@@ -2110,14 +2117,22 @@ static ivas_error copyRendererConfigStruct(
mvr2r( hRCin->roomAcoustics.pAcoustic_dsr, hRCout->roomAcoustics.pAcoustic_dsr, CLDFB_NO_CHANNELS_MAX );
mvr2r( hRCin->directivity, hRCout->directivity, 3 * MAX_NUM_OBJECTS );
#ifdef SPLIT_REND_WITH_HEAD_ROT
+ /* TODO: This seems wrong. Why set default instead of copying from hRCin?
+ * Currently seems to work because we only ever copy from a default-initialized handle anyway */
hRCout->split_rend_config.splitRendBitRate = SPLIT_REND_768k;
hRCout->split_rend_config.dof = 3;
hRCout->split_rend_config.hq_mode = 0;
hRCout->split_rend_config.codec_delay_ms = 0;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ hRCout->split_rend_config.isar_frame_size_ms = 20;
+#endif
hRCout->split_rend_config.codec_frame_size_ms = 0; /* 0 means "use default for selected codec" */
hRCout->split_rend_config.codec = ISAR_SPLIT_REND_CODEC_DEFAULT;
hRCout->split_rend_config.poseCorrectionMode = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB;
hRCout->split_rend_config.rendererSelection = hRCin->split_rend_config.rendererSelection;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ hRCout->split_rend_config.lc3plus_highres = hRCin->split_rend_config.lc3plus_highres;
+#endif
#endif
hRCout->roomAcoustics.use_er = hRCin->roomAcoustics.use_er;
hRCout->roomAcoustics.lowComplexity = hRCin->roomAcoustics.lowComplexity;
@@ -3809,7 +3824,15 @@ ivas_error IVAS_DEC_GetSplitRendBitstreamHeader(
IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
ISAR_SPLIT_REND_CODEC *pCodec, /* o: pointer to codec setting */
ISAR_SPLIT_REND_POSE_CORRECTION_MODE *poseCorrection, /* o: pointer to pose correction mode */
- int16_t *pCodec_frame_size_ms /* o: pointer to codec frame size setting */ )
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ int16_t *pIsar_frame_size_ms, /* o: pointer to isar frame size setting */
+#endif
+ int16_t *pCodec_frame_size_ms /* o: pointer to codec frame size setting */
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ,
+ int16_t *pLc3plusHighRes
+#endif
+)
{
if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL )
{
@@ -3819,6 +3842,10 @@ ivas_error IVAS_DEC_GetSplitRendBitstreamHeader(
*pCodec = hIvasDec->st_ivas->hRenderConfig->split_rend_config.codec;
*pCodec_frame_size_ms = hIvasDec->st_ivas->hRenderConfig->split_rend_config.codec_frame_size_ms;
*poseCorrection = hIvasDec->st_ivas->hRenderConfig->split_rend_config.poseCorrectionMode;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ *pIsar_frame_size_ms = hIvasDec->st_ivas->hRenderConfig->split_rend_config.isar_frame_size_ms;
+ *pLc3plusHighRes = hIvasDec->st_ivas->hRenderConfig->split_rend_config.lc3plus_highres;
+#endif
return IVAS_ERR_OK;
}
@@ -3907,8 +3934,10 @@ static void *pcm_buffer_offset(
}
break;
default:
- return NULL;
+ break;
}
+
+ return NULL;
}
diff --git a/lib_dec/lib_dec.h b/lib_dec/lib_dec.h
index 9a2b6d4b16929457cabad7a37dada51439003002..bafbf36dace0112580f621a01166171d6dccfc98 100644
--- a/lib_dec/lib_dec.h
+++ b/lib_dec/lib_dec.h
@@ -182,7 +182,14 @@ ivas_error IVAS_DEC_GetSplitRendBitstreamHeader(
IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */
ISAR_SPLIT_REND_CODEC *pCodec, /* o: pointer to codec setting */
ISAR_SPLIT_REND_POSE_CORRECTION_MODE *poseCorrection, /* o: pointer to pose correction mode */
- int16_t *pCodec_frame_size_ms /* o: pointer to codec frame size setting */
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ int16_t *pIsar_frame_size_ms, /* o: pointer to isar frame size setting */
+#endif
+ int16_t *pCodec_frame_size_ms /* o: pointer to codec frame size setting */
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ,
+ int16_t *pLc3plusHighRes /* o: pointer to LC3plus High-Res setting */
+#endif
);
/*! r: decoder error code */
diff --git a/lib_isar/isar_cnst.h b/lib_isar/isar_cnst.h
index aa475a9c9a7506d80c801d0ebd334de6ba4ebfef..d93f9ae39f7b0f2fac02a21309086c42eb6273d6 100644
--- a/lib_isar/isar_cnst.h
+++ b/lib_isar/isar_cnst.h
@@ -115,6 +115,10 @@ typedef enum
#define ISAR_SPLIT_REND_ROT_AXIS_BITS 3
#define ISAR_SPLIT_REND_RO_FLAG_BITS 1
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+#define IVAS_LC3PLUS_MAX_NUM_DECODERS 2
+#endif
+
/*----------------------------------------------------------------------------------*
* Split rendering bitrate constants
*----------------------------------------------------------------------------------*/
diff --git a/lib_isar/isar_lc3plus_common.c b/lib_isar/isar_lc3plus_common.c
index e878b890cf2b683d617a8a40aee20cede88f69ca..7a9010335f2690c40b4931a374575113efcea973 100644
--- a/lib_isar/isar_lc3plus_common.c
+++ b/lib_isar/isar_lc3plus_common.c
@@ -57,4 +57,33 @@ ivas_error ISAR_LC3PLUS_LC3plusErrToIvasErr(
return IVAS_ERR_INTERNAL;
}
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ivas_error IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( const LC3PLUS_RTP_ERR lc3PlusRtpError )
+{
+ switch ( lc3PlusRtpError )
+ {
+ case LC3PLUS_RTP_ERR_NO_ERROR:
+ return IVAS_ERR_OK;
+ case LC3PLUS_RTP_ERR_NULL_PTR:
+ return IVAS_ERR_UNEXPECTED_NULL_POINTER;
+ case LC3PLUS_RTP_ERR_INVALID_PARAMETERS:
+ return IVAS_ERR_WRONG_PARAMS;
+ case LC3PLUS_RTP_ERR_NOT_IMPLEMENTED:
+ return IVAS_ERR_NOT_IMPLEMENTED;
+ case LC3PLUS_RTP_ERR_UNSUPPORTED_CONFIGURATION:
+ return IVAS_ERR_INTERNAL;
+ case LC3PLUS_RTP_ERR_INVALID_BITSTREAM:
+ return IVAS_ERR_UNEXPECTED_LC3PLUS_BITSTREAM;
+ case LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE:
+ return IVAS_ERR_INVALID_BUFFER_SIZE;
+ case LC3PLUS_RTP_ERR_NOT_ENOUGH_FTDS_ALLOCATED:
+ return IVAS_ERR_INTERNAL;
+ case LC3PLUS_RTP_ERR_GENERIC_ERROR:
+ default:
+ break;
+ }
+
+ return IVAS_ERR_UNKNOWN;
+}
+#endif
#endif
diff --git a/lib_isar/isar_lc3plus_common.h b/lib_isar/isar_lc3plus_common.h
index e350129499e2016a974b469cc6f5977cb76ab84d..13decaf944f66782242f51c8c09bed0b17da9806 100644
--- a/lib_isar/isar_lc3plus_common.h
+++ b/lib_isar/isar_lc3plus_common.h
@@ -35,25 +35,38 @@
#include
+#include "options.h"
#include "ivas_error.h"
#ifdef SPLIT_REND_WITH_HEAD_ROT
#include "lc3.h"
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+#include "isar_lc3plus_payload.h"
+#endif
/*! common configuration parameters between encoder and decoder */
typedef struct LC3PLUS_CONFIG
{
/*! frame duration in microseconds [10000, 5000, 2500] */
- uint32_t lc3plus_frame_duration_us;
- /*! ivas frame duration in microseconds [20000, 5000] */
- uint32_t ivas_frame_duration_us;
+ int16_t lc3plus_frame_duration_us;
+ /*! isar frame duration in microseconds [20000, 10000, 5000] */
+ int16_t isar_frame_duration_us;
/*! sampling rate*/
- uint32_t samplerate;
+ int32_t samplerate;
/*! number of channels */
- uint16_t channels;
+ int16_t channels;
+#if defined ISAR_BITSTREAM_UPDATE_LC3PLUS || defined ISAR_BITSTREAM_UPDATE_LC3PLUS
+ /*! high resolution mode enabled (1) or disabled (0)*/
+ int16_t high_res_mode_enabled;
+#endif
} LC3PLUS_CONFIG;
/*! utility function to convert LC3PLUS_Errors to the suitable ivas_error */
ivas_error ISAR_LC3PLUS_LC3plusErrToIvasErr( const LC3PLUS_Error lc3PlusError );
+
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+/*! utility function to convert LC3PLUS_Errors to the suitable ivas_error */
+ivas_error IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( const LC3PLUS_RTP_ERR lc3PlusRtpError );
#endif
-#endif /* IVAS_LC3PLUS_COM_H */
+#endif /* SPLIT_REND_WITH_HEAD_ROT */
+#endif /* ISAR_LC3PLUS_COM_H */
diff --git a/lib_isar/isar_lc3plus_dec.c b/lib_isar/isar_lc3plus_dec.c
index 7ca5dda48eb0a08a0068b9a79d2db339c95fa34c..565f55e8cc5ee90cb679e1789b96684762001732 100644
--- a/lib_isar/isar_lc3plus_dec.c
+++ b/lib_isar/isar_lc3plus_dec.c
@@ -42,6 +42,7 @@
#ifdef SPLIT_REND_WITH_HEAD_ROT
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
/*-------------------------------------------------------------------------
* isar_LC3PLUS_AllocateSubframeDecodingMatrix()
*
@@ -60,6 +61,7 @@ static void isar_LC3PLUS_DEC_FreeSubframeDecodingMatrix(
return;
}
+#endif
/*-------------------------------------------------------------------------
@@ -75,20 +77,37 @@ ivas_error ISAR_LC3PLUS_DEC_Open(
{
LC3PLUS_Error err;
int32_t decoder_size;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ int16_t i;
+
+ if ( 0 == config.lc3plus_frame_duration_us )
+ {
+ return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Invalid lc3plus_frame_duration_us (0)\n" );
+ }
+#else
int16_t lc3plusFrameIdx;
int16_t numLC3plusFramesPerIvasFrame;
int16_t i;
+#endif
if ( ( *handle = malloc( sizeof( struct ISAR_LC3PLUS_DEC_HANDLE ) ) ) == NULL )
{
return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" );
}
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ if ( config.channels > IVAS_LC3PLUS_MAX_NUM_DECODERS )
+ {
+ return IVAS_ERROR( IVAS_ERR_INIT_ERROR, "Maximum number of channels exceeds IVAS_LC3PLUS_MAX_NUM_DECODERS\n" );
+ }
+#else
+
if ( 0 == config.lc3plus_frame_duration_us )
{
return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Invalid lc3plus_frame_duration_us (0)\n" );
}
- numLC3plusFramesPerIvasFrame = (int16_t) ( config.ivas_frame_duration_us / config.lc3plus_frame_duration_us );
+ numLC3plusFramesPerIvasFrame = (int16_t) ( config.isar_frame_duration_us / config.lc3plus_frame_duration_us );
+#endif
( *handle )->num_decs = 0;
@@ -147,7 +166,11 @@ ivas_error ISAR_LC3PLUS_DEC_Open(
return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus decoder\n" );
}
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ err = lc3plus_dec_init( ( *handle )->handles[iCh], config.samplerate, 1, LC3PLUS_PLC_ADVANCED, config.high_res_mode_enabled );
+#else
err = lc3plus_dec_init( ( *handle )->handles[iCh], config.samplerate, 1, LC3PLUS_PLC_ADVANCED, 0 );
+#endif
if ( LC3PLUS_OK != err )
{
ISAR_LC3PLUS_DEC_Close( handle );
@@ -168,18 +191,24 @@ ivas_error ISAR_LC3PLUS_DEC_Open(
return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus decoder\n" );
}
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
if ( ( ( *handle )->selective_decoding_states[iCh]->frame_actions = malloc( numLC3plusFramesPerIvasFrame * sizeof( SelectiveDecAction ) ) ) == NULL )
{
ISAR_LC3PLUS_DEC_Close( handle );
return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus decoder\n" );
}
+#endif
( *handle )->selective_decoding_states[iCh]->has_skipped_a_frame = 0;
( *handle )->selective_decoding_states[iCh]->shall_decode_cached_frame = 0;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ( *handle )->selective_decoding_states[iCh]->frame_action = DEC_ACTION_DECODE_AND_USE;
+#else
for ( lc3plusFrameIdx = 0; lc3plusFrameIdx < numLC3plusFramesPerIvasFrame; lc3plusFrameIdx++ )
{
( *handle )->selective_decoding_states[iCh]->frame_actions[lc3plusFrameIdx] = DEC_ACTION_DECODE_AND_USE;
}
+#endif
/* allocate and configure per LC3plus decoder bitstream cache */
if ( ( ( *handle )->bitstream_caches[iCh] = malloc( sizeof( ISAR_LC3PLUS_DEC_BITSTREAM_CACHE ) ) ) == NULL )
@@ -187,7 +216,11 @@ ivas_error ISAR_LC3PLUS_DEC_Open(
ISAR_LC3PLUS_DEC_Close( handle );
return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus decoder\n" );
}
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ( *handle )->bitstream_caches[iCh]->bitstream_cache_capacity = 400 /*LC3plus max non-HR octet count*/;
+#else
( *handle )->bitstream_caches[iCh]->bitstream_cache_capacity = 400 /*LC3plus max non-HR octet count*/ * numLC3plusFramesPerIvasFrame;
+#endif
if ( ( ( *handle )->bitstream_caches[iCh]->bitstream_cache = malloc( ( *handle )->bitstream_caches[iCh]->bitstream_cache_capacity ) ) == NULL )
{
ISAR_LC3PLUS_DEC_Close( handle );
@@ -197,7 +230,7 @@ ivas_error ISAR_LC3PLUS_DEC_Open(
}
( *handle )->config = config;
- if ( config.ivas_frame_duration_us < config.lc3plus_frame_duration_us || config.ivas_frame_duration_us % config.lc3plus_frame_duration_us != 0 )
+ if ( config.isar_frame_duration_us < config.lc3plus_frame_duration_us || config.isar_frame_duration_us % config.lc3plus_frame_duration_us != 0 )
{
ISAR_LC3PLUS_DEC_Close( handle );
return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "Current pcm_conversion_buffer sizing requires that lc3plus uses a shorter or equal frame duration than ivas\n" );
@@ -212,7 +245,7 @@ ivas_error ISAR_LC3PLUS_DEC_Open(
return IVAS_ERR_OK;
}
-
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
/*-------------------------------------------------------------------------
* ISAR_LC3PLUS_DEC_AllocateSubframeDecodingMatrix()
*
@@ -261,7 +294,7 @@ ivas_error ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix(
int16_t numIvasSubFramesPerLC3frame;
uint32_t decIdx;
int16_t ivasSubframeIdx;
- int16_t effectiveIvasSubframeDuration;
+ int16_t effectiveIsarSubframeDuration;
int16_t actual_num_spatial_subframes;
if ( NULL == handle )
@@ -274,14 +307,14 @@ ivas_error ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix(
return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "subframeChannelMatrix is NULL\n" );
}
- if ( handle->config.lc3plus_frame_duration_us == 0 || handle->config.ivas_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 )
+ if ( handle->config.lc3plus_frame_duration_us == 0 || handle->config.isar_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 )
{
- return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "invalid ivas_frame_duration_us/lc3plus_frame_duration_us values\n" );
+ return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "invalid isar_frame_duration_us/lc3plus_frame_duration_us values\n" );
}
- effectiveIvasSubframeDuration = (int16_t) ( handle->config.ivas_frame_duration_us == 20000 ? handle->config.ivas_frame_duration_us / MAX_PARAM_SPATIAL_SUBFRAMES : handle->config.ivas_frame_duration_us );
- numIvasSubFramesPerLC3frame = (int16_t) handle->config.lc3plus_frame_duration_us / effectiveIvasSubframeDuration;
- actual_num_spatial_subframes = (int16_t) handle->config.ivas_frame_duration_us / effectiveIvasSubframeDuration;
+ effectiveIsarSubframeDuration = (int16_t) ( handle->config.isar_frame_duration_us == 20000 ? handle->config.isar_frame_duration_us / MAX_PARAM_SPATIAL_SUBFRAMES : handle->config.isar_frame_duration_us );
+ numIvasSubFramesPerLC3frame = (int16_t) handle->config.lc3plus_frame_duration_us / effectiveIsarSubframeDuration;
+ actual_num_spatial_subframes = (int16_t) handle->config.isar_frame_duration_us / effectiveIsarSubframeDuration;
/* 0.5(0) = 10ms lc3plus, 5ms subframe */
if ( numIvasSubFramesPerLC3frame != 1 )
{
@@ -360,6 +393,7 @@ ivas_error ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix(
return IVAS_ERR_OK;
}
+#endif
/*-------------------------------------------------------------------------
@@ -430,7 +464,9 @@ void ISAR_LC3PLUS_DEC_Close(
if ( NULL != ( *handle )->selective_decoding_states && NULL != ( *handle )->selective_decoding_states[iDec] )
{
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
free( ( *handle )->selective_decoding_states[iDec]->frame_actions );
+#endif
free( ( *handle )->selective_decoding_states[iDec] );
}
@@ -509,13 +545,20 @@ static ivas_error isar_LC3PLUS_DEC_Decode_or_Conceal_internal(
)
{
uint32_t iDec;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ int32_t config_num_media_times;
+ int32_t iMediaTime;
+ int32_t iFtd;
+ LC3PLUS_RTP_PAYLOAD payload;
+#else
int32_t iLc3plusFrame;
int32_t lc3framesPerIvasFrame;
+ int32_t bitstreamOffsetPerCoder;
+ uint8_t *bitstream_in_iter = bitstream_in;
+#endif
int32_t ivasSampleIndex;
int16_t numSamplesPerLC3plusChannel;
- int32_t bitstreamOffsetPerCoder;
ivas_error err;
- uint8_t *bitstream_in_iter = bitstream_in;
if ( NULL == handle )
{
@@ -538,19 +581,59 @@ static ivas_error isar_LC3PLUS_DEC_Decode_or_Conceal_internal(
return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "bitstream_in_size must be positive\n" );
}
- if ( handle->config.ivas_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 )
+ if ( handle->config.isar_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 )
{
- return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "ivas_frame_duration_us must be equal or multiple of lc3plus_frame_duration_us \n" );
+ return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "isar_frame_duration_us must be equal or multiple of lc3plus_frame_duration_us \n" );
+ }
+
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ config_num_media_times = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us;
+ if ( !badFrameIndicator )
+ {
+ if ( LC3PLUS_RTP_payload_deserialize( &payload, bitstream_in, bitstream_in_size ) != LC3PLUS_RTP_ERR_NO_ERROR )
+ {
+ return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_payload_deserialize failed\n" );
+ }
+ if ( payload.sampling_rate_hz != handle->config.samplerate )
+ {
+ return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "LC3plus config change (samplerate) in bitstream is not supported\n" );
+ }
+ if ( payload.num_channels != handle->config.channels )
+ {
+ return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "LC3plus config change (number of channels) in bitstream is not supported\n" );
+ }
+ if ( payload.frame_duration_us != handle->config.lc3plus_frame_duration_us )
+ {
+ return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "LC3plus config change (frame duration) in bitstream is not supported\n" );
+ }
+ if ( payload.high_resolution_enabled != handle->config.high_res_mode_enabled )
+ {
+ return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "LC3plus config change (high resolution mode) in bitstream is not supported\n" );
+ }
+ if ( payload.num_media_times != config_num_media_times )
+ {
+ return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "LC3plus config change (number of media times per frame data block) in bitstream is not supported\n" );
+ }
}
+#endif
- lc3framesPerIvasFrame = handle->config.ivas_frame_duration_us / handle->config.lc3plus_frame_duration_us;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ numSamplesPerLC3plusChannel = (int16_t) ( handle->config.samplerate / ( 1000000 / handle->config.isar_frame_duration_us ) / config_num_media_times );
+ for ( iDec = 0; iDec < handle->num_decs; iDec++ )
+ {
+ for ( iMediaTime = 0; iMediaTime < config_num_media_times; iMediaTime++ )
+ {
+ iFtd = iDec + iMediaTime * handle->num_decs;
+#else
+ lc3framesPerIvasFrame = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us;
- numSamplesPerLC3plusChannel = (int16_t) ( handle->config.samplerate / ( 1000000 / handle->config.ivas_frame_duration_us ) / lc3framesPerIvasFrame );
+ numSamplesPerLC3plusChannel = (int16_t) ( handle->config.samplerate / ( 1000000 / handle->config.isar_frame_duration_us ) / lc3framesPerIvasFrame );
bitstreamOffsetPerCoder = bitstream_in_size / handle->num_decs / lc3framesPerIvasFrame;
for ( iDec = 0; iDec < handle->num_decs; iDec++ )
{
for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
{
+#endif
if ( handle->selective_decoding_states[iDec]->shall_decode_cached_frame )
{
if ( 0 == handle->bitstream_caches[iDec]->bitstream_cache_size )
@@ -572,8 +655,14 @@ static ivas_error isar_LC3PLUS_DEC_Decode_or_Conceal_internal(
{
handle->bitstream_caches[iDec]->bitstream_cache_size = 0;
}
+
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ switch ( handle->selective_decoding_states[iDec]->frame_action )
+#else
switch ( handle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] )
+#endif
{
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
case DEC_ACTION_DECODE_AND_DROP:
{
err = decode_or_conceal_one_lc3plus_frame( handle->handles[iDec], bitstream_in_iter, bitstreamOffsetPerCoder, &handle->pcm_conversion_buffer, badFrameIndicator );
@@ -584,8 +673,37 @@ static ivas_error isar_LC3PLUS_DEC_Decode_or_Conceal_internal(
handle->selective_decoding_states[iDec]->has_skipped_a_frame = 0;
break;
}
+#endif
case DEC_ACTION_DECODE_AND_USE:
{
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ if ( badFrameIndicator )
+ {
+ err = decode_or_conceal_one_lc3plus_frame( handle->handles[iDec], bitstream_in, bitstream_in_size, &handle->pcm_conversion_buffer, badFrameIndicator );
+ }
+ else if ( payload.ftds[iFtd].frame_data_length == LC3PLUS_RTP_FDL_SPEECH_BAD )
+ {
+ return IVAS_ERR_NOT_IMPLEMENTED;
+ /* Untested therefore disabled. Would probably only need to call concealment,
+ * but the LC3plus API requires a non-NULL ptr for this which is not available here */
+ }
+ else
+ {
+ err = decode_or_conceal_one_lc3plus_frame( handle->handles[iDec], payload.ftds[iFtd].frame_data, payload.ftds[iFtd].frame_data_length, &handle->pcm_conversion_buffer, badFrameIndicator );
+ }
+ if ( err != IVAS_ERR_OK )
+ {
+ return IVAS_ERROR( err, "lc3plus decoding failed\n" );
+ }
+
+ for ( int16_t iSampleInt16 = 0; iSampleInt16 < numSamplesPerLC3plusChannel; iSampleInt16++ )
+ {
+ ivasSampleIndex = iSampleInt16 + iMediaTime * numSamplesPerLC3plusChannel;
+ pcm_out[iDec][ivasSampleIndex] = (float) handle->pcm_conversion_buffer[iSampleInt16];
+ }
+ handle->selective_decoding_states[iDec]->has_skipped_a_frame = 0;
+ break;
+#else
err = decode_or_conceal_one_lc3plus_frame( handle->handles[iDec], bitstream_in_iter, bitstreamOffsetPerCoder, &handle->pcm_conversion_buffer, badFrameIndicator );
if ( err != IVAS_ERR_OK )
{
@@ -599,15 +717,30 @@ static ivas_error isar_LC3PLUS_DEC_Decode_or_Conceal_internal(
}
handle->selective_decoding_states[iDec]->has_skipped_a_frame = 0;
break;
+#endif
}
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
case DEC_ACTION_SKIP:
{
/* log that this instance has skipped a frame and must decode twice once reactivated */
handle->selective_decoding_states[iDec]->has_skipped_a_frame = 1;
break;
}
+#endif
case DEC_ACTION_CACHE:
{
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ if ( handle->bitstream_caches[iDec]->bitstream_cache_capacity < (int32_t) payload.ftds[iFtd].frame_data_length )
+ {
+ return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "bitstream_cache_capacity is too low for LC3plus frame size\n" );
+ }
+ /* store bit rate of cached frame */
+ mvc2c( payload.ftds[iFtd].frame_data, handle->bitstream_caches[iDec]->bitstream_cache, (int16_t) payload.ftds[iFtd].frame_data_length );
+ handle->bitstream_caches[iDec]->bitstream_cache_size = payload.ftds[iFtd].frame_data_length;
+ /* log that this instance has skipped a frame and must decode twice once reactivated */
+ handle->selective_decoding_states[iDec]->has_skipped_a_frame = 1;
+ break;
+#else
if ( handle->bitstream_caches[iDec]->bitstream_cache_capacity < bitstreamOffsetPerCoder )
{
return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "bitstream_cache_capacity is too low for LC3plus frame size\n" );
@@ -618,11 +751,18 @@ static ivas_error isar_LC3PLUS_DEC_Decode_or_Conceal_internal(
/* log that this instance has skipped a frame and must decode twice once reactivated */
handle->selective_decoding_states[iDec]->has_skipped_a_frame = 1;
break;
+#endif
}
case DEC_ACTION_NUM_ENUMS:
default:
return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "invalid LC3plus decoder state\n" );
}
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ } /* for each media time */
+ /* reset skipping state, must be set by the user before each decode call*/
+ handle->selective_decoding_states[iDec]->frame_action = DEC_ACTION_DECODE_AND_USE;
+ } /* for each dec/channel */
+#else
bitstream_in_iter += bitstreamOffsetPerCoder;
}
@@ -634,6 +774,7 @@ static ivas_error isar_LC3PLUS_DEC_Decode_or_Conceal_internal(
}
}
+#endif
return IVAS_ERR_OK;
}
diff --git a/lib_isar/isar_lc3plus_dec.h b/lib_isar/isar_lc3plus_dec.h
index 576c576959328c36b2f1beede10fa350a8b7f8d4..91af70cef2ef3f192883d2c72c462cd3d29fe451 100644
--- a/lib_isar/isar_lc3plus_dec.h
+++ b/lib_isar/isar_lc3plus_dec.h
@@ -44,9 +44,13 @@
typedef enum
{
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
DEC_ACTION_DECODE_AND_DROP = 0,
+#endif
DEC_ACTION_DECODE_AND_USE,
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
DEC_ACTION_SKIP,
+#endif
DEC_ACTION_CACHE,
DEC_ACTION_NUM_ENUMS
} SelectiveDecAction;
@@ -56,8 +60,13 @@ typedef struct ISAR_LC3PLUS_DEC_SELECTIVE_DECODING_STATE
{
/*! indicates that the decoder has skipped one or more frames. This means it must decode two frames to flush algorithmic delay when re-activated */
int16_t has_skipped_a_frame;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ /*! action to execute for the next frame */
+ SelectiveDecAction frame_action;
+#else
/*! if set to 1, decoder will skip decoding for the next frame */
SelectiveDecAction *frame_actions;
+#endif
/*! if set to 1, decoder will decode the cache before decoding any of current frames */
int16_t shall_decode_cached_frame;
} ISAR_LC3PLUS_DEC_SELECTIVE_DECODING_STATE;
@@ -94,11 +103,13 @@ void ISAR_LC3PLUS_DEC_Close(
ISAR_LC3PLUS_DEC_HANDLE *handle /* i/o: pointer to decoder handle */
);
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
/*! Sets a matrix[MAX_PARAM_SPATIAL_SUBFRAMES][numLC3plusDecoders] where all require subframes must be flagged with 1, frames that are not required with 0 */
ivas_error ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix(
ISAR_LC3PLUS_DEC_HANDLE handle, /* i : decoder handle */
int16_t *subframeChannelMatrix[MAX_PARAM_SPATIAL_SUBFRAMES] /* i : */
);
+#endif
ivas_error ISAR_LC3PLUS_DEC_Decode(
ISAR_LC3PLUS_DEC_HANDLE handle, /* i : decoder handle */
@@ -112,10 +123,13 @@ ivas_error ISAR_LC3PLUS_DEC_Conceal(
float **pcm_out /* o : concealed samples */
);
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
ivas_error ISAR_LC3PLUS_DEC_AllocateSubframeDecodingMatrix(
int16_t ***subframeChannelMatrix,
const uint32_t num_decs );
+void ISAR_LC3PLUS_DEC_FreeSubframeDecodingMatrix( int16_t **subframeChannelMatrix );
#endif
-#endif /* IVAS_LC3PLUS_DEC_H */
+#endif /* SPLIT_REND_WITH_HEAD_ROT */
+#endif /* ISAR_LC3PLUS_DEC_H */
diff --git a/lib_isar/isar_lc3plus_enc.c b/lib_isar/isar_lc3plus_enc.c
index 4de75cc5265081fc2bf53a45c21df7f7c705556c..da2c1d48f047b8ecbe725b6d2e53430598d07f74 100644
--- a/lib_isar/isar_lc3plus_enc.c
+++ b/lib_isar/isar_lc3plus_enc.c
@@ -36,6 +36,50 @@
#include "ivas_error_utils.h"
#include "prot.h"
#include "wmc_auto.h"
+#include "options.h"
+
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+static const LC3PLUS_RTP_FDL s_fdl_request = LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA;
+#endif
+
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+static int32_t limit_per_channel_bitrate( LC3PLUS_CONFIG config,
+ int32_t per_channel_bitrate )
+{
+ if ( config.high_res_mode_enabled )
+ {
+ switch ( config.lc3plus_frame_duration_us )
+ {
+ case 10000:
+ return min( per_channel_bitrate, 500000 );
+ case 5000:
+ return min( per_channel_bitrate, 600000 );
+ case 2500:
+ return min( per_channel_bitrate, 672000 );
+ default:
+ assert( false && "unreachable" );
+ }
+ }
+
+ switch ( config.samplerate )
+ {
+ case 48000:
+ case 32000:
+ return min( per_channel_bitrate, 320000 );
+ case 24000:
+ return min( per_channel_bitrate, 314400 );
+ case 16000:
+ return min( per_channel_bitrate, 221600 );
+ case 8000:
+ return min( per_channel_bitrate, 114400 );
+ default:
+ assert( false && "unreachable" );
+ }
+
+ assert( false && "unreachable" );
+ return -1;
+}
+#endif
#ifdef SPLIT_REND_WITH_HEAD_ROT
/*-------------------------------------------------------------------*
@@ -50,7 +94,19 @@ ivas_error ISAR_LC3PLUS_ENC_Open(
ISAR_LC3PLUS_ENC_HANDLE *handle /* o : encoder handle */
)
{
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ int32_t num_lc3plus_media_times_per_ivas_frame;
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ int32_t lc3plus_num_bytes_per_frame;
+#endif
+ bool is_last_media_time, is_last_channel;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ivas_error ivas_err;
+#endif
+#endif
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
int32_t bitsPerSecondPerChannel;
+#endif
int32_t encoder_size;
LC3PLUS_Error err;
int32_t lfeChans[1];
@@ -62,8 +118,19 @@ ivas_error ISAR_LC3PLUS_ENC_Open(
{
return IVAS_ERROR( IVAS_ERR_INTERNAL, "Invalid number of channels\n" );
}
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
bitsPerSecondPerChannel = bitsPerSecond / config.channels;
-
+#endif
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ if ( config.lc3plus_frame_duration_us != 2500 && config.lc3plus_frame_duration_us != 5000 && config.lc3plus_frame_duration_us != 10000 )
+ {
+ return IVAS_ERROR( IVAS_ERR_INTERNAL, "Invalid lc3plus_frame_duration_us\n" );
+ }
+ if ( config.isar_frame_duration_us != 20000 && config.isar_frame_duration_us != 10000 && config.isar_frame_duration_us != 5000 )
+ {
+ return IVAS_ERROR( IVAS_ERR_INTERNAL, "Invalid isar_frame_duration_us\n" );
+ }
+#endif
encoder_size = lc3plus_enc_get_size( config.samplerate, 1 );
if ( 0 == encoder_size )
{
@@ -74,6 +141,10 @@ ivas_error ISAR_LC3PLUS_ENC_Open(
{
return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" );
}
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ( *handle )->config = config;
+ ( *handle )->frame_type_descriptors = NULL;
+#endif
( *handle )->pcm_conversion_buffer = NULL;
( *handle )->num_encs = 0;
@@ -88,6 +159,17 @@ ivas_error ISAR_LC3PLUS_ENC_Open(
( *handle )->handles[i] = NULL;
}
( *handle )->num_encs = config.channels;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ num_lc3plus_media_times_per_ivas_frame = config.isar_frame_duration_us / config.lc3plus_frame_duration_us;
+ ( *handle )->fdl_request = s_fdl_request;
+ ( *handle )->num_ftds = config.channels * num_lc3plus_media_times_per_ivas_frame;
+ ( *handle )->frame_type_descriptors = malloc( ( *handle )->num_ftds * sizeof( LC3PLUS_RTP_FTD ) );
+ if ( NULL == ( *handle )->frame_type_descriptors )
+ {
+ ISAR_LC3PLUS_ENC_Close( handle );
+ return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus frame_type_descriptors\n" );
+ }
+#endif
for ( int32_t iCh = 0; iCh < config.channels; iCh++ )
{
@@ -97,7 +179,11 @@ ivas_error ISAR_LC3PLUS_ENC_Open(
return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus encoder\n" );
}
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ err = lc3plus_enc_init( ( *handle )->handles[iCh], config.samplerate, 1, config.high_res_mode_enabled, lfeChans );
+#else
err = lc3plus_enc_init( ( *handle )->handles[iCh], config.samplerate, 1, 0, lfeChans );
+#endif
if ( err != LC3PLUS_OK )
{
ISAR_LC3PLUS_ENC_Close( handle );
@@ -110,22 +196,25 @@ ivas_error ISAR_LC3PLUS_ENC_Open(
ISAR_LC3PLUS_ENC_Close( handle );
return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc_set_frame_dms failed\n" );
}
-
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
err = lc3plus_enc_set_bitrate( ( *handle )->handles[iCh], bitsPerSecondPerChannel );
if ( err != LC3PLUS_OK )
{
ISAR_LC3PLUS_ENC_Close( handle );
return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc_set_bitrate failed\n" );
}
+#endif
}
- if ( config.ivas_frame_duration_us < config.lc3plus_frame_duration_us || config.ivas_frame_duration_us % config.lc3plus_frame_duration_us != 0 )
+ if ( config.isar_frame_duration_us < config.lc3plus_frame_duration_us || config.isar_frame_duration_us % config.lc3plus_frame_duration_us != 0 )
{
ISAR_LC3PLUS_ENC_Close( handle );
return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "Current pcm_conversion_buffer sizing requires that lc3plus uses a shorter or equal frame duration than ivas\n" );
}
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
( *handle )->config = config;
+#endif
( *handle )->pcm_conversion_buffer = malloc( sizeof( int16_t ) * config.samplerate * config.lc3plus_frame_duration_us / 1000000 );
if ( NULL == ( *handle )->pcm_conversion_buffer )
{
@@ -133,8 +222,170 @@ ivas_error ISAR_LC3PLUS_ENC_Open(
return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus encoder wrapper pcm_conversion_buffer\n" );
}
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ /* update FDI fields */
+ for ( int32_t iMediaTime = 0; iMediaTime < num_lc3plus_media_times_per_ivas_frame; ++iMediaTime )
+ {
+ for ( uint32_t iEnc = 0; iEnc < ( *handle )->num_encs; ++iEnc )
+ {
+ int32_t ftd_index = iEnc + iMediaTime * ( *handle )->num_encs;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ( *handle )->frame_type_descriptors[ftd_index].frame_data_length = 0; /* will be set to the correct value in IVAS_LC3PLUS_ENC_SetBitrate */
+#else
+ lc3plus_num_bytes_per_frame = lc3plus_enc_get_num_bytes( ( *handle )->handles[iEnc] );
+ if ( lc3plus_num_bytes_per_frame <= 0 )
+ {
+ ISAR_LC3PLUS_ENC_Close( handle );
+ return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_enc_get_num_bytes reported invalid result failed\n" );
+ }
+ ( *handle )->frame_type_descriptors[ftd_index].frame_data_length = lc3plus_num_bytes_per_frame;
+#endif
+ if ( 0 != LC3PLUS_RTP_ftd_bwr_from_samplerate( &( *handle )->frame_type_descriptors[ftd_index].bwr, config.samplerate, config.high_res_mode_enabled ) )
+ {
+ ISAR_LC3PLUS_ENC_Close( handle );
+ return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_ftd_bwr_from_samplerate failed\n" );
+ }
+ if ( 0 != LC3PLUS_RTP_ftd_fdi_from_frame_duration_us( &( *handle )->frame_type_descriptors[ftd_index].fdi, config.lc3plus_frame_duration_us ) )
+ {
+ ISAR_LC3PLUS_ENC_Close( handle );
+ return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_ftd_fdi_from_frame_duration_us failed\n" );
+ }
+ ( *handle )->frame_type_descriptors[ftd_index].h = LC3PLUS_RTP_FTD_H_PRIMARY;
+ ( *handle )->frame_type_descriptors[ftd_index].frame_data = NULL;
+
+ /* The FTDs in the ToC are included in the following order:
+ * 1) First the FTD for the first channel of the first FDB (oldest frame)
+ * 2) Then the FTDs for the remaining channels for the first FDB in increasing CC order
+ * 3) Then the FTD for the first channel of the second FDB
+ * 4) Then the FTDs for the remaining channels for the second FDB
+ * 5) Etc. to the last FDB */
+ is_last_media_time = num_lc3plus_media_times_per_ivas_frame - 1 == iMediaTime;
+ is_last_channel = ( *handle )->num_encs - 1 == iEnc;
+ if ( is_last_media_time && is_last_channel )
+ {
+ ( *handle )->frame_type_descriptors[ftd_index].fc = LC3PLUS_RTP_FTD_FC_LAST_OVERALL;
+ }
+ else if ( !is_last_media_time && is_last_channel )
+ {
+ ( *handle )->frame_type_descriptors[ftd_index].fc = LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME;
+ }
+ else
+ {
+ ( *handle )->frame_type_descriptors[ftd_index].fc = LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL;
+ }
+ }
+ }
+
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ivas_err = IVAS_LC3PLUS_ENC_SetBitrate( *handle, bitsPerSecond );
+ if ( ivas_err != IVAS_ERR_OK )
+ {
+ ISAR_LC3PLUS_ENC_Close( handle );
+ return ivas_err;
+ }
+#endif
+#endif
+ return IVAS_ERR_OK;
+}
+
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+/*-------------------------------------------------------------------*
+ * Function IVAS_LC3PLUS_ENC_SetBitrate()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+ivas_error IVAS_LC3PLUS_ENC_SetBitrate(
+ ISAR_LC3PLUS_ENC_HANDLE handle, /* o : LC3plus encoder handle */
+ const uint32_t bitsPerSecond /* i : new target bit rate */
+)
+{
+ int32_t numLc3plusMediaTimesPerIvasFrame;
+ int32_t lc3plus_num_bytes_per_frame;
+ int32_t availableOctetsPerIsarFrame;
+ int32_t actualOctetsPerFrame;
+ LC3PLUS_Error err;
+ int32_t iFtd;
+ int32_t fdrLength;
+ int32_t lc3plusPacketRate;
+ int32_t numSubframes;
+ int32_t minPayloadOverhead;
+ int32_t targetLc3PlusBitratePerChannel;
+ int32_t targetLc3PlusOctetCount;
+ int32_t lc3plusFdlLength;
+
+ if ( NULL == handle )
+ {
+ return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3PLUS_Enc_Wrap_Handle is NULL\n" );
+ }
+
+ availableOctetsPerIsarFrame = bitsPerSecond / ( 1000000 / handle->config.isar_frame_duration_us ) / 8;
+ lc3plusPacketRate = 1000 * 1000 / handle->config.lc3plus_frame_duration_us;
+ numLc3plusMediaTimesPerIvasFrame = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us;
+ numSubframes = numLc3plusMediaTimesPerIvasFrame * handle->config.channels;
+
+ /* subtract minimum required payload bytes & calculate a first per-channel target bit rate */
+ if ( LC3PLUS_RTP_frame_data_length_get_size( &fdrLength, s_fdl_request ) != LC3PLUS_RTP_ERR_NO_ERROR )
+ {
+ return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_frame_data_length_get_size failed\n" );
+ }
+ minPayloadOverhead = fdrLength + ( numSubframes * LC3PLUS_RTP_FTD_MIN_SIZE );
+ targetLc3PlusBitratePerChannel = ( availableOctetsPerIsarFrame - minPayloadOverhead ) / handle->config.channels * 8 * lc3plusPacketRate / numLc3plusMediaTimesPerIvasFrame;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ if ( targetLc3PlusBitratePerChannel <= 0 )
+ {
+ return IVAS_ERROR( IVAS_ERR_LC3PLUS_INVALID_BITRATE, "available LC3plus bitrate <= 0\n" );
+ }
+#endif
+ targetLc3PlusBitratePerChannel = limit_per_channel_bitrate( handle->config, targetLc3PlusBitratePerChannel );
+ targetLc3PlusOctetCount = targetLc3PlusBitratePerChannel / 8 / lc3plusPacketRate;
+ /* check resulting octet count. If it requires larger than 1-byte length fields, decrease the bitrate by enough to make room for the additional length field */
+ if ( LC3PLUS_RTP_frame_data_length_get_size( &lc3plusFdlLength, targetLc3PlusOctetCount ) != LC3PLUS_RTP_ERR_NO_ERROR )
+ {
+ return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_frame_data_length_get_size failed\n" );
+ }
+ if ( lc3plusFdlLength != LC3PLUS_RTP_FDL_MIN_LENGTH )
+ {
+ /* reduce bitrate to allow for the required fdl field */
+ targetLc3PlusBitratePerChannel = ( targetLc3PlusOctetCount - ( lc3plusFdlLength - LC3PLUS_RTP_FDL_MIN_LENGTH ) ) / handle->config.channels * 8 * lc3plusPacketRate;
+ }
+
+ for ( int32_t iCh = 0; iCh < handle->config.channels; iCh++ )
+ {
+ err = lc3plus_enc_set_bitrate( handle->handles[iCh], targetLc3PlusBitratePerChannel );
+ if ( err != LC3PLUS_OK )
+ {
+ return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc_set_bitrate failed\n" );
+ }
+ }
+
+ // update FTD settings after bitrate change
+ for ( int32_t iMediaTime = 0; iMediaTime < numLc3plusMediaTimesPerIvasFrame; ++iMediaTime )
+ {
+ for ( uint32_t iEnc = 0; iEnc < handle->num_encs; ++iEnc )
+ {
+ iFtd = iEnc + iMediaTime * handle->num_encs;
+ lc3plus_num_bytes_per_frame = lc3plus_enc_get_num_bytes( handle->handles[iEnc] );
+ if ( lc3plus_num_bytes_per_frame <= 0 )
+ {
+ return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_enc_get_num_bytes reported invalid result failed\n" );
+ }
+ handle->frame_type_descriptors[iFtd].frame_data_length = lc3plus_num_bytes_per_frame;
+ }
+ }
+
+ // TODO: remove sanity checks?
+ if ( ISAR_LC3PLUS_ENC_GetOutputBitstreamSize( handle, &actualOctetsPerFrame ) != IVAS_ERR_OK )
+ {
+ return IVAS_ERROR( IVAS_ERR_INTERNAL, "ISAR_LC3PLUS_ENC_GetOutputBitstreamSize failed\n" );
+ }
+ if ( actualOctetsPerFrame > availableOctetsPerIsarFrame )
+ {
+ return IVAS_ERROR( IVAS_ERR_INTERNAL, "Bitrate reduction logic failed\n" );
+ }
return IVAS_ERR_OK;
}
+#endif
/*-------------------------------------------------------------------*
@@ -191,7 +442,15 @@ ivas_error ISAR_LC3PLUS_ENC_GetOutputBitstreamSize(
int32_t *bsSize /* o : size of each bitstream frame in bytes */
)
{
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ LC3PLUS_RTP_ERR rtp_err;
+ int32_t num_lc3plus_media_times_per_ivas_frame;
+ int32_t iMediaTime;
+ int32_t ftd_frame_data_length_size, lc3plus_frame_data_length;
+ int32_t ftd_index;
+#else
int32_t bitstreamSizeMultiplier;
+#endif
if ( NULL == handle )
{
return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3PLUS_Enc_Wrap_Handle is NULL\n" );
@@ -201,23 +460,65 @@ ivas_error ISAR_LC3PLUS_ENC_GetOutputBitstreamSize(
return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "bsSize is NULL\n" );
}
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ if ( 0 == handle->config.lc3plus_frame_duration_us )
+ {
+ return IVAS_ERROR( IVAS_ERR_INIT_ERROR, "lc3plus_frame_duration_us is 0\n" );
+ }
+ if ( handle->config.isar_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 )
+ {
+ return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "isar_frame_duration_us must be equal or multiple of lc3plus_frame_duration_us \n" );
+ }
+
+ num_lc3plus_media_times_per_ivas_frame = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us;
+#endif
*bsSize = 0;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ int32_t fdl_request_length;
+ rtp_err = LC3PLUS_RTP_frame_data_length_get_size( &fdl_request_length, handle->fdl_request );
+ if ( rtp_err != LC3PLUS_RTP_ERR_NO_ERROR )
+ {
+ return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Invalid LC3plus frame_data_length request\n" );
+ }
+ *bsSize += fdl_request_length;
+#endif
for ( uint32_t iEnc = 0; iEnc < handle->num_encs; iEnc++ )
{
if ( NULL == handle->handles[iEnc] )
{
return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3plus encoder handle is NULL\n" );
}
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ lc3plus_frame_data_length = lc3plus_enc_get_num_bytes( handle->handles[iEnc] );
+ for ( iMediaTime = 0; iMediaTime < num_lc3plus_media_times_per_ivas_frame; ++iMediaTime )
+ {
+ ftd_index = iEnc + iMediaTime * handle->num_encs;
+ if ( lc3plus_frame_data_length != (int32_t) handle->frame_type_descriptors[ftd_index].frame_data_length )
+ {
+ return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "LC3plus FTD data not synchronised with encoder bitrate\n" );
+ }
+ rtp_err = LC3PLUS_RTP_frame_data_length_get_size( &ftd_frame_data_length_size, handle->frame_type_descriptors[ftd_index].frame_data_length );
+ if ( rtp_err != LC3PLUS_RTP_ERR_NO_ERROR )
+ {
+ return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Invalid LC3plus frame_data_length\n" );
+ }
+ *bsSize += LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL;
+ *bsSize += handle->frame_type_descriptors[ftd_index].frame_data_length;
+ *bsSize += ftd_frame_data_length_size;
+ }
+ }
+#else
*bsSize += lc3plus_enc_get_num_bytes( handle->handles[iEnc] );
}
- if ( handle->config.ivas_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 )
+ if ( handle->config.isar_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 )
{
- return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "ivas_frame_duration_us must be equal or multiple of lc3plus_frame_duration_us \n" );
+ return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "isar_frame_duration_us must be equal or multiple of lc3plus_frame_duration_us \n" );
}
- bitstreamSizeMultiplier = handle->config.ivas_frame_duration_us / handle->config.lc3plus_frame_duration_us;
+ bitstreamSizeMultiplier = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us;
*bsSize *= bitstreamSizeMultiplier;
+#endif
return IVAS_ERR_OK;
}
@@ -237,6 +538,12 @@ void ISAR_LC3PLUS_ENC_Close(
{
return;
}
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ if ( NULL != ( *handle )->frame_type_descriptors )
+ {
+ free( ( *handle )->frame_type_descriptors );
+ }
+#endif
for ( uint32_t iEnc = 0; iEnc < ( *handle )->num_encs; iEnc++ )
{
if ( NULL != ( *handle )->handles[iEnc] )
@@ -268,17 +575,28 @@ void ISAR_LC3PLUS_ENC_Close(
ivas_error ISAR_LC3PLUS_ENC_Encode(
ISAR_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */
float **pcm_in, /* i : pointer input samples */
- void *bitstream_out /* o : pointer to bitstream frame */
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ void *bitstream_out, /* o : pointer to bitstream frame */
+ const int32_t bitstream_out_size /* i : size of the bitstream_out buffer in bytes. Must be equal to ISAR_LC3PLUS_ENC_GetOutputBitstreamSize. */
+#else
+ void *bitstream_out /* o : pointer to bitstream frame */
+#endif
)
{
- uint32_t numSamplesPerLC3plusChannel;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ int32_t ftdIndex;
+ LC3PLUS_RTP_ERR rtpErr;
+ uint32_t num_media_times;
+#else
uint32_t lc3framesPerIvasFrame;
- int32_t ivasSampleIndex;
uint8_t *bitstream_out_iter = bitstream_out;
+#endif
+ uint32_t numSamplesPerLC3plusChannel;
+ int32_t ivasSampleIndex;
int32_t num_bytes = 0;
LC3PLUS_Error err;
- push_wmops( "IVAS_LC3PLUS_ENC_Encode" );
+ push_wmops( "ISAR_LC3PLUS_ENC_Encode" );
if ( NULL == handle )
{
@@ -293,26 +611,53 @@ ivas_error ISAR_LC3PLUS_ENC_Encode(
return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "bitstream_out is NULL\n" );
}
- if ( handle->config.ivas_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 )
+ if ( handle->config.isar_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 )
{
- return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "ivas_frame_duration_us must be equal or multiple of lc3plus_frame_duration_us \n" );
+ return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "isar_frame_duration_us must be equal or multiple of lc3plus_frame_duration_us \n" );
}
- lc3framesPerIvasFrame = handle->config.ivas_frame_duration_us / handle->config.lc3plus_frame_duration_us;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ num_media_times = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us;
+ numSamplesPerLC3plusChannel = handle->config.samplerate / ( 1000000 / handle->config.isar_frame_duration_us ) / num_media_times;
- numSamplesPerLC3plusChannel = handle->config.samplerate / ( 1000000 / handle->config.ivas_frame_duration_us ) / lc3framesPerIvasFrame;
+ size_t actual_size;
+ rtpErr = LC3PLUS_RTP_payload_serialize( bitstream_out, bitstream_out_size, &actual_size, s_fdl_request, handle->frame_type_descriptors, handle->num_ftds );
+ if ( rtpErr != LC3PLUS_RTP_ERR_NO_ERROR )
+ {
+ return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( rtpErr ), "LC3PLUS_RTP_payload_serialize failed\n" );
+ }
+#else
+ lc3framesPerIvasFrame = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us;
+
+ numSamplesPerLC3plusChannel = handle->config.samplerate / ( 1000000 / handle->config.isar_frame_duration_us ) / lc3framesPerIvasFrame;
+#endif
for ( uint32_t iEnc = 0; iEnc < handle->num_encs; iEnc++ )
{
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ for ( uint32_t iMediaTime = 0; iMediaTime < num_media_times; iMediaTime++ )
+#else
for ( uint32_t iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
+#endif
{
for ( uint32_t iSampleInt16 = 0; iSampleInt16 < numSamplesPerLC3plusChannel; iSampleInt16++ )
{
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ivasSampleIndex = iSampleInt16 + iMediaTime * numSamplesPerLC3plusChannel;
+#else
ivasSampleIndex = iSampleInt16 + iLc3plusFrame * numSamplesPerLC3plusChannel;
+#endif
handle->pcm_conversion_buffer[iSampleInt16] = (int16_t) max( INT16_MIN, min( pcm_in[iEnc][ivasSampleIndex], INT16_MAX ) );
}
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ftdIndex = iMediaTime * handle->num_encs + iEnc;
+#endif
num_bytes = 0;
push_wmops( "lc3plus_enc16" );
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ err = lc3plus_enc16( handle->handles[iEnc], &handle->pcm_conversion_buffer, handle->frame_type_descriptors[ftdIndex].frame_data, &num_bytes, NULL );
+#else
err = lc3plus_enc16( handle->handles[iEnc], &handle->pcm_conversion_buffer, bitstream_out_iter, &num_bytes, NULL );
+#endif
pop_wmops();
if ( err != LC3PLUS_OK )
{
@@ -322,8 +667,15 @@ ivas_error ISAR_LC3PLUS_ENC_Encode(
{
return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_enc16 did not produce output\n" );
}
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ if ( num_bytes != (int32_t) handle->frame_type_descriptors[ftdIndex].frame_data_length )
+ {
+ return IVAS_ERROR( IVAS_ERR_INTERNAL, "payload format and lc3plus enc bitrate are not aligned\n" );
+ }
+#else
bitstream_out_iter += num_bytes;
+#endif
}
}
diff --git a/lib_isar/isar_lc3plus_enc.h b/lib_isar/isar_lc3plus_enc.h
index 1a9f467b5f2f09fe8a83417ad0100dc55e3a1980..3a2dffe63ab3c7f58401fa7903735a8afc5aeaa4 100644
--- a/lib_isar/isar_lc3plus_enc.h
+++ b/lib_isar/isar_lc3plus_enc.h
@@ -38,6 +38,9 @@
#ifdef SPLIT_REND_WITH_HEAD_ROT
#include "lc3.h"
#include "isar_lc3plus_common.h"
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+#include "isar_lc3plus_payload.h"
+#endif
/* encoder wrapper */
typedef struct ISAR_LC3PLUS_ENC_HANDLE
@@ -46,14 +49,30 @@ typedef struct ISAR_LC3PLUS_ENC_HANDLE
LC3PLUS_Enc **handles;
uint32_t num_encs;
int16_t *pcm_conversion_buffer;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ LC3PLUS_RTP_FTD *frame_type_descriptors;
+ int32_t num_ftds;
+ LC3PLUS_RTP_FDL fdl_request;
+#endif
} * ISAR_LC3PLUS_ENC_HANDLE;
ivas_error ISAR_LC3PLUS_ENC_Open(
- const LC3PLUS_CONFIG config, /* i : encoder configuration */
- const uint32_t bitsPerSecond, /* i : bit rate */
+ const LC3PLUS_CONFIG config, /* i : encoder configuration */
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ const uint32_t initialBitsPerSecond, /* i : initial target bit rate */
+#else
+ const uint32_t bitsPerSecond, /* i : bit rate */
+#endif
ISAR_LC3PLUS_ENC_HANDLE *handle /* o : LC3plus encoder handle */
);
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ivas_error IVAS_LC3PLUS_ENC_SetBitrate(
+ ISAR_LC3PLUS_ENC_HANDLE handle, /* o : LC3plus encoder handle */
+ const uint32_t bitsPerSecond /* i : new target bit rate */
+);
+#endif
+
ivas_error ISAR_LC3PLUS_ENC_GetDelay(
ISAR_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */
int32_t *delayInSamples /* o : algorithmic delay of encoding and decoding in number of samples per channel */
@@ -61,7 +80,7 @@ ivas_error ISAR_LC3PLUS_ENC_GetDelay(
ivas_error ISAR_LC3PLUS_ENC_GetOutputBitstreamSize(
ISAR_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */
- int32_t *bsSize /* o : size of each bitstream frame in bytes */
+ int32_t *bsSize /* o : size of next bitstream frame in bytes */
);
void ISAR_LC3PLUS_ENC_Close(
@@ -71,7 +90,12 @@ void ISAR_LC3PLUS_ENC_Close(
ivas_error ISAR_LC3PLUS_ENC_Encode(
ISAR_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */
float **pcm_in, /* i : pointer input samples */
- void *bitstream_out /* o : pointer to bitstream frame */
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ void *bitstream_out, /* o : pointer to bitstream frame */
+ const int32_t bitstream_out_size /* i : size of the bitstream_out buffer in bytes. Must be equal to ISAR_LC3PLUS_ENC_GetOutputBitstreamSize. */
+#else
+ void *bitstream_out /* o : pointer to bitstream frame */
+#endif
);
#endif
diff --git a/lib_isar/isar_lc3plus_payload.c b/lib_isar/isar_lc3plus_payload.c
new file mode 100644
index 0000000000000000000000000000000000000000..b240897655ab4da7c58f7ffbc602c9adb0eefff5
--- /dev/null
+++ b/lib_isar/isar_lc3plus_payload.c
@@ -0,0 +1,823 @@
+/******************************************************************************************************
+
+ (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository. All Rights Reserved.
+
+ This software is protected by copyright law and by international treaties.
+ The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository retain full ownership rights in their respective contributions in
+ the software. This notice grants no license of any kind, including but not limited to patent
+ license, nor is any license granted by implication, estoppel or otherwise.
+
+ Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
+ contributions.
+
+ This software is provided "AS IS", without any express or implied warranties. The software is in the
+ development stage. It is intended exclusively for experts who have experience with such software and
+ solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
+ and fitness for a particular purpose are hereby disclaimed and excluded.
+
+ Any dispute, controversy or claim arising under or in relation to providing this software shall be
+ submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
+ accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
+ the United Nations Convention on Contracts on the International Sales of Goods.
+
+*******************************************************************************************************/
+
+#include
+#include
+#include
+#include "isar_lc3plus_payload.h"
+#include "options.h"
+
+#ifdef SPLIT_REND_WITH_HEAD_ROT
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+static LC3PLUS_RTP_ERR s_frame_duration_ms_from_fdi( int32_t *frame_duration_us, const LC3PLUS_RTP_FTD_FDI fdi )
+{
+ if ( NULL == frame_duration_us )
+ {
+ return LC3PLUS_RTP_ERR_NULL_PTR;
+ }
+ switch ( fdi )
+ {
+ case LC3PLUS_RTP_FTD_FDI_2500_US:
+ *frame_duration_us = 2500;
+ break;
+ case LC3PLUS_RTP_FTD_FDI_5000_US:
+ *frame_duration_us = 5000;
+ break;
+ case LC3PLUS_RTP_FTD_FDI_10000_US:
+ *frame_duration_us = 10000;
+ break;
+ case LC3PLUS_RTP_FTD_FDI_RESERVED:
+ default:
+ return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
+ }
+ return LC3PLUS_RTP_ERR_NO_ERROR;
+}
+
+static LC3PLUS_RTP_ERR s_sampling_rate_hz_from_bwr( int32_t *sample_rate_hz, const LC3PLUS_RTP_FTD_BWR bwr )
+{
+ if ( NULL == sample_rate_hz )
+ {
+ return LC3PLUS_RTP_ERR_NULL_PTR;
+ }
+ switch ( bwr )
+ {
+ case LC3PLUS_RTP_FTD_BWR_NB:
+ *sample_rate_hz = 8000;
+ break;
+ case LC3PLUS_RTP_FTD_BWR_WB:
+ *sample_rate_hz = 16000;
+ break;
+ case LC3PLUS_RTP_FTD_BWR_SSWB:
+ *sample_rate_hz = 24000;
+ break;
+ case LC3PLUS_RTP_FTD_BWR_SWB:
+ *sample_rate_hz = 32000;
+ break;
+ case LC3PLUS_RTP_FTD_BWR_FBCD:
+ *sample_rate_hz = 44100;
+ break;
+ case LC3PLUS_RTP_FTD_BWR_FB:
+ *sample_rate_hz = 48000;
+ break;
+ case LC3PLUS_RTP_FTD_BWR_FBHR:
+ *sample_rate_hz = 48000;
+ break;
+ case LC3PLUS_RTP_FTD_BWR_UBHR:
+ *sample_rate_hz = 96000;
+ break;
+ default:
+ return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
+ }
+ return LC3PLUS_RTP_ERR_NO_ERROR;
+}
+
+static LC3PLUS_RTP_ERR s_high_resolution_flag_from_bwr( int16_t *high_resolution_flag, const LC3PLUS_RTP_FTD_BWR bwr )
+{
+ if ( NULL == high_resolution_flag )
+ {
+ return LC3PLUS_RTP_ERR_NULL_PTR;
+ }
+ switch ( bwr )
+ {
+ case LC3PLUS_RTP_FTD_BWR_NB:
+ *high_resolution_flag = 0;
+ break;
+ case LC3PLUS_RTP_FTD_BWR_WB:
+ *high_resolution_flag = 0;
+ break;
+ case LC3PLUS_RTP_FTD_BWR_SSWB:
+ *high_resolution_flag = 0;
+ break;
+ case LC3PLUS_RTP_FTD_BWR_SWB:
+ *high_resolution_flag = 0;
+ break;
+ case LC3PLUS_RTP_FTD_BWR_FBCD:
+ *high_resolution_flag = 0;
+ break;
+ case LC3PLUS_RTP_FTD_BWR_FB:
+ *high_resolution_flag = 0;
+ break;
+ case LC3PLUS_RTP_FTD_BWR_FBHR:
+ *high_resolution_flag = 1;
+ break;
+ case LC3PLUS_RTP_FTD_BWR_UBHR:
+ *high_resolution_flag = 1;
+ break;
+ default:
+ return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
+ }
+ return LC3PLUS_RTP_ERR_NO_ERROR;
+}
+
+LC3PLUS_RTP_ERR LC3PLUS_RTP_frame_data_length_get_size( int32_t *length, const LC3PLUS_RTP_FDL frameDataLengthValue )
+{
+ if ( frameDataLengthValue == LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA || frameDataLengthValue == LC3PLUS_RTP_FDL_SPEECH_BAD || frameDataLengthValue == LC3PLUS_RTP_FDL_SPEECH_SID )
+ {
+ *length = 1;
+ }
+ else if ( frameDataLengthValue >= LC3PLUS_RTP_FDL_LENGTH_1_MIN && frameDataLengthValue <= LC3PLUS_RTP_FDL_LENGTH_1_MAX )
+ {
+ *length = 1;
+ }
+ else if ( frameDataLengthValue >= LC3PLUS_RTP_FDL_LENGTH_2_MIN && frameDataLengthValue <= LC3PLUS_RTP_FDL_LENGTH_2_MAX )
+ {
+ *length = 2;
+ }
+ else if ( frameDataLengthValue >= LC3PLUS_RTP_FDL_LENGTH_3_MIN && frameDataLengthValue <= LC3PLUS_RTP_FDL_LENGTH_3_MAX )
+ {
+ *length = 3;
+ }
+ else
+ {
+ return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
+ }
+ return LC3PLUS_RTP_ERR_NO_ERROR;
+}
+
+static LC3PLUS_RTP_ERR s_frame_data_length_pack( const LC3PLUS_RTP_FDL frameDataLengthValue, uint8_t *dst )
+{
+ int32_t frame_data_length_size;
+ LC3PLUS_RTP_ERR err;
+
+ if ( NULL == dst )
+ {
+ return LC3PLUS_RTP_ERR_NULL_PTR;
+ }
+
+ err = LC3PLUS_RTP_frame_data_length_get_size( &frame_data_length_size, frameDataLengthValue );
+ if ( err != LC3PLUS_RTP_ERR_NO_ERROR )
+ {
+ return err;
+ }
+ if ( 1 == frame_data_length_size )
+ {
+ *dst++ = frameDataLengthValue >> 0 & LC3PLUS_RTP_FDL_EXTENSION_VALUE;
+ }
+ else if ( 2 == frame_data_length_size )
+ {
+ const int32_t frameDataLengthValueToWrite = frameDataLengthValue - LC3PLUS_RTP_FDL_EXTENSION_VALUE;
+ *dst++ = LC3PLUS_RTP_FDL_EXTENSION_VALUE;
+ *dst = frameDataLengthValueToWrite >> 0 & LC3PLUS_RTP_FDL_EXTENSION_VALUE;
+ }
+ else if ( 3 == frame_data_length_size )
+ {
+ const int32_t frameDataLengthValueToWrite = frameDataLengthValue - ( 2 * LC3PLUS_RTP_FDL_EXTENSION_VALUE );
+ *dst++ = LC3PLUS_RTP_FDL_EXTENSION_VALUE;
+ *dst++ = LC3PLUS_RTP_FDL_EXTENSION_VALUE;
+ *dst = frameDataLengthValueToWrite >> 0 & LC3PLUS_RTP_FDL_EXTENSION_VALUE;
+ }
+ return LC3PLUS_RTP_ERR_NO_ERROR;
+}
+
+static int32_t s_get_size_from_fdl( const LC3PLUS_RTP_FDL fdl )
+{
+ if ( fdl >= LC3PLUS_RTP_FDL_LENGTH_1_MIN && fdl <= LC3PLUS_RTP_FDL_LENGTH_3_MAX )
+ {
+ return fdl;
+ }
+ return 0;
+}
+
+static bool s_fdl_is_magic_value( const LC3PLUS_RTP_FDL fdl )
+{
+ if ( fdl == LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA || fdl == LC3PLUS_RTP_FDL_SPEECH_SID || fdl == LC3PLUS_RTP_FDL_SPEECH_BAD )
+ {
+ return true;
+ }
+ return false;
+}
+
+static bool s_fdl_value_is_valid_request( const LC3PLUS_RTP_FDL fdl_request )
+{
+ /* LC3PLUS_RTP_FDL_SPEECH_SID && LC3PLUS_RTP_FDL_SPEECH_SID are not valid values for the FDL request */
+ if ( fdl_request == LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA || ( fdl_request >= LC3PLUS_RTP_FDL_LENGTH_1_MIN && fdl_request <= LC3PLUS_RTP_FDL_LENGTH_3_MAX ) )
+ {
+ return true;
+ }
+ return false;
+}
+
+static LC3PLUS_RTP_ERR s_frame_data_length_parse( LC3PLUS_RTP_FDL *frame_data_length_value, const uint8_t *src, const size_t remaining_capacity )
+{
+ int32_t frame_data_length_size;
+ LC3PLUS_RTP_ERR err;
+ if ( NULL == src || NULL == frame_data_length_value || remaining_capacity < 1 )
+ {
+ return LC3PLUS_RTP_ERR_NULL_PTR;
+ }
+
+ if ( remaining_capacity > 2 && LC3PLUS_RTP_FDL_EXTENSION_VALUE == *src && LC3PLUS_RTP_FDL_EXTENSION_VALUE == *( src + 1 ) )
+ {
+ *frame_data_length_value = *( src + 2 ) + 2 * LC3PLUS_RTP_FDL_EXTENSION_VALUE;
+ }
+ else if ( remaining_capacity > 1 && LC3PLUS_RTP_FDL_EXTENSION_VALUE == *src )
+ {
+ *frame_data_length_value = *( src + 1 ) + 1 * LC3PLUS_RTP_FDL_EXTENSION_VALUE;
+ }
+ else if ( remaining_capacity > 0 )
+ {
+ *frame_data_length_value = *src << 0;
+ }
+ else
+ {
+ return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
+ }
+
+ /* sanity check */
+ err = LC3PLUS_RTP_frame_data_length_get_size( &frame_data_length_size, *frame_data_length_value );
+ if ( err != LC3PLUS_RTP_ERR_NO_ERROR )
+ {
+ return err;
+ }
+ return LC3PLUS_RTP_ERR_NO_ERROR;
+}
+
+static LC3PLUS_RTP_ERR s_parse_ftd( const uint8_t *p_read, LC3PLUS_RTP_FTD *receiver_ftd, int32_t *num_bytes_read, const size_t remaining_capacity )
+{
+ int32_t frame_data_block_size;
+ LC3PLUS_RTP_FDL fdl;
+ LC3PLUS_RTP_ERR err;
+ if ( NULL == p_read || NULL == receiver_ftd || NULL == num_bytes_read || remaining_capacity < LC3PLUS_RTP_FTD_MIN_SIZE )
+ {
+ return LC3PLUS_RTP_ERR_NULL_PTR;
+ }
+
+ *num_bytes_read = 0;
+ receiver_ftd->fc = 0;
+ receiver_ftd->fdi = 0;
+ receiver_ftd->bwr = 0;
+ receiver_ftd->h = 0;
+ receiver_ftd->fc |= *p_read & LC3PLUS_RTP_FTD_FC_MASK;
+ receiver_ftd->fdi |= ( *p_read & LC3PLUS_RTP_FTD_FDI_MASK );
+ receiver_ftd->bwr |= ( *p_read & LC3PLUS_RTP_FTD_BWR_MASK );
+ receiver_ftd->h |= ( *p_read & LC3PLUS_RTP_FTD_H_MASK );
+ p_read++;
+ *num_bytes_read = 1;
+
+ err = s_frame_data_length_parse( &fdl, p_read, remaining_capacity - *num_bytes_read );
+ if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
+ {
+ return err;
+ }
+ frame_data_block_size = s_get_size_from_fdl( fdl );
+
+ receiver_ftd->frame_data_length = frame_data_block_size;
+ int32_t length_field_size;
+ err = LC3PLUS_RTP_frame_data_length_get_size( &length_field_size, receiver_ftd->frame_data_length );
+ if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
+ {
+ return err;
+ }
+ *num_bytes_read += length_field_size;
+ return LC3PLUS_RTP_ERR_NO_ERROR;
+}
+
+LC3PLUS_RTP_ERR LC3PLUS_RTP_payload_serialize(
+ uint8_t *serialized_buffer,
+ const size_t serialized_buffer_capacity,
+ size_t *packed_buffer_actual_size,
+ const LC3PLUS_RTP_FDL fdl_request,
+ LC3PLUS_RTP_FTD *sender_ftds,
+ const size_t sender_ftds_num )
+{
+ LC3PLUS_RTP_ERR err;
+ uint8_t *p_write = serialized_buffer;
+ uint32_t i;
+ int32_t bytes_written = 0;
+ int32_t lc3plus_frame_size_sum;
+ uint8_t *p_frame_data;
+ int32_t fdl_request_length;
+
+ if ( NULL == serialized_buffer || NULL == packed_buffer_actual_size || NULL == sender_ftds )
+ {
+ return LC3PLUS_RTP_ERR_NULL_PTR;
+ }
+
+ *packed_buffer_actual_size = 0;
+ err = LC3PLUS_RTP_frame_data_length_get_size( &fdl_request_length, fdl_request );
+ if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
+ {
+ return err;
+ }
+ if ( !s_fdl_value_is_valid_request( fdl_request ) )
+ {
+ return LC3PLUS_RTP_ERR_INVALID_FDL_REQUEST;
+ }
+ if ( (int32_t) serialized_buffer_capacity < bytes_written + fdl_request_length )
+ {
+ return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
+ }
+ err = s_frame_data_length_pack( fdl_request, p_write );
+ if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
+ {
+ return err;
+ }
+ bytes_written += fdl_request_length;
+ p_write += bytes_written;
+
+ for ( i = 0; i < sender_ftds_num; ++i )
+ {
+ /* only the last ftd may have the LC3PLUS_RTP_FTD_FC_LAST_OVERALL value */
+ if ( sender_ftds[i].fc == LC3PLUS_RTP_FTD_FC_LAST_OVERALL && i != ( sender_ftds_num - 1 ) )
+ {
+ return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
+ }
+ /* the last ftd must have the LC3PLUS_RTP_FTD_FC_LAST_OVERALL value */
+ if ( sender_ftds[i].fc != LC3PLUS_RTP_FTD_FC_LAST_OVERALL && i == ( sender_ftds_num - 1 ) )
+ {
+ return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
+ }
+ if ( (int32_t) serialized_buffer_capacity < bytes_written + LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL )
+ {
+ return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
+ }
+ *p_write = 0x00;
+ *p_write |= LC3PLUS_RTP_FTD_FC_MASK & (uint8_t) sender_ftds[i].fc;
+ *p_write |= LC3PLUS_RTP_FTD_FDI_MASK & (uint8_t) sender_ftds[i].fdi;
+ *p_write |= LC3PLUS_RTP_FTD_BWR_MASK & (uint8_t) sender_ftds[i].bwr;
+ *p_write |= LC3PLUS_RTP_FTD_H_MASK & (uint8_t) sender_ftds[i].h;
+ p_write++;
+ bytes_written += LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL;
+
+ int32_t fdl_length;
+ err = LC3PLUS_RTP_frame_data_length_get_size( &fdl_length, sender_ftds[i].frame_data_length );
+ if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
+ {
+ return err;
+ }
+ if ( (int32_t) serialized_buffer_capacity < bytes_written + fdl_length )
+ {
+ return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
+ }
+ err = s_frame_data_length_pack( sender_ftds[i].frame_data_length, p_write );
+ if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
+ {
+ return err;
+ }
+ p_write += fdl_length;
+ bytes_written += fdl_length;
+ }
+
+ lc3plus_frame_size_sum = 0;
+ p_frame_data = serialized_buffer + bytes_written;
+ for ( i = 0; i < sender_ftds_num; ++i )
+ {
+ sender_ftds[i].frame_data = p_frame_data;
+ p_frame_data += sender_ftds[i].frame_data_length;
+ lc3plus_frame_size_sum += sender_ftds[i].frame_data_length;
+ }
+ *packed_buffer_actual_size = bytes_written + lc3plus_frame_size_sum;
+ assert( *packed_buffer_actual_size <= serialized_buffer_capacity );
+ return LC3PLUS_RTP_ERR_NO_ERROR;
+}
+
+static LC3PLUS_RTP_ERR s_ftds_parse(
+ LC3PLUS_RTP_FTD *receiver_ftds,
+ const int32_t receiver_ftds_num_max,
+ int16_t *receiver_ftds_num,
+ uint8_t *serialized_buffer,
+ const size_t serialized_buffer_size )
+{
+ int32_t diff;
+ uint8_t *p_read;
+ uint32_t ftds_offset_sum = 0;
+ int16_t i;
+ LC3PLUS_RTP_ERR error;
+ int32_t frame_offset_counter;
+ int32_t size;
+
+ p_read = serialized_buffer;
+ if ( NULL == receiver_ftds || NULL == receiver_ftds_num || NULL == serialized_buffer )
+ {
+ return LC3PLUS_RTP_ERR_NULL_PTR;
+ }
+ if ( 0 == serialized_buffer_size )
+ {
+ return LC3PLUS_RTP_ERR_EMPTY_TOC;
+ }
+ if ( receiver_ftds_num_max <= 0 )
+ {
+ return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
+ }
+ {
+ int32_t num_bytes_read_sum = 0;
+ const int32_t min_num_bytes_per_ftd = 2;
+ int16_t receiver_ftds_index = 0;
+ bool another_ftd = true;
+ int32_t num_bytes_read_per_ftd;
+
+ while ( another_ftd )
+ {
+ if ( (int32_t) serialized_buffer_size < min_num_bytes_per_ftd )
+ {
+ return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
+ }
+ if ( num_bytes_read_sum >= (int32_t) serialized_buffer_size - min_num_bytes_per_ftd )
+ {
+ return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
+ }
+ num_bytes_read_per_ftd = 0;
+ error = s_parse_ftd( p_read, &receiver_ftds[receiver_ftds_index], &num_bytes_read_per_ftd, serialized_buffer_size - num_bytes_read_sum );
+ if ( LC3PLUS_RTP_ERR_NO_ERROR != error )
+ {
+ return error;
+ }
+ p_read += num_bytes_read_per_ftd;
+ num_bytes_read_sum += num_bytes_read_per_ftd;
+
+ if ( receiver_ftds[receiver_ftds_index].fc == LC3PLUS_RTP_FTD_FC_RESERVED )
+ {
+ return LC3PLUS_RTP_ERR_INVALID_BITSTREAM;
+ }
+ else if ( receiver_ftds[receiver_ftds_index].fc == LC3PLUS_RTP_FTD_FC_LAST_OVERALL )
+ {
+ another_ftd = false;
+ }
+
+ if ( another_ftd )
+ {
+ if ( receiver_ftds_index >= receiver_ftds_num_max )
+ {
+ return LC3PLUS_RTP_ERR_NOT_ENOUGH_FTDS_ALLOCATED;
+ }
+ ( receiver_ftds_index )++;
+ }
+ }
+ *receiver_ftds_num = receiver_ftds_index + 1;
+ }
+
+ /* set frame-data pointers into serialized_buffer */
+ for ( i = 0; i < *receiver_ftds_num; ++i )
+ {
+ error = LC3PLUS_RTP_frame_data_length_get_size( &size, receiver_ftds[i].frame_data_length );
+ if ( error != LC3PLUS_RTP_ERR_NO_ERROR )
+ {
+ return error;
+ }
+ ftds_offset_sum += LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL + size;
+ }
+
+ frame_offset_counter = 0;
+ for ( i = 0; i < *receiver_ftds_num; ++i )
+ {
+ if ( s_fdl_is_magic_value( receiver_ftds[i].frame_data_length ) )
+ {
+ receiver_ftds[i].frame_data = NULL;
+ }
+ else
+ {
+ receiver_ftds[i].frame_data = serialized_buffer + ftds_offset_sum + frame_offset_counter;
+ frame_offset_counter += receiver_ftds[i].frame_data_length;
+ }
+ }
+
+ if ( ftds_offset_sum + frame_offset_counter != serialized_buffer_size )
+ {
+ /* parsed content & size n bytes of input buffer do not line up */
+ /* if the buffer capacity is larger and the remaining bytes are zero, we don't treat this as an error since it's due to the IVAS-Split rendering zero padding */
+ diff = serialized_buffer_size - ( ftds_offset_sum + frame_offset_counter );
+ if ( diff < 0 )
+ {
+ return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
+ }
+ /* verify that all bytes are zero */
+ p_read += frame_offset_counter;
+ for ( i = 0; i < diff; ++i )
+ {
+ if ( *p_read != 0 )
+ {
+ /* non-zero byte in padding region */
+ return LC3PLUS_RTP_ERR_NONZERO_PADDING_BYTES;
+ }
+ p_read++;
+ }
+ }
+ return LC3PLUS_RTP_ERR_NO_ERROR;
+}
+
+LC3PLUS_RTP_ERR LC3PLUS_RTP_payload_deserialize(
+ LC3PLUS_RTP_PAYLOAD *payload,
+ uint8_t *serialized_buffer,
+ const size_t serialized_buffer_size )
+{
+ int32_t new_frame_duration_us;
+ int32_t new_sampling_rate_hz;
+ int16_t new_high_resolution_flag;
+ int16_t i = 0;
+ int16_t channel_id = 0;
+ int16_t media_time_id = 0;
+ const int16_t invalid_value = -1;
+ int16_t media_times_per_channel[LC3PLUS_RTP_PAYLOAD_MAX_NUM_CHANNELS];
+ int16_t channels_per_media_time[LC3PLUS_RTP_PAYLOAD_MAX_NUM_MEDIA_TIMES];
+ LC3PLUS_RTP_ERR err;
+
+ if ( NULL == payload || NULL == serialized_buffer )
+ {
+ return LC3PLUS_RTP_ERR_NULL_PTR;
+ }
+ if ( 0 == serialized_buffer_size )
+ {
+ return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
+ }
+
+ for ( media_time_id = 0; media_time_id < LC3PLUS_RTP_PAYLOAD_MAX_NUM_MEDIA_TIMES; ++media_time_id )
+ {
+ channels_per_media_time[media_time_id] = invalid_value;
+ }
+ media_time_id = 0;
+ for ( channel_id = 0; channel_id < LC3PLUS_RTP_PAYLOAD_MAX_NUM_CHANNELS; ++channel_id )
+ {
+ media_times_per_channel[channel_id] = invalid_value;
+ }
+ channel_id = 0;
+
+ err = s_frame_data_length_parse( &payload->fdl_request, serialized_buffer, serialized_buffer_size );
+ if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
+ {
+ return err;
+ }
+ int32_t fdl_request_length;
+ err = LC3PLUS_RTP_frame_data_length_get_size( &fdl_request_length, payload->fdl_request );
+ if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
+ {
+ return err;
+ }
+ if ( !s_fdl_value_is_valid_request( payload->fdl_request ) )
+ {
+ return LC3PLUS_RTP_ERR_INVALID_FDL_REQUEST;
+ }
+
+ err = s_ftds_parse( payload->ftds, sizeof( payload->ftds ) / sizeof( LC3PLUS_RTP_FTD ), &payload->num_ftds, serialized_buffer + fdl_request_length, serialized_buffer_size - fdl_request_length );
+ if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
+ {
+ return err;
+ }
+ if ( 0 == payload->num_ftds )
+ {
+ return LC3PLUS_RTP_ERR_GENERIC_ERROR;
+ }
+ /* verify shared setting between all FTDs [samplerate, frame_duration, channel count] */
+
+ /* initialize on the first FTD, use this as reference */
+ err = s_frame_duration_ms_from_fdi( &payload->frame_duration_us, payload->ftds[0].fdi );
+ if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
+ {
+ return err;
+ }
+ err = s_sampling_rate_hz_from_bwr( &payload->sampling_rate_hz, payload->ftds[0].bwr );
+ if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
+ {
+ return err;
+ }
+ err = s_high_resolution_flag_from_bwr( &payload->high_resolution_enabled, payload->ftds[0].bwr );
+ if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
+ {
+ return err;
+ }
+ payload->num_channels = 0;
+ payload->num_media_times = 0;
+ for ( i = 0; i < payload->num_ftds; ++i )
+ {
+ if ( payload->ftds[i].h != LC3PLUS_RTP_FTD_H_PRIMARY )
+ {
+ /* not implemented */
+ return LC3PLUS_RTP_ERR_NOT_IMPLEMENTED;
+ }
+
+ err = s_frame_duration_ms_from_fdi( &new_frame_duration_us, payload->ftds[i].fdi );
+ if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
+ {
+ return err;
+ }
+ if ( payload->frame_duration_us != new_frame_duration_us )
+ {
+ /* mixed frame durations not supported */
+ return LC3PLUS_RTP_ERR_UNSUPPORTED_CONFIGURATION;
+ }
+
+ err = s_sampling_rate_hz_from_bwr( &new_sampling_rate_hz, payload->ftds[i].bwr );
+ if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
+ {
+ return err;
+ }
+ if ( payload->sampling_rate_hz != new_sampling_rate_hz )
+ {
+ /* mixed sampling frequencies not supported */
+ return LC3PLUS_RTP_ERR_UNSUPPORTED_CONFIGURATION;
+ }
+
+
+ err = s_high_resolution_flag_from_bwr( &new_high_resolution_flag, payload->ftds[i].bwr );
+ if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
+ {
+ return err;
+ }
+ if ( payload->high_resolution_enabled != new_high_resolution_flag )
+ {
+ /* mixed high resolution mode not supported */
+ return LC3PLUS_RTP_ERR_UNSUPPORTED_CONFIGURATION;
+ }
+
+ switch ( payload->ftds[i].fc )
+ {
+ case LC3PLUS_RTP_FTD_FC_LAST_OVERALL:
+ channels_per_media_time[media_time_id]++;
+ media_times_per_channel[channel_id]++;
+ channel_id = 0;
+ media_time_id = 0;
+ break;
+ case LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL:
+ media_times_per_channel[channel_id]++;
+ channels_per_media_time[media_time_id]++;
+ channel_id++;
+ break;
+ case LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME:
+ media_times_per_channel[channel_id]++;
+ channels_per_media_time[media_time_id]++;
+ channel_id = 0;
+ media_time_id++;
+ break;
+ case LC3PLUS_RTP_FTD_FC_RESERVED:
+ default:
+ return LC3PLUS_RTP_ERR_INVALID_BITSTREAM;
+ }
+ }
+
+ {
+ int32_t valid_num_media_times_per_channel;
+ int32_t iCh;
+ /* check whether all channels exist for each media time */
+ if ( media_times_per_channel[0] == invalid_value )
+ {
+ return LC3PLUS_RTP_ERR_NOT_IMPLEMENTED;
+ }
+ valid_num_media_times_per_channel = media_times_per_channel[0];
+ for ( iCh = 0; iCh < LC3PLUS_RTP_PAYLOAD_MAX_NUM_CHANNELS; ++iCh )
+ {
+ if ( media_times_per_channel[iCh] == invalid_value )
+ {
+ break;
+ }
+ if ( valid_num_media_times_per_channel != media_times_per_channel[iCh] )
+ {
+ return LC3PLUS_RTP_ERR_NOT_IMPLEMENTED;
+ }
+ }
+ }
+ {
+ /* whether all media times exist for each channel */
+ int32_t iMediaTime;
+ int32_t valid_num_channels_per_media_time;
+ if ( channels_per_media_time[0] == invalid_value )
+ {
+ return LC3PLUS_RTP_ERR_NOT_IMPLEMENTED;
+ }
+ valid_num_channels_per_media_time = channels_per_media_time[0];
+ for ( iMediaTime = 0; iMediaTime < LC3PLUS_RTP_PAYLOAD_MAX_NUM_MEDIA_TIMES; ++iMediaTime )
+ {
+ if ( channels_per_media_time[iMediaTime] == invalid_value )
+ {
+ break;
+ }
+ if ( valid_num_channels_per_media_time != channels_per_media_time[iMediaTime] )
+ {
+ return LC3PLUS_RTP_ERR_NOT_IMPLEMENTED;
+ }
+ }
+ }
+
+ /* convert zero-index to count */
+ payload->num_channels = channels_per_media_time[0] + 1;
+ payload->num_media_times = media_times_per_channel[0] + 1;
+
+ /* verify that all media times have the same number of channels, partial packets are not supported */
+ if ( payload->num_ftds != payload->num_channels * payload->num_media_times )
+ {
+ return LC3PLUS_RTP_ERR_GENERIC_ERROR;
+ }
+ return LC3PLUS_RTP_ERR_NO_ERROR;
+}
+
+LC3PLUS_RTP_ERR LC3PLUS_RTP_ftd_bwr_from_samplerate( LC3PLUS_RTP_FTD_BWR *bwr, const int32_t sampling_rate, const int32_t high_res_enabled )
+{
+ if ( NULL == bwr )
+ {
+ return LC3PLUS_RTP_ERR_NULL_PTR;
+ }
+ switch ( sampling_rate )
+ {
+ case 8000:
+ if ( high_res_enabled )
+ {
+ return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
+ }
+ *bwr = LC3PLUS_RTP_FTD_BWR_NB;
+ return LC3PLUS_RTP_ERR_NO_ERROR;
+ case 16000:
+ if ( high_res_enabled )
+ {
+ return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
+ }
+ *bwr = LC3PLUS_RTP_FTD_BWR_WB;
+ return LC3PLUS_RTP_ERR_NO_ERROR;
+ case 24000:
+ if ( high_res_enabled )
+ {
+ return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
+ }
+ *bwr = LC3PLUS_RTP_FTD_BWR_SSWB;
+ return LC3PLUS_RTP_ERR_NO_ERROR;
+ case 32000:
+ if ( high_res_enabled )
+ {
+ return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
+ }
+ *bwr = LC3PLUS_RTP_FTD_BWR_SWB;
+ return LC3PLUS_RTP_ERR_NO_ERROR;
+ case 44100:
+ if ( high_res_enabled )
+ {
+ return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
+ }
+ *bwr = LC3PLUS_RTP_FTD_BWR_FBCD;
+ return LC3PLUS_RTP_ERR_NO_ERROR;
+ case 48000:
+ if ( 0 == high_res_enabled )
+ {
+ *bwr = LC3PLUS_RTP_FTD_BWR_FB;
+ return LC3PLUS_RTP_ERR_NO_ERROR;
+ }
+ else
+ {
+ *bwr = LC3PLUS_RTP_FTD_BWR_FBHR;
+ return LC3PLUS_RTP_ERR_NO_ERROR;
+ }
+ case 96000:
+ if ( 0 == high_res_enabled )
+ {
+ return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
+ }
+ *bwr = LC3PLUS_RTP_FTD_BWR_UBHR;
+ return LC3PLUS_RTP_ERR_NO_ERROR;
+ default:
+ break;
+ }
+
+ return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
+}
+
+LC3PLUS_RTP_ERR LC3PLUS_RTP_ftd_fdi_from_frame_duration_us( LC3PLUS_RTP_FTD_FDI *fdi, const int32_t frame_duration_us )
+{
+ if ( NULL == fdi )
+ {
+ return LC3PLUS_RTP_ERR_NULL_PTR;
+ }
+ switch ( frame_duration_us )
+ {
+ case 2500:
+ *fdi = LC3PLUS_RTP_FTD_FDI_2500_US;
+ return LC3PLUS_RTP_ERR_NO_ERROR;
+ case 5000:
+ *fdi = LC3PLUS_RTP_FTD_FDI_5000_US;
+ return LC3PLUS_RTP_ERR_NO_ERROR;
+ case 10000:
+ *fdi = LC3PLUS_RTP_FTD_FDI_10000_US;
+ return LC3PLUS_RTP_ERR_NO_ERROR;
+ default:
+ break;
+ }
+
+ return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
+}
+
+#endif /* ISAR_BITSTREAM_UPDATE_LC3PLUS */
+#endif /* SPLIT_REND_WITH_HEAD_ROT */
diff --git a/lib_isar/isar_lc3plus_payload.h b/lib_isar/isar_lc3plus_payload.h
new file mode 100644
index 0000000000000000000000000000000000000000..1e649690ec435fd690e86f57738b3fb399bd2956
--- /dev/null
+++ b/lib_isar/isar_lc3plus_payload.h
@@ -0,0 +1,216 @@
+/******************************************************************************************************
+
+ (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository. All Rights Reserved.
+
+ This software is protected by copyright law and by international treaties.
+ The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository retain full ownership rights in their respective contributions in
+ the software. This notice grants no license of any kind, including but not limited to patent
+ license, nor is any license granted by implication, estoppel or otherwise.
+
+ Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
+ contributions.
+
+ This software is provided "AS IS", without any express or implied warranties. The software is in the
+ development stage. It is intended exclusively for experts who have experience with such software and
+ solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
+ and fitness for a particular purpose are hereby disclaimed and excluded.
+
+ Any dispute, controversy or claim arising under or in relation to providing this software shall be
+ submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
+ accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
+ the United Nations Convention on Contracts on the International Sales of Goods.
+
+*******************************************************************************************************/
+
+#ifndef ISAR_LC3PLUS_PAYLOAD_H
+#define ISAR_LC3PLUS_PAYLOAD_H
+
+#include
+#include
+#include "lc3.h"
+#include "options.h"
+
+#ifdef SPLIT_REND_WITH_HEAD_ROT
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+
+/* Implementation of the "B.2.6 Table of contents" part of the RTP payload format
+ * for LC3plus as specified in ETSI TS 103 634. */
+
+typedef enum LC3PLUS_RTP_ERR
+{
+ LC3PLUS_RTP_ERR_NO_ERROR,
+ LC3PLUS_RTP_ERR_NULL_PTR,
+ LC3PLUS_RTP_ERR_INVALID_PARAMETERS,
+ LC3PLUS_RTP_ERR_EMPTY_TOC,
+ LC3PLUS_RTP_ERR_NOT_IMPLEMENTED,
+ LC3PLUS_RTP_ERR_UNSUPPORTED_CONFIGURATION,
+ LC3PLUS_RTP_ERR_INVALID_BITSTREAM,
+ LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE,
+ LC3PLUS_RTP_ERR_NOT_ENOUGH_FTDS_ALLOCATED,
+ LC3PLUS_RTP_ERR_INVALID_FDL_REQUEST,
+ LC3PLUS_RTP_ERR_NONZERO_PADDING_BYTES,
+ LC3PLUS_RTP_ERR_GENERIC_ERROR
+} LC3PLUS_RTP_ERR;
+
+/*
+ * The content of the FTD is shown in Figure B.6.
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |FC |FDI| BWR |H| FDL1 | (FDL2) | (FDL3) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+/* FC (2 bits):
+ * Frame and Channel (FC) indicator for subsequent frame data (if available). The meaning of the FC
+ * indicator is shown in Table B.2. The FC value defines the media time stamp (in integer increments
+ * of TSI) and the channel counter (CC, starting from 1 for the first channel) for the subsequent
+ * FTD (if available). */
+typedef enum LC3PLUS_RTP_FTD_FC
+{
+ LC3PLUS_RTP_FTD_FC_LAST_OVERALL = 0x00, /* Last FDL in ToC, no FDL follows the current FDL */
+ LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL = 0x01, /* The next FDL is for the next channel for the same media time */
+ LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME = 0x02, /* The next FDL is for first channel for next media time, channel counter is reset */
+ LC3PLUS_RTP_FTD_FC_RESERVED = 0x03, /* Reserved */
+} LC3PLUS_RTP_FTD_FC;
+#define LC3PLUS_RTP_FTD_FC_MASK 0x03
+
+/* FDI (2 bits):
+ * Frame Duration Index, with encoding as shown in Table B.3. The FDI shall be static for a given
+ * payload type during the session. The FDI also dictates the TSI, needed for deriving the media
+ * time in case of more than one frame in the payload. */
+typedef enum LC3PLUS_RTP_FTD_FDI
+{
+ LC3PLUS_RTP_FTD_FDI_2500_US = 0x00,
+ LC3PLUS_RTP_FTD_FDI_5000_US = 0x04,
+ LC3PLUS_RTP_FTD_FDI_10000_US = 0x08,
+ LC3PLUS_RTP_FTD_FDI_RESERVED = 0x0C,
+} LC3PLUS_RTP_FTD_FDI;
+#define LC3PLUS_RTP_FTD_FDI_MASK 0x0C
+LC3PLUS_RTP_ERR LC3PLUS_RTP_ftd_fdi_from_frame_duration_us( LC3PLUS_RTP_FTD_FDI *fdi, const int32_t frame_duration_us );
+
+/* BWR (3 bits):
+ * Bandwidth and resolution combination used by the codec is jointly encoded into a bandwidth and
+ * resolution (BWR) index. The BWR index is encoded as shown in Table B.4. The BWR encoding is
+ * defined in Table B.4. The BWR index shall be static for a given payload type during the session. */
+typedef enum LC3PLUS_RTP_FTD_BWR
+{
+ LC3PLUS_RTP_FTD_BWR_NB = 0x00,
+ LC3PLUS_RTP_FTD_BWR_WB = 0x10,
+ LC3PLUS_RTP_FTD_BWR_SSWB = 0x20,
+ LC3PLUS_RTP_FTD_BWR_SWB = 0x30,
+ LC3PLUS_RTP_FTD_BWR_FBCD = 0x40,
+ LC3PLUS_RTP_FTD_BWR_FB = 0x50,
+ LC3PLUS_RTP_FTD_BWR_FBHR = 0x60,
+ LC3PLUS_RTP_FTD_BWR_UBHR = 0x70,
+} LC3PLUS_RTP_FTD_BWR;
+#define LC3PLUS_RTP_FTD_BWR_MASK 0x70
+LC3PLUS_RTP_ERR LC3PLUS_RTP_ftd_bwr_from_samplerate( LC3PLUS_RTP_FTD_BWR *bwr, const int32_t sampling_rate, const int32_t high_res_enabled );
+
+/* H (1 bit):
+ * Indicates whether the corresponding frame is a normal frame (primary encoding) or a helper frame
+ * (secondary encoding). 0 indicates a primary frame, 1 indicates secondary (redundant) frame */
+typedef enum LC3PLUS_RTP_FTD_H
+{
+ LC3PLUS_RTP_FTD_H_PRIMARY = 0x00,
+ LC3PLUS_RTP_FTD_H_SECONDARY = 0x80,
+} LC3PLUS_RTP_FTD_H;
+#define LC3PLUS_RTP_FTD_H_MASK 0x80
+
+typedef enum LC3PLUS_RTP_FDL
+{
+ LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA = 0,
+ LC3PLUS_RTP_FDL_SPEECH_BAD = 1,
+ LC3PLUS_RTP_FDL_SPEECH_SID = 2,
+ LC3PLUS_RTP_FDL_RESERVED_MIN = 3,
+ LC3PLUS_RTP_FDL_RESERVED_MAX = 19,
+ LC3PLUS_RTP_FDL_LENGTH_1_MIN = 20,
+ LC3PLUS_RTP_FDL_LENGTH_1_MAX = 254,
+ LC3PLUS_RTP_FDL_LENGTH_2_MIN = 255,
+ LC3PLUS_RTP_FDL_LENGTH_2_MAX = 509,
+ LC3PLUS_RTP_FDL_LENGTH_3_MIN = 510,
+ LC3PLUS_RTP_FDL_LENGTH_3_MAX = 765
+} LC3PLUS_RTP_FDL;
+/* value used to indicate that the Frame Data Length (FDL) extends to the next byte */
+#define LC3PLUS_RTP_FDL_EXTENSION_VALUE 0xFF
+
+typedef struct LC3PLUS_RTP_FTD
+{
+ LC3PLUS_RTP_FTD_FC fc;
+ LC3PLUS_RTP_FTD_FDI fdi;
+ LC3PLUS_RTP_FTD_BWR bwr;
+ LC3PLUS_RTP_FTD_H h;
+ uint8_t *frame_data;
+ LC3PLUS_RTP_FDL frame_data_length;
+} LC3PLUS_RTP_FTD;
+#define LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL 1
+#define LC3PLUS_RTP_FDL_MIN_LENGTH 1
+#define LC3PLUS_RTP_FTD_MIN_SIZE ( LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL + LC3PLUS_RTP_FDL_MIN_LENGTH )
+
+/*! Serialize the sender_ftds structs and fdl_request into a linear compact buffer
+ * @param[out] serialized_buffer pointer to the start of the memory location where the serialized buffer will be written to
+ * @param[in] serialized_buffer_capacity capacity of the serialized_buffer in bytes
+ * @param[out] packed_buffer_actual_size actually used size of in bytes of the packed_buffer (<=serialized_buffer_capacity)
+ * @param[in] fdl_request frame data length request
+ * @param[in,out] sender_ftds the function will overwrite the frame_data pointer with the correct memory location in
+ * the packed_buffer (so it can subsequently be used as input for the LC3plus encode call)
+ * @param[in] sender_ftds_num number of sender_ftds
+ * @return LC3PLUS_RTP_ERR_NO_ERROR in case of success */
+LC3PLUS_RTP_ERR LC3PLUS_RTP_payload_serialize(
+ uint8_t *serialized_buffer,
+ const size_t serialized_buffer_capacity,
+ size_t *packed_buffer_actual_size,
+ const LC3PLUS_RTP_FDL fdl_request,
+ LC3PLUS_RTP_FTD *sender_ftds,
+ const size_t sender_ftds_num );
+
+/*! Get size of the frame data length field for a certain frame data length value in bytes.
+ * @param[out] length size of the frame data length field in bytes [1,2,3]
+ * @param[in] frameDataLengthValue frame data length value
+ * @return LC3PLUS_RTP_ERR_NO_ERROR in case of success */
+LC3PLUS_RTP_ERR LC3PLUS_RTP_frame_data_length_get_size( int32_t *length, const LC3PLUS_RTP_FDL frameDataLengthValue );
+
+#define LC3PLUS_RTP_PAYLOAD_MAX_NUM_CHANNELS 16
+#define LC3PLUS_RTP_PAYLOAD_MAX_NUM_MEDIA_TIMES 8 /* max ivas frame duration/min lc3plus frame duration: 20000/2500 */
+#define LC3PLUS_RTP_PAYLOAD_MAX_NUM_FTDS LC3PLUS_RTP_PAYLOAD_MAX_NUM_CHANNELS *LC3PLUS_RTP_PAYLOAD_MAX_NUM_MEDIA_TIMES
+
+typedef struct LC3PLUS_RTP_PAYLOAD_CONFIG
+{
+ /* frame duration in us shared among all FTDs */
+ int32_t frame_duration_us;
+ /* high resolution flag shared among all FTDs */
+ int16_t high_resolution_enabled;
+ /* sampling frequency shared among all FTDs */
+ int32_t sampling_rate_hz;
+ /* number of individual channels in the payload */
+ int16_t num_channels;
+ /* number of individual media times in the payload */
+ int16_t num_media_times;
+ /* frame data length request */
+ LC3PLUS_RTP_FDL fdl_request;
+ /* FTD data with pointer to raw frame data */
+ LC3PLUS_RTP_FTD ftds[LC3PLUS_RTP_PAYLOAD_MAX_NUM_FTDS];
+ /* actual number of ftds */
+ int16_t num_ftds;
+} LC3PLUS_RTP_PAYLOAD;
+
+/*! Deserialized a serialized buffer into a LC3PLUS_RTP_PAYLOAD struct
+ * @param payload pointer to target LC3PLUS_RTP_PAYLOAD object. Note: frame_data pointers in the struct will point to the respective memory locations in the serialized_buffer.
+ * @param serialized_buffer pointer to the start of the serialized input buffer
+ * @param serialized_buffer_size size of the serialized input buffer in bytes
+ * @return LC3PLUS_RTP_ERR_NO_ERROR in case of success */
+LC3PLUS_RTP_ERR LC3PLUS_RTP_payload_deserialize(
+ LC3PLUS_RTP_PAYLOAD *payload,
+ uint8_t *serialized_buffer,
+ const size_t serialized_buffer_size );
+
+#endif /* ISAR_BITSTREAM_UPDATE_LC3PLUS */
+#endif /* #ifdef SPLIT_REND_WITH_HEAD_ROT */
+#endif /* ISAR_LC3PLUS_PAYLOAD_H */
diff --git a/lib_isar/isar_prot.h b/lib_isar/isar_prot.h
index c5842bab7593a330e1cd7d2cda8670cb6a092e08..ffc42b2283fbfb342e21a89da0524b475d1a7c87 100644
--- a/lib_isar/isar_prot.h
+++ b/lib_isar/isar_prot.h
@@ -56,7 +56,12 @@ ivas_error split_renderer_open_lc3plus(
SPLIT_REND_WRAPPER *hSplitRendWrapper,
const ISAR_SPLIT_REND_CONFIG_DATA *pSplitRendConfig,
const int32_t OutSampleRate,
- const int16_t num_subframes );
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ const IVAS_RENDER_FRAMESIZE ivas_frame_size
+#else
+ const int16_t num_subframes
+#endif
+);
void isar_splitBinPreRendClose(
ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE *hBinHrSplitPreRend );
@@ -69,7 +74,11 @@ void lc3plusTimeAlignCldfbPoseCorr(
ivas_error splitRendLc3plusEncodeAndWrite(
SPLIT_REND_WRAPPER *hSplitBin,
ISAR_SPLIT_REND_BITS_HANDLE pBits,
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ const int32_t available_bits,
+#else
const int32_t SplitRendBitRate,
+#endif
float *in[] );
int32_t ISAR_SPLIT_REND_BITStream_read_int32(
@@ -260,6 +269,9 @@ ivas_error isar_renderMultiTDBinToSplitBinaural(
SPLIT_REND_WRAPPER *hSplitBin,
const IVAS_QUATERNION headPosition,
const int32_t SplitRendBitRate,
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ const int16_t isar_frame_size_ms,
+#endif
const int16_t codec_frame_size_ms,
ISAR_SPLIT_REND_BITS_HANDLE pBits,
const int16_t max_bands,
@@ -298,10 +310,12 @@ void isar_set_split_rend_ht_setup(
IVAS_QUATERNION Quaternions[MAX_PARAM_SPATIAL_SUBFRAMES],
float Rmat[MAX_PARAM_SPATIAL_SUBFRAMES][3][3] );
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
int32_t isar_get_lc3plus_bitrate(
const int32_t SplitRendBitRate,
const ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrectionMode,
const int16_t split_prerender_frame_size_ms );
+#endif
ivas_error isar_split_rend_validate_config(
const ISAR_SPLIT_REND_CONFIG_DATA *pSplitRendConfig,
@@ -311,15 +325,27 @@ int32_t isar_get_lcld_bitrate(
const int32_t SplitRendBitRate,
const ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrectionMode );
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
int8_t isar_get_lc3plus_bitrate_id(
const int32_t SplitRendBitRate );
+#endif
int32_t isar_get_split_rend_md_target_brate(
const int32_t SplitRendBitRate,
const int16_t pcm_out_flag );
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ivas_error isar_framesize_to_ms(
+ const IVAS_RENDER_FRAMESIZE frame_size, /* i : frame size enum */
+ int16_t *ms /* o : frame size in ms */
+);
+#endif
+
ivas_error isar_split_rend_choose_default_codec(
ISAR_SPLIT_REND_CODEC *pCodec, /* i/o: pointer to codec setting */
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ int16_t *pIsar_frame_size_ms, /* i/o: pointer to isar frame size setting */
+#endif
int16_t *pCodec_frame_size_ms, /* i/o: pointer to codec frame size setting */
const int16_t cldfb_in_flag, /* i : flag indicating rendering in TD */
const int16_t pcm_out_flag, /* i : flag to indicate PCM output */
@@ -339,10 +365,12 @@ int16_t wrap_a(
const int16_t min_val,
const int16_t max_val );
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
int32_t isar_get_lc3plus_size_from_id(
const int8_t SplitRendBitRateId,
const ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrectionMode,
const int16_t split_prerender_frame_size_ms );
+#endif
void isar_renderSplitUpdateNoCorrectionPoseData(
const ISAR_SPLIT_REND_CONFIG_DATA *pSplit_rend_config,
diff --git a/lib_isar/isar_splitRendererPre.c b/lib_isar/isar_splitRendererPre.c
index be899732246ca8d82b45dd2bdd8201fcbbdc8932..ef1072f5c9e3a736c8f70eb973fce9396b47e63b 100644
--- a/lib_isar/isar_splitRendererPre.c
+++ b/lib_isar/isar_splitRendererPre.c
@@ -1925,19 +1925,55 @@ ivas_error split_renderer_open_lc3plus(
SPLIT_REND_WRAPPER *hSplitRendWrapper,
const ISAR_SPLIT_REND_CONFIG_DATA *pSplitRendConfig,
const int32_t OutSampleRate,
- const int16_t num_subframes )
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ const IVAS_RENDER_FRAMESIZE isar_frame_size
+#else
+ const int16_t num_subframes
+#endif
+)
{
ivas_error error;
int16_t i, delayBufferLength;
LC3PLUS_CONFIG config;
+#if defined ISAR_BITSTREAM_UPDATE_LC3PLUS
+ int16_t isar_frame_size_ms;
+
+ if ( ( error = isar_framesize_to_ms( isar_frame_size, &isar_frame_size_ms ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+#endif
+
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ /* Check configuration validity */
+ if ( isar_frame_size_ms < pSplitRendConfig->codec_frame_size_ms )
+ {
+ return IVAS_ERROR( IVAS_ERR_INVALID_SPLIT_REND_CONFIG, "SR codec frame doesn't fit in one output frame" );
+ }
+#endif
config.lc3plus_frame_duration_us = pSplitRendConfig->codec_frame_size_ms * 1000;
- config.ivas_frame_duration_us = ( pSplitRendConfig->dof == 0 ) ? config.lc3plus_frame_duration_us * num_subframes : 20000;
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ config.isar_frame_duration_us = ( pSplitRendConfig->dof == 0 ) ? config.lc3plus_frame_duration_us * num_subframes : 20000;
+#endif
config.samplerate = OutSampleRate;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ config.isar_frame_duration_us = isar_frame_size_ms * 1000;
+#endif
+
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ config.high_res_mode_enabled = ( pSplitRendConfig->lc3plus_highres != 0 );
+#endif
config.channels = BINAURAL_CHANNELS;
- if ( ( error = ISAR_LC3PLUS_ENC_Open( config, isar_get_lc3plus_bitrate( pSplitRendConfig->splitRendBitRate, pSplitRendConfig->poseCorrectionMode, (int16_t) ( config.ivas_frame_duration_us / 1000 ) ), &hSplitRendWrapper->hLc3plusEnc ) ) != IVAS_ERR_OK )
+ if ( ( error = ISAR_LC3PLUS_ENC_Open( config,
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ isar_get_lcld_bitrate( pSplitRendConfig->splitRendBitRate, pSplitRendConfig->poseCorrectionMode ),
+#else
+ isar_get_lc3plus_bitrate( pSplitRendConfig->splitRendBitRate, pSplitRendConfig->poseCorrectionMode, (int16_t) ( config.isar_frame_duration_us / 1000 ) ),
+#endif
+ &hSplitRendWrapper->hLc3plusEnc ) ) != IVAS_ERR_OK )
{
return error;
}
@@ -1993,7 +2029,13 @@ ivas_error split_renderer_open_lc3plus(
ivas_error splitRendLc3plusEncodeAndWrite(
SPLIT_REND_WRAPPER *hSplitBin,
ISAR_SPLIT_REND_BITS_HANDLE pBits,
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ const int32_t available_bits,
+#endif
+#else
const int32_t SplitRendBitRate,
+#endif
float *in[] )
{
ivas_error error;
@@ -2013,15 +2055,28 @@ ivas_error splitRendLc3plusEncodeAndWrite(
channel_ptrs[i] = in[i];
}
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ if ( ( error = IVAS_LC3PLUS_ENC_SetBitrate( hSplitBin->hLc3plusEnc, available_bits * FRAMES_PER_SEC ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+#endif
+
if ( ( error = ISAR_LC3PLUS_ENC_GetOutputBitstreamSize( hSplitBin->hLc3plusEnc, &lc3plusBitstreamSize ) ) != IVAS_ERR_OK )
{
return error;
}
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
ISAR_SPLIT_REND_BITStream_write_int32( pBits, isar_get_lc3plus_bitrate_id( SplitRendBitRate ), 8 );
+#endif
/* Write bitstream */
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ if ( ( error = ISAR_LC3PLUS_ENC_Encode( hSplitBin->hLc3plusEnc, channel_ptrs, &pBits->bits_buf[pBits->bits_written / 8], lc3plusBitstreamSize ) ) != IVAS_ERR_OK )
+#else
if ( ( error = ISAR_LC3PLUS_ENC_Encode( hSplitBin->hLc3plusEnc, channel_ptrs, &pBits->bits_buf[pBits->bits_written / 8] ) ) != IVAS_ERR_OK )
+#endif
{
return error;
}
@@ -2030,10 +2085,12 @@ ivas_error splitRendLc3plusEncodeAndWrite(
pBits->codec = ISAR_SPLIT_REND_CODEC_LC3PLUS;
pBits->pose_correction = hSplitBin->multiBinPoseData.poseCorrectionMode;
pBits->codec_frame_size_ms = (int16_t) ( hSplitBin->hLc3plusEnc->config.lc3plus_frame_duration_us / 1000 );
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ pBits->isar_frame_size_ms = (int16_t) ( hSplitBin->hLc3plusEnc->config.isar_frame_duration_us / 1000 );
+#endif
return IVAS_ERR_OK;
}
-
/*-------------------------------------------------------------------------
* Function isar_renderMultiTDBinToSplitBinaural()
*
@@ -2044,6 +2101,9 @@ ivas_error isar_renderMultiTDBinToSplitBinaural(
SPLIT_REND_WRAPPER *hSplitBin,
const IVAS_QUATERNION headPosition,
const int32_t SplitRendBitRate,
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ const int16_t isar_frame_size_ms,
+#endif
const int16_t codec_frame_size_ms,
ISAR_SPLIT_REND_BITS_HANDLE pBits,
const int16_t max_bands,
@@ -2053,7 +2113,11 @@ ivas_error isar_renderMultiTDBinToSplitBinaural(
const int16_t ro_md_flag )
{
ivas_error error;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ int32_t bit_len, available_bits, target_md_bits;
+#else
int32_t bit_len, available_bits, target_md_bits, actual_md_bits;
+#endif
int16_t num_cldfb_bands, ch, slot_idx, pos_idx, num_poses;
float Cldfb_In_BinReal[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
float Cldfb_In_BinImag[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
@@ -2090,7 +2154,9 @@ ivas_error isar_renderMultiTDBinToSplitBinaural(
}
}
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
actual_md_bits = pBits->bits_written;
+#endif
if ( ( hSplitBin->multiBinPoseData.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) || ( !useLc3plus && !pcm_out_flag ) )
{
num_slots = ( hSplitBin->multiBinPoseData.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) ? CLDFB_NO_COL_MAX : ( hSplitBin->hSplitBinLCLDEnc->iNumBlocks * hSplitBin->hSplitBinLCLDEnc->iNumIterations );
@@ -2131,7 +2197,9 @@ ivas_error isar_renderMultiTDBinToSplitBinaural(
{
target_md_bits = isar_get_split_rend_md_target_brate( SplitRendBitRate, pcm_out_flag ) * L_FRAME48k / 48000;
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
actual_md_bits = pBits->bits_written;
+#endif
isar_rend_CldfbSplitPreRendProcess( hSplitBin->hBinHrSplitPreRend, headPosition, &hSplitBin->multiBinPoseData, Cldfb_In_BinReal, Cldfb_In_BinImag, pBits, target_md_bits, low_res_pre_rend_rot, ro_md_flag );
}
@@ -2144,15 +2212,32 @@ ivas_error isar_renderMultiTDBinToSplitBinaural(
if ( !useLc3plus )
{
available_bits = ( SplitRendBitRate * hSplitBin->hSplitBinLCLDEnc->iNumBlocks * hSplitBin->hSplitBinLCLDEnc->iNumIterations ) / ( 16 * FRAMES_PER_SEC );
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ available_bits -= pBits->bits_written;
+#else
actual_md_bits = pBits->bits_written - actual_md_bits;
available_bits -= actual_md_bits;
+#endif
pBits->codec_frame_size_ms = codec_frame_size_ms;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ pBits->isar_frame_size_ms = isar_frame_size_ms;
+#endif
isar_splitBinLCLDEncProcess( hSplitBin->hSplitBinLCLDEnc, Cldfb_In_BinReal, Cldfb_In_BinImag, available_bits, pBits );
}
else
{
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ available_bits = ( SplitRendBitRate / FRAMES_PER_SEC ) - pBits->bits_written;
+ if ( ( error = splitRendLc3plusEncodeAndWrite( hSplitBin, pBits, available_bits, in ) ) != IVAS_ERR_OK )
+#else
+ available_bits = ( SplitRendBitRate / FRAMES_PER_SEC ) - pBits->bits_written;
+ if ( ( error = splitRendLc3plusEncodeAndWrite( hSplitBin, pBits, in ) ) != IVAS_ERR_OK )
+#endif
+#else
if ( ( error = splitRendLc3plusEncodeAndWrite( hSplitBin, pBits, SplitRendBitRate, in ) ) != IVAS_ERR_OK )
+#endif
{
return error;
}
@@ -2177,7 +2262,7 @@ ivas_error isar_renderMultiTDBinToSplitBinaural(
}
else
{
- bit_len = hSplitBin->hLc3plusEnc->config.ivas_frame_duration_us / 1000;
+ bit_len = hSplitBin->hLc3plusEnc->config.isar_frame_duration_us / 1000;
bit_len = SplitRendBitRate * bit_len / 1000;
}
}
diff --git a/lib_isar/isar_splitRenderer_utils.c b/lib_isar/isar_splitRenderer_utils.c
index b20791f4b9f6aaf12b823a5612f8e5ccb034ec20..f6933796dfcfb1d0a657ec819dbe0193912dff35 100644
--- a/lib_isar/isar_splitRenderer_utils.c
+++ b/lib_isar/isar_splitRenderer_utils.c
@@ -564,6 +564,7 @@ int32_t isar_get_lcld_bitrate(
}
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
/*-------------------------------------------------------------------------
* Function isar_get_lc3plus_bitrate()
*
@@ -685,6 +686,7 @@ int32_t isar_get_lc3plus_size_from_id(
/* Return size in bytes */
return (int32_t) ( bitrate * split_prerender_frame_size_ms / 1000 / 8 );
}
+#endif
/*-------------------------------------------------------------------------
@@ -749,14 +751,19 @@ ivas_error isar_split_rend_validate_config(
break;
case SPLIT_REND_384k:
case SPLIT_REND_512k:
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ case SPLIT_REND_768k:
+#endif
/* Always valid */
break;
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
case SPLIT_REND_768k:
if ( pSplitRendConfig->dof == 0 && pSplitRendConfig->codec == ISAR_SPLIT_REND_CODEC_LC3PLUS )
{
return IVAS_ERROR( IVAS_ERR_INVALID_SPLIT_REND_CONFIG, "Bitrate is too high for LC3plus with 0 DOF" );
}
break;
+#endif
default:
return IVAS_ERR_LC3PLUS_INVALID_BITRATE;
}
@@ -1187,6 +1194,31 @@ void isar_init_multi_bin_pose_data(
return;
}
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ivas_error isar_framesize_to_ms(
+ const IVAS_RENDER_FRAMESIZE frame_size, /* i : frame size enum */
+ int16_t *ms /* o : frame size in ms */
+)
+{
+ switch ( frame_size )
+ {
+ case IVAS_RENDER_FRAMESIZE_5MS:
+ *ms = 5;
+ break;
+ case IVAS_RENDER_FRAMESIZE_10MS:
+ *ms = 10;
+ break;
+ case IVAS_RENDER_FRAMESIZE_20MS:
+ *ms = 20;
+ break;
+ default:
+ return IVAS_ERROR( IVAS_ERR_INTERNAL, "Unsupported ISAR frame size" );
+ }
+
+ return IVAS_ERR_OK;
+}
+#endif
+
/*-------------------------------------------------------------------------
* Function isar_split_rend_choose_default_codec()
@@ -1196,6 +1228,9 @@ void isar_init_multi_bin_pose_data(
ivas_error isar_split_rend_choose_default_codec(
ISAR_SPLIT_REND_CODEC *pCodec, /* i/o: pointer to codec setting */
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ int16_t *pIsar_frame_size_ms, /* i/o: pointer to isar frame size setting */
+#endif
int16_t *pCodec_frame_size_ms, /* i/o: pointer to codec frame size setting */
const int16_t cldfb_in_flag, /* i : flag indicating rendering in TD */
const int16_t pcm_out_flag, /* i : flag to indicate PCM output */
@@ -1229,7 +1264,12 @@ ivas_error isar_split_rend_choose_default_codec(
return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Unknown split codec value" );
}
}
-
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ if ( *pIsar_frame_size_ms == 0 ) /* isar frame size hasn't been set yet - use default for current configuration */
+ {
+ *pIsar_frame_size_ms = 20;
+ }
+#endif
return IVAS_ERR_OK;
}
diff --git a/lib_isar/lib_isar_post_rend.c b/lib_isar/lib_isar_post_rend.c
index 7e27e8e1599e1935015185224fabef1f31054c64..12fc8e6e43991f911abf3582958b5e24fa9c78f5 100644
--- a/lib_isar/lib_isar_post_rend.c
+++ b/lib_isar/lib_isar_post_rend.c
@@ -80,11 +80,18 @@ typedef struct
{
const int32_t *pOutSampleRate;
const AUDIO_CONFIG *pOutConfig;
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
const LSSETUP_CUSTOM_STRUCT *pCustomLsOut;
const EFAP_WRAPPER *pEfapOutWrapper;
+#endif
const ISAR_POST_REND_HeadRotData *pHeadRotData;
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
const RENDER_CONFIG_HANDLE *hhRendererConfig;
+#endif
const int16_t *pSplitRendBFI;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ const ISAR_SPLIT_REND_CONFIG_DATA *pSplitRenderConfig;
+#endif
} rendering_context;
/* Common base for input structs */
@@ -211,6 +218,10 @@ static void convertBitsBufferToInternalBitsBuff(
hBits->codec = outBits.config.codec;
hBits->pose_correction = outBits.config.poseCorrection;
hBits->codec_frame_size_ms = outBits.config.codec_frame_size_ms;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ hBits->isar_frame_size_ms = outBits.config.isar_frame_size_ms;
+ hBits->lc3plus_highres = outBits.config.lc3plusHighRes;
+#endif
return;
}
@@ -226,6 +237,10 @@ static void convertInternalBitsBuffToBitsBuffer(
hOutBits->config.codec = bits.codec;
hOutBits->config.poseCorrection = bits.pose_correction;
hOutBits->config.codec_frame_size_ms = bits.codec_frame_size_ms;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ hOutBits->config.isar_frame_size_ms = bits.isar_frame_size_ms;
+ hOutBits->config.lc3plusHighRes = bits.lc3plus_highres;
+#endif
return;
}
@@ -455,6 +470,9 @@ static rendering_context getRendCtx(
ctx.pOutSampleRate = &hIvasRend->sampleRateOut;
ctx.pHeadRotData = &hIvasRend->headRotData;
ctx.pSplitRendBFI = &hIvasRend->splitRendBFI;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ctx.pSplitRenderConfig = &hIvasRend->splitRenderConfig;
+#endif
return ctx;
}
@@ -477,8 +495,12 @@ static ivas_error getRendInputNumChannels(
static ivas_error updateSplitPostRendPanGains(
input_split_post_rend *inputSplitPostRend,
const AUDIO_CONFIG outConfig,
- ISAR_SPLIT_REND_CONFIG_DATA *hRendCfg,
- int16_t num_subframes )
+ ISAR_SPLIT_REND_CONFIG_DATA *hRendCfg
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ,
+ int16_t num_subframes
+#endif
+)
{
ivas_error error;
rendering_context rendCtx;
@@ -490,27 +512,34 @@ static ivas_error updateSplitPostRendPanGains(
rendCtx = inputSplitPostRend->base.ctx;
isar_renderSplitGetMultiBinPoseData( hRendCfg, &inputSplitPostRend->splitPostRendWrapper.multiBinPoseData, rendCtx.pHeadRotData->sr_pose_pred_axis );
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ config.high_res_mode_enabled = ( hRendCfg->lc3plus_highres != 0 );
+#endif
config.lc3plus_frame_duration_us = hRendCfg->codec_frame_size_ms * 1000;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ config.isar_frame_duration_us = hRendCfg->isar_frame_size_ms * 1000;
+#else
if ( num_subframes != MAX_PARAM_SPATIAL_SUBFRAMES )
{
if ( hRendCfg->codec == ISAR_SPLIT_REND_CODEC_LC3PLUS )
{
- config.ivas_frame_duration_us = ( hRendCfg->poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ) ? config.lc3plus_frame_duration_us * num_subframes : 20000;
+ config.isar_frame_duration_us = ( hRendCfg->poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ) ? config.lc3plus_frame_duration_us * num_subframes : 20000;
}
else
{
- config.ivas_frame_duration_us = ( hRendCfg->poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ) ? config.lc3plus_frame_duration_us : 20000;
+ config.isar_frame_duration_us = ( hRendCfg->poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ) ? config.lc3plus_frame_duration_us : 20000;
}
iNumLCLDIterationsPerFrame = 1;
}
else
{
- config.ivas_frame_duration_us = 20000;
+ config.isar_frame_duration_us = 20000;
}
+#endif
if ( hRendCfg->codec_frame_size_ms > 0 )
{
- iNumLCLDIterationsPerFrame = (int16_t) config.ivas_frame_duration_us / ( 1000 * hRendCfg->codec_frame_size_ms );
+ iNumLCLDIterationsPerFrame = (int16_t) config.isar_frame_duration_us / ( 1000 * hRendCfg->codec_frame_size_ms );
iNumLCLDIterationsPerFrame = max( 1, iNumLCLDIterationsPerFrame );
iNumBlocksPerFrame = CLDFB_NO_COL_MAX * hRendCfg->codec_frame_size_ms / 20;
}
@@ -552,8 +581,12 @@ static ivas_error setRendInputActiveSplitPostRend(
void *input,
const AUDIO_CONFIG inConfig,
const IVAS_REND_InputId id,
- ISAR_SPLIT_REND_CONFIG_DATA *hRendCfg,
- const int16_t num_subframes )
+ ISAR_SPLIT_REND_CONFIG_DATA *hRendCfg
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ,
+ const int16_t num_subframes
+#endif
+)
{
ivas_error error;
rendering_context rendCtx;
@@ -572,7 +605,12 @@ static ivas_error setRendInputActiveSplitPostRend(
initRendInputBase( &inputSplitPostRend->base, inConfig, id, rendCtx, inputSplitPostRend->bufferData, MAX_CLDFB_BIN_BUFFER_LENGTH );
inputSplitPostRend->numCachedSamples = 0;
- if ( ( error = updateSplitPostRendPanGains( inputSplitPostRend, outConfig, hRendCfg, num_subframes ) ) != IVAS_ERR_OK )
+ if ( ( error = updateSplitPostRendPanGains( inputSplitPostRend, outConfig, hRendCfg
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ,
+ num_subframes
+#endif
+ ) ) != IVAS_ERR_OK )
{
return error;
}
@@ -907,7 +945,12 @@ ivas_error ISAR_POST_REND_AddInput(
int32_t maxNumInputsOfType;
void *inputsArray;
int32_t inputStructSize;
- ivas_error ( *activateInput )( void *, AUDIO_CONFIG, IVAS_REND_InputId, ISAR_SPLIT_REND_CONFIG_DATA *, int16_t );
+ ivas_error ( *activateInput )( void *, AUDIO_CONFIG, IVAS_REND_InputId, ISAR_SPLIT_REND_CONFIG_DATA *
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ,
+ int16_t
+#endif
+ );
int32_t inputIndex;
/* Validate function arguments */
@@ -935,7 +978,12 @@ ivas_error ISAR_POST_REND_AddInput(
}
*inputId = makeInputId( inConfig, inputIndex );
- if ( ( error = activateInput( (uint8_t *) inputsArray + inputStructSize * inputIndex, inConfig, *inputId, &hIvasRend->splitRenderConfig, hIvasRend->num_subframes ) ) != IVAS_ERR_OK )
+ if ( ( error = activateInput( (uint8_t *) inputsArray + inputStructSize * inputIndex, inConfig, *inputId, &hIvasRend->splitRenderConfig
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ,
+ hIvasRend->num_subframes
+#endif
+ ) ) != IVAS_ERR_OK )
{
return error;
}
@@ -1136,6 +1184,9 @@ ivas_error ISAR_POST_REND_InitConfig(
hIvasRend->splitRenderConfig.hq_mode = 0;
hIvasRend->splitRenderConfig.codec_delay_ms = 0;
hIvasRend->splitRenderConfig.codec_frame_size_ms = 0; /* 0 means "use default for selected codec" */
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ hIvasRend->splitRenderConfig.isar_frame_size_ms = 0; /* 0 means "use default for selected codec" */
+#endif
hIvasRend->splitRenderConfig.codec = ISAR_SPLIT_REND_CODEC_DEFAULT;
hIvasRend->splitRenderConfig.poseCorrectionMode = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB;
hIvasRend->splitRenderConfig.rendererSelection = ISAR_SPLIT_REND_RENDERER_SELECTION_DEFAULT;
@@ -1170,6 +1221,9 @@ int16_t ISAR_POST_REND_GetRenderConfig(
splitRenderConfig->hq_mode = 0;
splitRenderConfig->codec_delay_ms = 0;
splitRenderConfig->codec_frame_size_ms = 0; /* 0 means "use default for selected codec" */
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ splitRenderConfig->isar_frame_size_ms = 0; /* 0 means "use default for selected codec" */
+#endif
splitRenderConfig->codec = ISAR_SPLIT_REND_CODEC_DEFAULT;
splitRenderConfig->poseCorrectionMode = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB;
splitRenderConfig->rendererSelection = hRCin.rendererSelection;
@@ -1286,12 +1340,18 @@ static ivas_error splitBinLc3plusDecode(
ISAR_SPLIT_POST_REND_WRAPPER *hSplitBin,
ISAR_SPLIT_REND_BITS_HANDLE bits,
float outputBuffer[BINAURAL_CHANNELS][L_FRAME48k],
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
ISAR_SPLIT_REND_POSE_CORRECTION_MODE pose_correction,
+#endif
const int16_t SplitRendBFI )
{
ivas_error error;
float *channel_ptrs[MAX_HEAD_ROT_POSES * 2];
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ int32_t lc3plusBitstreamSize;
+#else
int32_t lc3plusBitrateId, lc3plusBitstreamSize;
+#endif
push_wmops( "splitBinLc3plusDecode" );
assert( hSplitBin->hLc3plusDec != NULL );
@@ -1308,9 +1368,15 @@ static ivas_error splitBinLc3plusDecode(
{
++bits->bits_read;
}
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ /* Size is in bytes */
+ assert( ( bits->bits_written - bits->bits_read ) % 8 == 0 );
+ lc3plusBitstreamSize = ( bits->bits_written - bits->bits_read ) / 8;
+#else
/* Read LC3plus bitstream size info */
lc3plusBitrateId = ISAR_SPLIT_REND_BITStream_read_int32( bits, 8 );
- lc3plusBitstreamSize = isar_get_lc3plus_size_from_id( (int8_t) lc3plusBitrateId, pose_correction, (int16_t) ( hSplitBin->hLc3plusDec->config.ivas_frame_duration_us / 1000 ) );
+ lc3plusBitstreamSize = isar_get_lc3plus_size_from_id( (int8_t) lc3plusBitrateId, pose_correction, (int16_t) ( hSplitBin->hLc3plusDec->config.isar_frame_duration_us / 1000 ) );
+#endif
if ( ( error = ISAR_LC3PLUS_DEC_Decode( hSplitBin->hLc3plusDec, &bits->bits_buf[bits->bits_read / 8], lc3plusBitstreamSize, channel_ptrs ) ) != IVAS_ERR_OK )
{
@@ -1353,7 +1419,9 @@ static ivas_error renderSplitBinauralWithPostRot(
int16_t outBufNumSamplesPerChannel, outBufNumColPerChannel;
int16_t numSamplesPerChannelCacheSize, numColPerChannelCacheSize;
float *readPtr, *writePtr;
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
uint32_t ivas_frame_duration_us;
+#endif
int16_t iNumBlocksPerFrame, iNumLCLDIterationsPerFrame;
const ISAR_POST_REND_HeadRotData *pHeadRotData;
@@ -1361,15 +1429,24 @@ static ivas_error renderSplitBinauralWithPostRot(
push_wmops( "renderSplitBinauralWithPostRot" );
error = IVAS_ERR_OK;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ if ( outAudio.config.numSamplesPerChannel / *splitBinInput->base.ctx.pOutSampleRate > splitBinInput->hBits->config.isar_frame_size_ms )
+ {
+ return IVAS_ERR_INTERNAL_FATAL;
+ }
+#endif
+
pHeadRotData = splitBinInput->base.ctx.pHeadRotData;
hSplitBin = &splitBinInput->splitPostRendWrapper;
convertBitsBufferToInternalBitsBuff( *splitBinInput->hBits, &bits );
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
ivas_frame_duration_us = 20000;
if ( splitBinInput->splitPostRendWrapper.hLc3plusDec != NULL )
{
- ivas_frame_duration_us = splitBinInput->splitPostRendWrapper.hLc3plusDec->config.ivas_frame_duration_us;
+ ivas_frame_duration_us = splitBinInput->splitPostRendWrapper.hLc3plusDec->config.isar_frame_duration_us;
}
+#endif
iNumLCLDIterationsPerFrame = 1;
iNumBlocksPerFrame = CLDFB_NO_COL_MAX;
@@ -1414,9 +1491,13 @@ static ivas_error renderSplitBinauralWithPostRot(
{
isPostRendInputCldfb = 1;
}
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ numSamplesPerChannelCacheSize = (int16_t) ( *splitBinInput->base.ctx.pOutSampleRate * bits.isar_frame_size_ms / 1000 ) - outBufNumSamplesPerChannel;
+#else
preRendFrameSize_ms = (int16_t) ( ivas_frame_duration_us ) / 1000;
numSamplesPerChannelCacheSize = (int16_t) ( *splitBinInput->base.ctx.pOutSampleRate * ( preRendFrameSize_ms - bits.codec_frame_size_ms ) / 1000 );
+#endif
outBufNumColPerChannel = MAX_PARAM_SPATIAL_SUBFRAMES;
numColPerChannelCacheSize = ( iNumBlocksPerFrame * iNumLCLDIterationsPerFrame ) - outBufNumColPerChannel;
@@ -1459,12 +1540,16 @@ static ivas_error renderSplitBinauralWithPostRot(
}
else
{
- if ( ( error = splitBinLc3plusDecode( hSplitBin, &bits, tmpCrendBuffer, bits.pose_correction, SplitRendBFI ) ) != IVAS_ERR_OK )
+ if ( ( error = splitBinLc3plusDecode( hSplitBin, &bits, tmpCrendBuffer,
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ bits.pose_correction,
+#endif
+ SplitRendBFI ) ) != IVAS_ERR_OK )
{
return error;
}
- /* cache the remaining 15ms */
+ /* cache the remaining decoded audio */
splitBinInput->numCachedSamples = numSamplesPerChannelCacheSize;
mvr2r( &tmpCrendBuffer[0][outBufNumSamplesPerChannel], splitBinInput->bufferData, numSamplesPerChannelCacheSize );
mvr2r( &tmpCrendBuffer[1][outBufNumSamplesPerChannel], splitBinInput->bufferData + numSamplesPerChannelCacheSize, numSamplesPerChannelCacheSize );
@@ -1512,7 +1597,11 @@ static ivas_error renderSplitBinauralWithPostRot(
copyBufferTo2dArray( splitBinInput->base.inputBuffer, tmpCrendBuffer );
if ( splitBinInput->numCachedSamples == 0 )
{
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ preRendFrameSize_ms = splitBinInput->base.ctx.pSplitRenderConfig->isar_frame_size_ms;
+#else
preRendFrameSize_ms = (int16_t) ( ivas_frame_duration_us ) / 1000;
+#endif
numSamplesPerChannelCacheSize = (int16_t) ( *splitBinInput->base.ctx.pOutSampleRate * preRendFrameSize_ms / 1000 );
numSamplesPerChannelCacheSize -= outAudio.config.numSamplesPerChannel;
splitBinInput->numCachedSamples = numSamplesPerChannelCacheSize;
@@ -1769,7 +1858,12 @@ ivas_error ISAR_REND_SetSplitRendBitstreamHeader(
ISAR_POST_REND_HANDLE hIvasRend, /* i/o: IVAS renderer handle */
const ISAR_SPLIT_REND_CODEC codec, /* o: codec setting */
const ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrection, /* o: pose correction mode */
- const int16_t codec_frame_size_ms /* o: codec frame size setting */
+ const int16_t codec_frame_size_ms /* i: codec frame size setting */
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ,
+ const int16_t isar_frame_size_ms, /* i: isar codec frame size setting */
+ const int16_t lc3plus_highres /* i: LC3plus Hig-Res setting. Ignored if codec is not LC3plus */
+#endif
)
{
if ( hIvasRend == NULL )
@@ -1777,8 +1871,14 @@ ivas_error ISAR_REND_SetSplitRendBitstreamHeader(
return IVAS_ERR_UNEXPECTED_NULL_POINTER;
}
hIvasRend->splitRenderConfig.codec = codec;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ hIvasRend->splitRenderConfig.isar_frame_size_ms = isar_frame_size_ms;
+#endif
hIvasRend->splitRenderConfig.codec_frame_size_ms = codec_frame_size_ms;
hIvasRend->splitRenderConfig.poseCorrectionMode = poseCorrection;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ hIvasRend->splitRenderConfig.lc3plus_highres = lc3plus_highres;
+#endif
return IVAS_ERR_OK;
}
diff --git a/lib_isar/lib_isar_post_rend.h b/lib_isar/lib_isar_post_rend.h
index 221e0b26ff4e7d370158d3aabf0f0e66d54f237b..7c06895e689c2412ce69baa182445268025bab0a 100644
--- a/lib_isar/lib_isar_post_rend.h
+++ b/lib_isar/lib_isar_post_rend.h
@@ -62,6 +62,10 @@ typedef struct
ISAR_SPLIT_REND_CODEC codec;
ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrection;
int16_t codec_frame_size_ms;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ int16_t isar_frame_size_ms;
+ int16_t lc3plusHighRes;
+#endif
} ISAR_POST_REND_BitstreamBufferConfig;
typedef struct
@@ -202,7 +206,12 @@ ivas_error ISAR_REND_SetSplitRendBitstreamHeader(
ISAR_POST_REND_HANDLE hIvasRend, /* i/o: IVAS renderer handle */
const ISAR_SPLIT_REND_CODEC codec, /* o: codec setting */
const ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrection, /* o: pose correction mode */
- const int16_t codec_frame_size_ms /* o: codec frame size setting */
+ const int16_t codec_frame_size_ms /* i: codec frame size setting */
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ,
+ const int16_t isar_frame_size_ms, /* i: isar frame size setting */
+ const int16_t lc3plus_highres /* i: LC3plus Hig-Res setting. Ignored if codec is not LC3plus */
+#endif
);
#ifdef DEBUGGING
diff --git a/lib_isar/lib_isar_pre_rend.c b/lib_isar/lib_isar_pre_rend.c
index 19a7345b98ec89d7c78ea4c9e643b6eab60b4dc5..c7d66e12632509132c286ceae070080fae2bdb40 100644
--- a/lib_isar/lib_isar_pre_rend.c
+++ b/lib_isar/lib_isar_pre_rend.c
@@ -82,7 +82,11 @@ ivas_error ISAR_PRE_REND_open(
const int32_t output_Fs, /* i: output sampling rate */
const int16_t cldfb_in_flag, /* i: Flag to indicate CLDFB or time doamin input */
const int16_t pcm_out_flag, /* i: Flag to indicate PCM output */
- const int16_t num_subframes, /* i: number of subframes */
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ const IVAS_RENDER_FRAMESIZE ivas_frame_size, /* i: IVAS frame size */
+#else
+ const int16_t num_subframes, /* i: number of subframes */
+#endif
const int16_t mixed_td_cldfb_flag /* i: Flag to indicate combined TD and CLDFB input */
)
{
@@ -91,7 +95,19 @@ ivas_error ISAR_PRE_REND_open(
int16_t cldfb_in_flag_local = cldfb_in_flag;
- if ( ( error = isar_split_rend_choose_default_codec( &( pSplitRendConfig->codec ), &pSplitRendConfig->codec_frame_size_ms, cldfb_in_flag_local, pcm_out_flag, (int16_t) num_subframes ) ) != IVAS_ERR_OK )
+ if ( ( error = isar_split_rend_choose_default_codec( &( pSplitRendConfig->codec ),
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ &pSplitRendConfig->isar_frame_size_ms,
+#endif
+ &pSplitRendConfig->codec_frame_size_ms,
+ cldfb_in_flag_local,
+ pcm_out_flag, (int16_t)
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ivas_frame_size
+#else
+ num_subframes
+#endif
+ ) ) != IVAS_ERR_OK )
{
return error;
}
@@ -176,7 +192,13 @@ ivas_error ISAR_PRE_REND_open(
{
if ( pSplitRendConfig->codec == ISAR_SPLIT_REND_CODEC_LC3PLUS )
{
- if ( ( error = split_renderer_open_lc3plus( hSplitBinRend, pSplitRendConfig, output_Fs, num_subframes ) ) != IVAS_ERR_OK )
+ if ( ( error = split_renderer_open_lc3plus( hSplitBinRend, pSplitRendConfig, output_Fs,
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ivas_frame_size
+#else
+ num_subframes
+#endif
+ ) ) != IVAS_ERR_OK )
{
return error;
}
@@ -301,8 +323,11 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural(
const IVAS_QUATERNION headPosition, /* i: head rotation QUATERNION */
const int32_t SplitRendBitRate, /* i: Split renderer bitrate */
ISAR_SPLIT_REND_CODEC splitCodec, /* i/o: Split renderer codec */
- int16_t codec_frame_size_ms, /* i/o: Split renderer codec framesize */
- ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: Split renderer codec framesize */
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ const int16_t isar_frame_size_ms, /* i: ISAR framesize */
+#endif
+ int16_t codec_frame_size_ms, /* i/o: ISAR transport codec framesize */
+ ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: ISAR bits struct handle */
float Cldfb_In_BinReal[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: CLDFB real buffer */
float Cldfb_In_BinImag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: CLDFB imag buffer */
const int16_t max_bands, /* i: CLDFB bands */
@@ -314,7 +339,11 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural(
)
{
ivas_error error;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ int32_t bit_len, target_md_bits, available_bits;
+#else
int32_t bit_len, target_md_bits, actual_md_bits, available_bits;
+#endif
error = IVAS_ERR_OK;
push_wmops( "isar_pre_rend_MultiBinToSplitBinaural" );
@@ -329,7 +358,19 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural(
{
/*TD input*/
/*if CLDFB handles have been allocated then assume valid multi binaural input in out[][] buffer and perform CLDFB analysis*/
- error = isar_renderMultiTDBinToSplitBinaural( hSplitBin, headPosition, SplitRendBitRate, codec_frame_size_ms, pBits, max_bands, output, low_res_pre_rend_rot, pcm_out_flag, ro_md_flag );
+ error = isar_renderMultiTDBinToSplitBinaural( hSplitBin,
+ headPosition,
+ SplitRendBitRate,
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ isar_frame_size_ms,
+#endif
+ codec_frame_size_ms,
+ pBits,
+ max_bands,
+ output,
+ low_res_pre_rend_rot,
+ pcm_out_flag,
+ ro_md_flag );
pop_wmops();
return error;
@@ -341,12 +382,16 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural(
lc3plusTimeAlignCldfbPoseCorr( hSplitBin, Cldfb_In_BinReal, Cldfb_In_BinImag );
}
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
actual_md_bits = pBits->bits_written;
+#endif
if ( hSplitBin->multiBinPoseData.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB )
{
target_md_bits = isar_get_split_rend_md_target_brate( SplitRendBitRate, pcm_out_flag ) * L_FRAME48k / 48000;
+#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
actual_md_bits = pBits->bits_written;
+#endif
isar_rend_CldfbSplitPreRendProcess( hSplitBin->hBinHrSplitPreRend, headPosition, &hSplitBin->multiBinPoseData, Cldfb_In_BinReal, Cldfb_In_BinImag, pBits, target_md_bits, low_res_pre_rend_rot, ro_md_flag );
}
@@ -359,15 +404,19 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural(
if ( splitCodec == ISAR_SPLIT_REND_CODEC_LCLD )
{
available_bits = ( SplitRendBitRate * hSplitBin->hSplitBinLCLDEnc->iNumBlocks * hSplitBin->hSplitBinLCLDEnc->iNumIterations ) / ( 16 * FRAMES_PER_SEC );
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ available_bits -= pBits->bits_written;
+#else
actual_md_bits = pBits->bits_written - actual_md_bits;
available_bits -= actual_md_bits;
+#endif
pBits->codec_frame_size_ms = codec_frame_size_ms;
isar_splitBinLCLDEncProcess( hSplitBin->hSplitBinLCLDEnc, Cldfb_In_BinReal, Cldfb_In_BinImag, available_bits, pBits );
}
else
{
int16_t ch, slot_idx, num_slots, ivas_fs;
- ivas_fs = (int16_t) hSplitBin->hLc3plusEnc->config.ivas_frame_duration_us / 1000;
+ ivas_fs = (int16_t) hSplitBin->hLc3plusEnc->config.isar_frame_duration_us / 1000;
num_slots = (int16_t) ( CLDFB_NO_COL_MAX * ivas_fs ) / 20;
/* CLDFB synthesis of main pose */
for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
@@ -384,7 +433,12 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural(
cldfbSynthesis( Cldfb_In_BinReal_p, Cldfb_In_BinImag_p, output[ch], hSplitBin->hCldfbHandles->cldfbSyn[0]->no_channels * num_slots, hSplitBin->hCldfbHandles->cldfbSyn[ch] );
}
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ available_bits = ( SplitRendBitRate / FRAMES_PER_SEC ) - pBits->bits_written;
+ if ( ( error = splitRendLc3plusEncodeAndWrite( hSplitBin, pBits, available_bits, output ) ) != IVAS_ERR_OK )
+#else
if ( ( error = splitRendLc3plusEncodeAndWrite( hSplitBin, pBits, SplitRendBitRate, output ) ) != IVAS_ERR_OK )
+#endif
{
return error;
}
@@ -425,7 +479,7 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural(
}
else
{
- bit_len = hSplitBin->hLc3plusEnc->config.ivas_frame_duration_us / 1000;
+ bit_len = hSplitBin->hLc3plusEnc->config.isar_frame_duration_us / 1000;
bit_len = SplitRendBitRate * bit_len / 1000;
}
}
diff --git a/lib_isar/lib_isar_pre_rend.h b/lib_isar/lib_isar_pre_rend.h
index 72169d6c35d001ddbf6be4e5274bccdffd4f2d03..a1e658ac123ba0dd78dbec8b1e75be99206e2a7e 100644
--- a/lib_isar/lib_isar_pre_rend.h
+++ b/lib_isar/lib_isar_pre_rend.h
@@ -48,7 +48,11 @@ ivas_error ISAR_PRE_REND_open(
const int32_t output_Fs, /* i: output sampling rate */
const int16_t cldfb_in_flag, /* i: Flag to indicate CLDFB or time doamin input */
const int16_t pcm_out_flag, /* i: Flag to indicate PCM output */
- const int16_t num_subframes, /* i: number of subframes */
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ const IVAS_RENDER_FRAMESIZE ivas_frame_size, /* i: IVAS frame size */
+#else
+ const int16_t num_subframes, /* i: number of subframes */
+#endif
const int16_t mixed_td_cldfb_flag /* i: Flag to indicate combined TD and CLDFB input */
);
@@ -68,8 +72,11 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural(
const IVAS_QUATERNION headPosition, /* i: head rotation QUATERNION */
const int32_t SplitRendBitRate, /* i: Split renderer bitrate */
ISAR_SPLIT_REND_CODEC splitCodec, /* i/o: Split renderer codec */
- int16_t codec_frame_size_ms, /* i/o: Split renderer codec framesize */
- ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: Split renderer codec framesize */
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ const int16_t isar_frame_size_ms, /* i: ISAR framesize */
+#endif
+ int16_t codec_frame_size_ms, /* i/o: ISAR transport codec framesize */
+ ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: ISAR bits struct handle */
float Cldfb_In_BinReal[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: CLDFB real buffer */
float Cldfb_In_BinImag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: CLDFB imag buffer */
const int16_t max_bands, /* i: CLDFB bands */
diff --git a/lib_rend/ivas_render_config.c b/lib_rend/ivas_render_config.c
index e9c9fa749aec261cf80fb46ea90632b72588a3f3..0b61ef7ab46c28994f33f1568a4037b2b4a37be7 100644
--- a/lib_rend/ivas_render_config.c
+++ b/lib_rend/ivas_render_config.c
@@ -136,10 +136,16 @@ ivas_error ivas_render_config_init_from_rom(
( *hRenderConfig )->split_rend_config.dof = 3;
( *hRenderConfig )->split_rend_config.hq_mode = 0;
( *hRenderConfig )->split_rend_config.codec_delay_ms = 0;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ( *hRenderConfig )->split_rend_config.isar_frame_size_ms = 20;
+#endif
( *hRenderConfig )->split_rend_config.codec_frame_size_ms = 0; /* 0 means "use default for selected codec" */
( *hRenderConfig )->split_rend_config.codec = ISAR_SPLIT_REND_CODEC_DEFAULT;
( *hRenderConfig )->split_rend_config.poseCorrectionMode = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB;
( *hRenderConfig )->split_rend_config.rendererSelection = ISAR_SPLIT_REND_RENDERER_SELECTION_DEFAULT;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ( *hRenderConfig )->split_rend_config.lc3plus_highres = 0;
+#endif
#endif
return IVAS_ERR_OK;
diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c
index a0d31fa8a642e38b1649da2a2288357dea523924..1ade3c85f43d471ce4a6d5820a588983a94bc7b5 100644
--- a/lib_rend/lib_rend.c
+++ b/lib_rend/lib_rend.c
@@ -4378,10 +4378,16 @@ int16_t IVAS_REND_GetRenderConfig(
hRCout->split_rend_config.dof = 3;
hRCout->split_rend_config.hq_mode = 0;
hRCout->split_rend_config.codec_delay_ms = 0;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ hRCout->split_rend_config.isar_frame_size_ms = 20;
+#endif
hRCout->split_rend_config.codec_frame_size_ms = 0; /* 0 means "use default for selected codec" */
hRCout->split_rend_config.codec = ISAR_SPLIT_REND_CODEC_DEFAULT;
hRCout->split_rend_config.poseCorrectionMode = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB;
hRCout->split_rend_config.rendererSelection = hRCin->split_rend_config.rendererSelection;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ hRCout->split_rend_config.lc3plus_highres = 0;
+#endif
#endif
hRCout->roomAcoustics.use_er = hRCin->roomAcoustics.use_er;
@@ -7847,8 +7853,23 @@ static ivas_error getSamplesInternal(
}
}
- if ( ( error = ISAR_PRE_REND_MultiBinToSplitBinaural( &hIvasRend->splitRendWrapper, hIvasRend->headRotData.headPositions[0], hIvasRend->hRendererConfig->split_rend_config.splitRendBitRate, hIvasRend->hRendererConfig->split_rend_config.codec, hIvasRend->hRendererConfig->split_rend_config.codec_frame_size_ms,
- &bits, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, ( const int16_t )( ( BINAURAL_MAXBANDS * hIvasRend->sampleRateOut ) / 48000 ), tmpBinaural, 1, cldfb_in_flag, ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ? 1 : 0, ro_md_flag ) ) != IVAS_ERR_OK )
+ if ( ( error = ISAR_PRE_REND_MultiBinToSplitBinaural( &hIvasRend->splitRendWrapper,
+ hIvasRend->headRotData.headPositions[0],
+ hIvasRend->hRendererConfig->split_rend_config.splitRendBitRate,
+ hIvasRend->hRendererConfig->split_rend_config.codec,
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ hIvasRend->hRendererConfig->split_rend_config.isar_frame_size_ms,
+#endif
+ hIvasRend->hRendererConfig->split_rend_config.codec_frame_size_ms,
+ &bits,
+ Cldfb_RealBuffer_Binaural,
+ Cldfb_ImagBuffer_Binaural,
+ ( const int16_t )( ( BINAURAL_MAXBANDS * hIvasRend->sampleRateOut ) / 48000 ),
+ tmpBinaural,
+ 1,
+ cldfb_in_flag,
+ ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ? 1 : 0,
+ ro_md_flag ) ) != IVAS_ERR_OK )
{
return error;
}
@@ -7941,6 +7962,10 @@ ivas_error IVAS_REND_GetSplitRendBitstreamHeader(
ISAR_SPLIT_REND_CODEC *pCodec, /* o: pointer to codec setting */
ISAR_SPLIT_REND_POSE_CORRECTION_MODE *poseCorrection, /* o: pointer to pose correction mode */
int16_t *pCodec_frame_size_ms /* o: pointer to codec frame size setting */
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ,
+ int16_t *pIsar_frame_size_ms /* o: pointer to isar frame size setting */
+#endif
)
{
if ( hIvasRend == NULL || hIvasRend->hRendererConfig == NULL )
@@ -7949,6 +7974,9 @@ ivas_error IVAS_REND_GetSplitRendBitstreamHeader(
}
*pCodec = hIvasRend->hRendererConfig->split_rend_config.codec;
*pCodec_frame_size_ms = hIvasRend->hRendererConfig->split_rend_config.codec_frame_size_ms;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ *pIsar_frame_size_ms = hIvasRend->hRendererConfig->split_rend_config.isar_frame_size_ms;
+#endif
*poseCorrection = hIvasRend->hRendererConfig->split_rend_config.poseCorrectionMode;
return IVAS_ERR_OK;
}
diff --git a/lib_rend/lib_rend.h b/lib_rend/lib_rend.h
index e3a1bd614701a62c2e5231791ff5b4dcfcd89973..768a53cfa52e2d0126961a7eb11032c16a00f727 100644
--- a/lib_rend/lib_rend.h
+++ b/lib_rend/lib_rend.h
@@ -62,6 +62,10 @@ typedef struct
ISAR_SPLIT_REND_CODEC codec;
ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrection;
int16_t codec_frame_size_ms;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ int16_t isar_frame_size_ms;
+ int16_t lc3plus_highres;
+#endif
} IVAS_REND_BitstreamBufferConfig;
typedef struct
{
@@ -271,7 +275,11 @@ ivas_error IVAS_REND_GetSplitRendBitstreamHeader(
IVAS_REND_HANDLE hIvasRend, /* i/o: IVAS renderer handle */
ISAR_SPLIT_REND_CODEC *pCodec, /* o: pointer to codec setting */
ISAR_SPLIT_REND_POSE_CORRECTION_MODE *poseCorrection, /* o: pointer to pose correction mode */
- int16_t *pCodec_frame_size_ms /* o: pointer to codec frame size setting */
+ int16_t *pCodec_frame_size_ms /* o: pointer to codec frame size setting */
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ,
+ int16_t *pIsar_frame_size_ms /* o: pointer to isar frame size setting */
+#endif
);
#endif
diff --git a/lib_util/render_config_reader.c b/lib_util/render_config_reader.c
index 981f2614204202cd2122b3e835b27a5291171d93..01a72d0598e5b278208c322fecefc1a5550e31a0 100644
--- a/lib_util/render_config_reader.c
+++ b/lib_util/render_config_reader.c
@@ -2561,6 +2561,15 @@ ivas_error RenderConfigReader_read(
errorHandler( pValue, ERROR_VALUE_INVALID );
}
}
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ else if ( strcmp( item, "LC3PLUS_HIGHRES" ) == 0 )
+ {
+ if ( !sscanf( pValue, "%hd", &hRenderConfig->split_rend_config.lc3plus_highres ) )
+ {
+ errorHandler( item, ERROR_VALUE_INVALID );
+ }
+ }
+#endif
#ifdef DEBUGGING
else
{
diff --git a/lib_util/split_render_file_read_write.c b/lib_util/split_render_file_read_write.c
index 714467b1189e88ce38410a7e656b6623036f7f1e..6a676235be767e8ca22ce41af3cc77db9b583f54 100644
--- a/lib_util/split_render_file_read_write.c
+++ b/lib_util/split_render_file_read_write.c
@@ -66,7 +66,14 @@ ivas_error split_rend_reader_open(
char *filename,
ISAR_SPLIT_REND_CODEC *codec,
ISAR_SPLIT_REND_POSE_CORRECTION_MODE *poseCorrection,
- int16_t *codec_frame_size_ms )
+ int16_t *codec_frame_size_ms
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ,
+ int16_t *isar_frame_size_ms,
+ int32_t *sampling_rate,
+ int16_t *lc3plus_highres
+#endif
+)
{
SplitFileReadWrite *hSplitRendFileReadWrite;
size_t header_len, h;
@@ -113,11 +120,28 @@ ivas_error split_rend_reader_open(
{
return IVAS_ERR_FAILED_FILE_READ;
}
- /* read frame size signalling */
+ /* read transport codec frame size signalling */
if ( fread( codec_frame_size_ms, sizeof( *codec_frame_size_ms ), 1, hSplitRendFileReadWrite->file ) != 1 )
{
return IVAS_ERR_FAILED_FILE_READ;
}
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ /* read isar bitstream frame size signalling */
+ if ( fread( isar_frame_size_ms, sizeof( *isar_frame_size_ms ), 1, hSplitRendFileReadWrite->file ) != 1 )
+ {
+ return IVAS_ERR_FAILED_FILE_READ;
+ }
+ /* read sampling rate signalling */
+ if ( fread( sampling_rate, sizeof( *sampling_rate ), 1, hSplitRendFileReadWrite->file ) != 1 )
+ {
+ return IVAS_ERR_FAILED_FILE_READ;
+ }
+ /* read LC3plus highres signalling */
+ if ( fread( lc3plus_highres, sizeof( *lc3plus_highres ), 1, hSplitRendFileReadWrite->file ) != 1 )
+ {
+ return IVAS_ERR_FAILED_FILE_READ;
+ }
+#endif
*hhSplitRendFileReadWrite = hSplitRendFileReadWrite;
@@ -138,7 +162,14 @@ ivas_error split_rend_writer_open(
const int32_t delayTimeScale,
ISAR_SPLIT_REND_CODEC codec,
ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrection,
- int16_t codec_frame_size_ms )
+ int16_t codec_frame_size_ms
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ,
+ const int16_t isar_frame_size_ms,
+ const int32_t sampling_rate,
+ const int16_t lc3plus_highres
+#endif
+)
{
SplitFileReadWrite *hSplitRendFileReadWrite;
size_t header_len, h;
@@ -184,11 +215,28 @@ ivas_error split_rend_writer_open(
{
return IVAS_ERR_FAILED_FILE_WRITE;
}
- /* Write frame size signalling */
+ /* Write transport codec frame size signalling */
if ( fwrite( &codec_frame_size_ms, sizeof( codec_frame_size_ms ), 1, hSplitRendFileReadWrite->file ) != 1 )
{
return IVAS_ERR_FAILED_FILE_WRITE;
}
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ /* Write isar bit stream frame size signalling */
+ if ( fwrite( &isar_frame_size_ms, sizeof( isar_frame_size_ms ), 1, hSplitRendFileReadWrite->file ) != 1 )
+ {
+ return IVAS_ERR_FAILED_FILE_WRITE;
+ }
+ /* Write sampling rate signalling */
+ if ( fwrite( &sampling_rate, sizeof( sampling_rate ), 1, hSplitRendFileReadWrite->file ) != 1 )
+ {
+ return IVAS_ERR_FAILED_FILE_WRITE;
+ }
+ /* Write LC3plus highres signalling */
+ if ( fwrite( &lc3plus_highres, sizeof( lc3plus_highres ), 1, hSplitRendFileReadWrite->file ) != 1 )
+ {
+ return IVAS_ERR_FAILED_FILE_WRITE;
+ }
+#endif
*hhSplitRendFileReadWrite = hSplitRendFileReadWrite;
diff --git a/lib_util/split_render_file_read_write.h b/lib_util/split_render_file_read_write.h
index 69d50c4951eb0824afd903772befa170ecdd3b5a..ea277cfc52a57caf2e0412561306569441494b02 100644
--- a/lib_util/split_render_file_read_write.h
+++ b/lib_util/split_render_file_read_write.h
@@ -44,7 +44,14 @@ ivas_error split_rend_reader_open(
char *filename,
ISAR_SPLIT_REND_CODEC *codec,
ISAR_SPLIT_REND_POSE_CORRECTION_MODE *poseCorrection,
- int16_t *codec_frame_size_ms );
+ int16_t *codec_frame_size_ms
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ,
+ int16_t *isar_frame_size_ms,
+ int32_t *sampling_rate,
+ int16_t *lc3plus_highres
+#endif
+);
/* Allocates and initializes a a split renderer writer instance */
@@ -55,7 +62,14 @@ ivas_error split_rend_writer_open(
const int32_t delayTimeScale,
ISAR_SPLIT_REND_CODEC codec,
ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrection,
- int16_t codec_frame_size_ms );
+ int16_t codec_frame_size_ms
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ,
+ const int16_t isar_frame_size_ms,
+ const int32_t sampling_rate,
+ const int16_t lc3plus_highres
+#endif
+);
/* Closes the split renderer reader/writer and deallocates memory */
diff --git a/scripts/split_rendering/lc3plus/ivas_lc3plus_unit_test.c b/scripts/split_rendering/lc3plus/ivas_lc3plus_unit_test.c
index 048b18eef3b22893688c327e9ce3fcb540357784..53c7c45165aab75e1f11bf81e7b8c2f16e19cf1d 100644
--- a/scripts/split_rendering/lc3plus/ivas_lc3plus_unit_test.c
+++ b/scripts/split_rendering/lc3plus/ivas_lc3plus_unit_test.c
@@ -30,6 +30,7 @@ the United Nations Convention on Contracts on the International Sales of Goods.
*******************************************************************************************************/
+#include
#include
#include
#include "options.h"
@@ -37,15 +38,21 @@ the United Nations Convention on Contracts on the International Sales of Goods.
#include "isar_lc3plus_common.h"
#include "isar_lc3plus_dec.h"
#include "ivas_error_utils.h"
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+#include "lc3.h"
+#endif
#ifdef SPLIT_REND_WITH_HEAD_ROT
-
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+#define MAX_SAMPLES_PER_CHANNEL 960 / 4
+#else
#define MAX_SAMPLES_PER_CHANNEL 960
+#endif
+#define DEFAULT_BPS 256000
-static int encodeAndDecodeOneStereoFrame( LC3PLUS_CONFIG config )
+static int encodeAndDecodeOneStereoFrame( LC3PLUS_CONFIG config, uint32_t bps )
{
ivas_error err;
- uint32_t bps = 128000;
int32_t encDelay = -1;
int32_t decDelay = -1;
@@ -59,15 +66,17 @@ static int encodeAndDecodeOneStereoFrame( LC3PLUS_CONFIG config )
err = ISAR_LC3PLUS_ENC_GetDelay( encHandle, &encDelay );
if ( IVAS_ERR_OK != err )
{
+ ISAR_LC3PLUS_ENC_Close( &encHandle );
return err;
}
if ( encDelay == -1 || encDelay == 0 )
{
+ ISAR_LC3PLUS_ENC_Close( &encHandle );
return IVAS_ERROR( IVAS_ERR_INTERNAL, "encDelay is zero or uninitialized\n" );
}
/* encode one frame */
- int16_t numSamplesPerChannels = config.samplerate / ( 1000000 / config.ivas_frame_duration_us );
+ int16_t numSamplesPerChannels = config.samplerate / ( 1000000 / config.isar_frame_duration_us );
float *pcm_in[2];
float pcm_in_ch1[MAX_SAMPLES_PER_CHANNEL * sizeof( float )];
memset( pcm_in_ch1, 0, numSamplesPerChannels * sizeof( float ) );
@@ -79,14 +88,38 @@ static int encodeAndDecodeOneStereoFrame( LC3PLUS_CONFIG config )
int32_t bitstreamSizePerIvasFrame = 0;
err = ISAR_LC3PLUS_ENC_GetOutputBitstreamSize( encHandle, &bitstreamSizePerIvasFrame );
if ( IVAS_ERR_OK != err )
+ {
+ ISAR_LC3PLUS_ENC_Close( &encHandle );
return err;
-
+ }
uint8_t *bitstream_out = malloc( bitstreamSizePerIvasFrame );
memset( bitstream_out, 0, bitstreamSizePerIvasFrame );
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ int perChannelBitrate = lc3plus_enc_get_real_bitrate(encHandle->handles[0]);
+ int perLc3plusFrameDataBlockOctets = encHandle->num_ftds * perChannelBitrate / 8 / (1000*1000/config.lc3plus_frame_duration_us);
+ int targetOctets = bps / 8 / (1000*1000/config.isar_frame_duration_us);
+ printf("IVAS-FS=%i LC3plus-FS=%i ch=%i targetBps=%i targetOctets=%i\n", config.isar_frame_duration_us, config.lc3plus_frame_duration_us, config.channels, bps, targetOctets);
+ printf(" coreBps=%i corePerChBps=%i coreCodecOctets=%i nFtds=%i \n", perChannelBitrate * encHandle->num_encs, perChannelBitrate, perLc3plusFrameDataBlockOctets, encHandle->num_ftds);
+ int pfOctets = bitstreamSizePerIvasFrame - perLc3plusFrameDataBlockOctets;
+ int pfBps = pfOctets * 8 * (1000*1000 / config.isar_frame_duration_us);
+ printf(" payloadFormatBps=%i payloadFormatOctets=%i \n\n", pfBps, pfOctets);
+ if(pfBps <= 0)
+ {
+ ISAR_LC3PLUS_ENC_Close( &encHandle );
+ return err;
+ }
+
+ err = ISAR_LC3PLUS_ENC_Encode( encHandle, pcm_in, bitstream_out, bitstreamSizePerIvasFrame );
+#else
err = ISAR_LC3PLUS_ENC_Encode( encHandle, pcm_in, bitstream_out );
+#endif
if ( IVAS_ERR_OK != err )
+ {
+ ISAR_LC3PLUS_ENC_Close( &encHandle );
+ free( bitstream_out );
return err;
+ }
ISAR_LC3PLUS_ENC_Close( &encHandle );
/* decode one frame */
@@ -98,16 +131,21 @@ static int encodeAndDecodeOneStereoFrame( LC3PLUS_CONFIG config )
&decHandle );
if ( IVAS_ERR_OK != err )
{
+ free( bitstream_out );
return err;
}
err = ISAR_LC3PLUS_DEC_GetDelay( decHandle, &decDelay );
if ( IVAS_ERR_OK != err )
{
+ ISAR_LC3PLUS_DEC_Close( &decHandle );
+ free( bitstream_out );
return err;
}
if ( decDelay == -1 || decDelay == 0 )
{
+ ISAR_LC3PLUS_DEC_Close( &decHandle );
+ free( bitstream_out );
return IVAS_ERROR( IVAS_ERR_INTERNAL, "decDelay is zero or uninitialized\n" );
}
@@ -124,18 +162,24 @@ static int encodeAndDecodeOneStereoFrame( LC3PLUS_CONFIG config )
err = ISAR_LC3PLUS_DEC_Conceal( decHandle, pcm_out );
if ( IVAS_ERR_OK != err )
{
+ ISAR_LC3PLUS_DEC_Close( &decHandle );
+ free( bitstream_out );
return err;
}
err = ISAR_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstreamSizePerIvasFrame, pcm_out );
if ( IVAS_ERR_OK != err )
{
+ ISAR_LC3PLUS_DEC_Close( &decHandle );
+ free( bitstream_out );
return err;
}
err = ISAR_LC3PLUS_DEC_Conceal( decHandle, pcm_out );
if ( IVAS_ERR_OK != err )
{
+ ISAR_LC3PLUS_DEC_Close( &decHandle );
+ free( bitstream_out );
return err;
}
@@ -149,7 +193,11 @@ static int encodeAndDecodeOneStereoFrame( LC3PLUS_CONFIG config )
static int openCloseEncoder( void )
{
ivas_error err;
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .ivas_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 };
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 };
+#else
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 };
+#endif
uint32_t bps = 128000;
ISAR_LC3PLUS_ENC_HANDLE encHandle;
@@ -166,31 +214,55 @@ static int openCloseEncoder( void )
static int tryOpenEncoderWithInvalidBitrate( void )
{
ivas_error err;
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .ivas_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 };
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 };
+#else
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 };
+#endif
/* lc3plus max bitrate is 320000 per channel */
uint32_t invalid_high_bps = 700000;
uint32_t invalid_low_bps = 8;
-
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ uint32_t limitedBitrate;
+#endif
ISAR_LC3PLUS_ENC_HANDLE encHandle;
err = ISAR_LC3PLUS_ENC_Open( config, invalid_high_bps, &encHandle );
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ /* setting an invalid bitrate should result in a limited bitrate*/
+ if ( IVAS_ERR_OK != err )
+#else
/* setting an invalid bitrate should trigger an error - which is what we expect */
if ( IVAS_ERR_LC3PLUS_INVALID_BITRATE != err )
+#endif
{
return 1;
}
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ limitedBitrate = lc3plus_enc_get_real_bitrate(encHandle->handles[0]);
+ if(limitedBitrate != 320000)
+ {
+ return 1;
+ }
+#endif
+ ISAR_LC3PLUS_ENC_Close(&encHandle);
err = ISAR_LC3PLUS_ENC_Open( config, invalid_low_bps, &encHandle );
/* setting an invalid bitrate should trigger an error - which is what we expect */
if ( IVAS_ERR_LC3PLUS_INVALID_BITRATE != err )
{
return 1;
}
+ ISAR_LC3PLUS_ENC_Close(&encHandle);
return 0;
}
static int tryOpenEncoderWithInvalidFrameDuration( void )
{
ivas_error err;
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .ivas_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 };
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 };
+#else
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 };
+#endif
config.lc3plus_frame_duration_us = 1234; /*unsupported frame duration*/
uint32_t bps = 320000;
@@ -207,7 +279,11 @@ static int tryOpenEncoderWithInvalidFrameDuration( void )
static int tryOpenEncoderWithInvalidSampleRate( void )
{
ivas_error err;
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .ivas_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 };
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 };
+#else
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 };
+#endif
config.samplerate = 1234; /*unsupported sample rate */
uint32_t bps = 320000;
@@ -247,11 +323,19 @@ static int tryCallEncoderApiWithInvalidParams( void )
return 1;
}
ISAR_LC3PLUS_ENC_Close( &invalidEncHandle );
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_Encode( invalidEncHandle, invalidPcm_in, invalidBitstream_out, bsSize ) )
+#else
if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_Encode( invalidEncHandle, invalidPcm_in, invalidBitstream_out ) )
+#endif
{
return 1;
}
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_Encode( invalidEncHandle, pcm_in, invalidBitstream_out, bsSize ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_Encode( invalidEncHandle, invalidPcm_in, bitstream_out, bsSize ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_Encode( invalidEncHandle, pcm_in, bitstream_out, bsSize ) )
+#else
if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_Encode( invalidEncHandle, pcm_in, invalidBitstream_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_Encode( invalidEncHandle, invalidPcm_in, bitstream_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_Encode( invalidEncHandle, pcm_in, bitstream_out ) )
+#endif
{
return 1;
}
@@ -297,8 +381,11 @@ static int tryCallDecoderApiWithInvalidParams( void )
static int openCloseDecoderWithCaching( void )
{
ivas_error err;
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .ivas_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 };
-
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 };
+#else
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 };
+#endif
ISAR_LC3PLUS_DEC_HANDLE decHandle;
err = ISAR_LC3PLUS_DEC_Open( config,
#ifdef LC3PLUS_DEC_ALLOW_DISABLE_CACHING
@@ -317,8 +404,11 @@ static int openCloseDecoderWithCaching( void )
static int openCloseDecoderWithoutCaching( void )
{
ivas_error err;
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .ivas_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 };
-
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 };
+#else
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 };
+#endif
ISAR_LC3PLUS_DEC_HANDLE decHandle;
err = ISAR_LC3PLUS_DEC_Open( config,
#ifdef LC3PLUS_DEC_ALLOW_DISABLE_CACHING
@@ -338,7 +428,11 @@ static int openCloseDecoderWithoutCaching( void )
static int tryOpenDecoderWithInvalidFrameDuration( void )
{
ivas_error err;
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .ivas_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 };
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 };
+#else
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 };
+#endif
config.lc3plus_frame_duration_us = 1234; /*unsupported frame duration*/
ISAR_LC3PLUS_DEC_HANDLE decHandle;
@@ -358,7 +452,11 @@ static int tryOpenDecoderWithInvalidFrameDuration( void )
static int tryOpenDecoderWithInvalidSampleRate( void )
{
ivas_error err;
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .ivas_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 };
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 };
+#else
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 };
+#endif
config.samplerate = 1234; /*unsupported sample rate*/
ISAR_LC3PLUS_DEC_HANDLE decHandle;
@@ -378,7 +476,11 @@ static int tryOpenDecoderWithInvalidSampleRate( void )
static int encodeOneFrame( void )
{
ivas_error err;
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .ivas_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 };
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 };
+#else
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 };
+#endif
uint32_t bps = 128000;
ISAR_LC3PLUS_ENC_HANDLE encHandle;
@@ -386,7 +488,7 @@ static int encodeOneFrame( void )
if ( IVAS_ERR_OK != err )
return err;
- int16_t numSamplesPerChannels = config.samplerate / ( 1000000 / config.ivas_frame_duration_us );
+ int16_t numSamplesPerChannels = config.samplerate / ( 1000000 / config.isar_frame_duration_us );
float *pcm[1];
float pcm_ch1[MAX_SAMPLES_PER_CHANNEL * sizeof( float )];
@@ -399,8 +501,11 @@ static int encodeOneFrame( void )
return err;
uint8_t *bitstream_out = malloc( bitstreamSizePerIvasFrame );
memset( bitstream_out, 0, bitstreamSizePerIvasFrame );
-
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ err = ISAR_LC3PLUS_ENC_Encode( encHandle, pcm, bitstream_out, bitstreamSizePerIvasFrame );
+#else
err = ISAR_LC3PLUS_ENC_Encode( encHandle, pcm, bitstream_out );
+#endif
if ( IVAS_ERR_OK != err )
return err;
@@ -413,7 +518,11 @@ static int encodeOneFrame( void )
static int encodeAndDecodeOneMonoFrame( void )
{
ivas_error err;
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .ivas_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 };
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 };
+#else
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 };
+#endif
uint32_t bps = 128000;
ISAR_LC3PLUS_ENC_HANDLE encHandle;
@@ -424,7 +533,7 @@ static int encodeAndDecodeOneMonoFrame( void )
}
/* encode one frame */
- int16_t numSamplesPerChannels = config.samplerate / ( 1000000 / config.ivas_frame_duration_us );
+ int16_t numSamplesPerChannels = config.samplerate / ( 1000000 / config.isar_frame_duration_us );
float *pcm_in[1];
float pcm_in_ch1[MAX_SAMPLES_PER_CHANNEL * sizeof( float )];
memset( pcm_in_ch1, 0, numSamplesPerChannels * sizeof( float ) );
@@ -437,8 +546,11 @@ static int encodeAndDecodeOneMonoFrame( void )
uint8_t *bitstream_out = malloc( bitstreamSizePerIvasFrame );
memset( bitstream_out, 0, bitstreamSizePerIvasFrame );
-
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ err = ISAR_LC3PLUS_ENC_Encode( encHandle, pcm_in, bitstream_out, bitstreamSizePerIvasFrame );
+#else
err = ISAR_LC3PLUS_ENC_Encode( encHandle, pcm_in, bitstream_out );
+#endif
if ( IVAS_ERR_OK != err )
return err;
ISAR_LC3PLUS_ENC_Close( &encHandle );
@@ -481,147 +593,264 @@ static int encodeAndDecodeOneMonoFrame( void )
static int encodeAndDecodeOneStereoFrameIvas20msLc3plus10ms_48kHz( void )
{
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .ivas_frame_duration_us = 20 * 1000, .channels = 2, .samplerate = 48000 };
- return encodeAndDecodeOneStereoFrame( config );
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20 * 1000, .channels = 2, .samplerate = 48000, .high_res_mode_enabled = 0 };
+#else
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20 * 1000, .channels = 2, .samplerate = 48000 };
+#endif
+ return encodeAndDecodeOneStereoFrame( config, DEFAULT_BPS );
}
static int encodeAndDecodeOneStereoFrameIvas20msLc3plus10ms_32kHz( void )
{
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .ivas_frame_duration_us = 20 * 1000, .channels = 2, .samplerate = 32000 };
- return encodeAndDecodeOneStereoFrame( config );
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20 * 1000, .channels = 2, .samplerate = 32000 };
+ return encodeAndDecodeOneStereoFrame( config, DEFAULT_BPS );
}
static int encodeAndDecodeOneStereoFrameIvas20msLc3plus10ms_16kHz( void )
{
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .ivas_frame_duration_us = 20 * 1000, .channels = 2, .samplerate = 16000 };
- return encodeAndDecodeOneStereoFrame( config );
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20 * 1000, .channels = 2, .samplerate = 16000 };
+ return encodeAndDecodeOneStereoFrame( config, DEFAULT_BPS );
}
static int encodeAndDecodeOneStereoFrameIvas5msLc3plus5ms_48kHz( void )
{
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .ivas_frame_duration_us = 5 * 1000, .channels = 2, .samplerate = 48000 };
- return encodeAndDecodeOneStereoFrame( config );
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5 * 1000, .channels = 2, .samplerate = 48000, .high_res_mode_enabled = 0 };
+#else
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5 * 1000, .channels = 2, .samplerate = 48000 };
+#endif
+ return encodeAndDecodeOneStereoFrame( config, DEFAULT_BPS );
+}
+
+static int encodeAndDecodeOneStereoFrameIvas10msLc3plus10ms_48kHz( void )
+{
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000, .high_res_mode_enabled = 0 };
+#else
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5 * 1000, .channels = 2, .samplerate = 48000 };
+#endif
+ return encodeAndDecodeOneStereoFrame( config, DEFAULT_BPS );
}
static int encodeAndDecodeOneMonoFrameIvas20msLc3plus10ms_48kHz( void )
{
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .ivas_frame_duration_us = 20 * 1000, .channels = 1, .samplerate = 48000 };
- return encodeAndDecodeOneStereoFrame( config );
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20 * 1000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 };
+#else
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20 * 1000, .channels = 1, .samplerate = 48000 };
+#endif
+ return encodeAndDecodeOneStereoFrame( config, DEFAULT_BPS );
}
static int encodeAndDecodeOneMonoFrameIvas5msLc3plus5ms_48kHz( void )
{
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .ivas_frame_duration_us = 5 * 1000, .channels = 1, .samplerate = 48000 };
- return encodeAndDecodeOneStereoFrame( config );
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5 * 1000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 };
+#else
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5 * 1000, .channels = 1, .samplerate = 48000 };
+#endif
+ return encodeAndDecodeOneStereoFrame( config, DEFAULT_BPS );
}
static int encodeAndDecodeOneStereoFrameIvas20msLc3plus2_5ms_48kHz( void )
{
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 2.5 * 1000, .ivas_frame_duration_us = 20 * 1000, .channels = 2, .samplerate = 48000 };
- return encodeAndDecodeOneStereoFrame( config );
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 2.5 * 1000, .isar_frame_duration_us = 20 * 1000, .channels = 2, .samplerate = 48000, .high_res_mode_enabled = 0 };
+#else
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 2.5 * 1000, .isar_frame_duration_us = 20 * 1000, .channels = 2, .samplerate = 48000 };
+#endif
+ return encodeAndDecodeOneStereoFrame( config, DEFAULT_BPS );
}
-#include "ivas_lc3plus_unit_test_selective_decoding.c"
+static int encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_80kbpsPerChannel( void )
+{
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000, .high_res_mode_enabled = 0 };
+#else
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000 };
+#endif
+ return encodeAndDecodeOneStereoFrame( config, config.channels * 82*1000 );
+}
+
+static int encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_96kbpsPerChannel( void )
+{
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000, .high_res_mode_enabled = 0 };
+#else
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000 };
+#endif
+ return encodeAndDecodeOneStereoFrame( config, config.channels * 98*1000 );
+}
+
+static int encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_124kbpsPerChannel( void )
+{
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000, .high_res_mode_enabled = 0 };
+#else
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000 };
+#endif
+ return encodeAndDecodeOneStereoFrame( config, config.channels * 126*1000 );
+}
+
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+static int encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_800kbpsPerChannel( void )
+{
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000, .high_res_mode_enabled = 0 };
+#else
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000 };
+#endif
+ return encodeAndDecodeOneStereoFrame( config, config.channels * 800*1000 );
+}
+#endif
+
+static int encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_204800bpsPerChannel( void )
+{
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 };
+#else
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000 };
+#endif
+ return encodeAndDecodeOneStereoFrame( config, config.channels * 204800 );
+}
+
+static int encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_205600bpsPerChannel( void )
+{
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 };
+#else
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000 };
+#endif
+ return encodeAndDecodeOneStereoFrame( config, config.channels * 205600 );
+}
+
+static int encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_206400bpsPerChannel( void )
+{
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 };
+#else
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000 };
+#endif
+ return encodeAndDecodeOneStereoFrame( config, config.channels * 206400 );
+}
+
+static int encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_207200bpsPerChannel( void )
+{
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 };
+#else
+ LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000 };
+#endif
+ return encodeAndDecodeOneStereoFrame( config, config.channels * 207200 );
+}
+
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+#include "ivas_lc3plus_unit_test_payload_format.c"
+#endif
int main(
int argc,
char *argv[] )
{
+ (void)argc;
+ (void)argv;
int ret = 0;
ret = openCloseEncoder();
if ( ret != 0 )
- return ret;
+ return 1;
ret = tryOpenEncoderWithInvalidBitrate();
if ( ret != 0 )
- return ret;
+ return 1;
ret = tryOpenEncoderWithInvalidFrameDuration();
if ( ret != 0 )
- return ret;
+ return 1;
ret = tryOpenEncoderWithInvalidSampleRate();
if ( ret != 0 )
- return ret;
+ return 1;
ret = tryCallEncoderApiWithInvalidParams();
if ( ret != 0 )
- return ret;
+ return 1;
ret = openCloseDecoderWithCaching();
if ( ret != 0 )
- return ret;
+ return 1;
ret = openCloseDecoderWithoutCaching();
if ( ret != 0 )
- return ret;
+ return 1;
ret = tryOpenDecoderWithInvalidFrameDuration();
if ( ret != 0 )
- return ret;
+ return 1;
ret = tryOpenDecoderWithInvalidSampleRate();
if ( ret != 0 )
- return ret;
+ return 1;
ret = tryCallDecoderApiWithInvalidParams();
if ( ret != 0 )
- return ret;
+ return 1;
ret = encodeOneFrame();
if ( ret != 0 )
- return ret;
+ return 1;
ret = encodeAndDecodeOneMonoFrame();
if ( ret != 0 )
- return ret;
+ return 1;
ret = encodeAndDecodeOneStereoFrameIvas20msLc3plus10ms_48kHz();
if ( ret != 0 )
- return ret;
+ return 1;
ret = encodeAndDecodeOneStereoFrameIvas20msLc3plus10ms_32kHz();
if ( ret != 0 )
- return ret;
+ return 1;
ret = encodeAndDecodeOneStereoFrameIvas20msLc3plus10ms_16kHz();
if ( ret != 0 )
- return ret;
+ return 1;
ret = encodeAndDecodeOneStereoFrameIvas5msLc3plus5ms_48kHz();
if ( ret != 0 )
- return ret;
+ return 1;
+ ret = encodeAndDecodeOneStereoFrameIvas10msLc3plus10ms_48kHz();
+ if ( ret != 0 )
+ return 1;
ret = encodeAndDecodeOneMonoFrameIvas20msLc3plus10ms_48kHz();
if ( ret != 0 )
- return ret;
+ return 1;
ret = encodeAndDecodeOneMonoFrameIvas5msLc3plus5ms_48kHz();
if ( ret != 0 )
- return ret;
+ return 1;
ret = encodeAndDecodeOneStereoFrameIvas20msLc3plus2_5ms_48kHz();
if ( ret != 0 )
- return ret;
- ret = selectiveDecIvas20msLc3plus5ms_48kHz_scenario_decode_all_subframes();
- if ( ret != 0 )
- return ret;
- ret = selectiveDecIvas20msLc3plus5ms_48kHz_scenario_dont_decode_last_2_subframes();
- if ( ret != 0 )
- return ret;
- ret = selectiveDecIvas20msLc3plus5ms_48kHz_scenario_dont_decode_last_3_subframes();
+ return 1;
+ ret = encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_80kbpsPerChannel();
if ( ret != 0 )
- return ret;
- ret = selectiveDecIvas20msLc3plus5ms_48kHz_scenario_skip_first_subframe();
+ return 1;
+ ret = encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_96kbpsPerChannel();
if ( ret != 0 )
- return ret;
- ret = selectiveDecIvas20msLc3plus5ms_48kHz_scenario_decode_cache();
+ return 1;
+ ret = encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_124kbpsPerChannel();
if ( ret != 0 )
- return ret;
- ret = selectiveDecIvas20msLc3plus5ms_48kHz_scenario_per_subframe_switches_skip_first();
+ return 1;
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ret = encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_800kbpsPerChannel();
if ( ret != 0 )
- return ret;
- ret = selectiveDecIvas20msLc3plus5ms_48kHz_scenario_per_subframe_switches_dec_first();
+ return 1;
+#endif
+ /* start configs around the FDL threshold */
+ ret = encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_204800bpsPerChannel();
if ( ret != 0 )
- return ret;
- ret = selectiveDecIvas20msLc3plus5ms_48kHz_scenario_per_subframe_bundle_switches_dec_first();
+ return 1;
+ ret = encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_205600bpsPerChannel();
if ( ret != 0 )
- return ret;
- ret = selectiveDecIvas20msLc3plus5ms_48kHz_scenario_per_subframe_bundle_switches_skip_first();
+ return 1;
+ ret = encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_206400bpsPerChannel();
if ( ret != 0 )
- return ret;
- ret = selectiveDecIvas20msLc3plus5ms_48kHz_scenario_get_active_dont_cache();
+ return 1;
+ ret = encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_207200bpsPerChannel();
if ( ret != 0 )
- return ret;
-#ifdef LC3PLUS_DEC_ALLOW_DISABLE_CACHING
- ret = selectiveDecIvas20msLc3plus5ms_48kHz_scenario_per_subframe_switches_dec_first_no_caching();
+ return 1;
+ /* end configs around the FDL threshold */
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+ ret = run_all_payload_tests();
if ( ret != 0 )
- return ret;
+ return 1;
#endif
- return ret;
+ return 0;
}
#else
int main( void )
diff --git a/scripts/split_rendering/lc3plus/ivas_lc3plus_unit_test_payload_format.c b/scripts/split_rendering/lc3plus/ivas_lc3plus_unit_test_payload_format.c
new file mode 100644
index 0000000000000000000000000000000000000000..a303d01f53ee873fe70c0fbad2a9b6a540daa154
--- /dev/null
+++ b/scripts/split_rendering/lc3plus/ivas_lc3plus_unit_test_payload_format.c
@@ -0,0 +1,451 @@
+/******************************************************************************************************
+
+(C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
+Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+contributors to this repository. All Rights Reserved.
+
+This software is protected by copyright law and by international treaties.
+The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
+Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+contributors to this repository retain full ownership rights in their respective contributions in
+the software. This notice grants no license of any kind, including but not limited to patent
+license, nor is any license granted by implication, estoppel or otherwise.
+
+Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
+contributions.
+
+This software is provided "AS IS", without any express or implied warranties. The software is in the
+development stage. It is intended exclusively for experts who have experience with such software and
+solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
+and fitness for a particular purpose are hereby disclaimed and excluded.
+
+Any dispute, controversy or claim arising under or in relation to providing this software shall be
+submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
+accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
+the United Nations Convention on Contracts on the International Sales of Goods.
+
+*******************************************************************************************************/
+
+#include
+#include
+#include
+#include "isar_lc3plus_payload.h"
+#include "ivas_error_utils.h"
+#include "isar_lc3plus_common.h"
+#include "options.h"
+
+#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
+
+/* included by ivas_lc3plus_unit_test.c */
+
+#define LC3PLUS_MAX_NUM_CODERS 16
+#define LC3PLUS_MAX_BS_SIZE LC3PLUS_MAX_NUM_CODERS *( 720 * LC3PLUS_RTP_PAYLOAD_MAX_NUM_MEDIA_TIMES )
+#define SIZE_70 70
+#define SIZE_160 160
+#define SIZE_320 320
+#define SIZE_600 600
+
+static int pack_and_unpack_payload_config_2ch_10ms_lc3plus_20ms_ivas( void )
+{
+ LC3PLUS_RTP_FTD sender_ftds[LC3PLUS_MAX_NUM_CODERS];
+ int32_t sender_ftds_num = 0;
+ const LC3PLUS_RTP_FDL fdl_req = LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA;
+
+ LC3PLUS_RTP_FTD *ftd_L_01 = &sender_ftds[0];
+ ftd_L_01->fc = LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL;
+ ftd_L_01->fdi = LC3PLUS_RTP_FTD_FDI_10000_US;
+ ftd_L_01->bwr = LC3PLUS_RTP_FTD_BWR_FB;
+ ftd_L_01->h = LC3PLUS_RTP_FTD_H_PRIMARY;
+ ftd_L_01->frame_data = NULL;
+ ftd_L_01->frame_data_length = SIZE_160;
+ sender_ftds_num++;
+
+ LC3PLUS_RTP_FTD *ftd_R_01 = &sender_ftds[1];
+ ftd_R_01->fc = LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME;
+ ftd_R_01->fdi = LC3PLUS_RTP_FTD_FDI_10000_US;
+ ftd_R_01->bwr = LC3PLUS_RTP_FTD_BWR_FB;
+ ftd_R_01->h = LC3PLUS_RTP_FTD_H_PRIMARY;
+ ftd_R_01->frame_data = NULL;
+ ftd_R_01->frame_data_length = SIZE_600;
+ sender_ftds_num++;
+
+ LC3PLUS_RTP_FTD *ftd_L_02 = &sender_ftds[2];
+ ftd_L_02->fc = LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL;
+ ftd_L_02->fdi = LC3PLUS_RTP_FTD_FDI_10000_US;
+ ftd_L_02->bwr = LC3PLUS_RTP_FTD_BWR_FB;
+ ftd_L_02->h = LC3PLUS_RTP_FTD_H_PRIMARY;
+ ftd_L_02->frame_data = NULL;
+ ftd_L_02->frame_data_length = SIZE_320;
+ sender_ftds_num++;
+
+ LC3PLUS_RTP_FTD *ftd_R_02 = &sender_ftds[3];
+ ftd_R_02->fc = LC3PLUS_RTP_FTD_FC_LAST_OVERALL;
+ ftd_R_02->fdi = LC3PLUS_RTP_FTD_FDI_10000_US;
+ ftd_R_02->bwr = LC3PLUS_RTP_FTD_BWR_FB;
+ ftd_R_02->h = LC3PLUS_RTP_FTD_H_PRIMARY;
+ ftd_R_02->frame_data = NULL;
+ ftd_R_02->frame_data_length = SIZE_160;
+ sender_ftds_num++;
+
+ const size_t packed_buffer_capacity = LC3PLUS_MAX_BS_SIZE;
+ size_t packed_buffer_actual_size;
+ uint8_t packed_buffer[LC3PLUS_MAX_BS_SIZE];
+ memset( packed_buffer, 0, packed_buffer_capacity );
+ // prepare bitstream buffer headers & layout
+ LC3PLUS_RTP_ERR error = LC3PLUS_RTP_payload_serialize( packed_buffer, packed_buffer_capacity, &packed_buffer_actual_size, fdl_req, sender_ftds, sender_ftds_num );
+ if ( error != LC3PLUS_RTP_ERR_NO_ERROR )
+ {
+ return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_payload_serialize failed\n" );
+ }
+
+ // copy encoded frames into their expected memory locations
+ uint8_t frame_data_L_01[SIZE_160];
+ memset( frame_data_L_01, 0x01, sizeof( frame_data_L_01 ) );
+ uint8_t frame_data_R_01[SIZE_600];
+ memset( frame_data_R_01, 0x02, sizeof( frame_data_R_01 ) );
+ uint8_t frame_data_L_02[SIZE_320];
+ memset( frame_data_L_02, 0x03, sizeof( frame_data_L_02 ) );
+ uint8_t frame_data_R_02[SIZE_160];
+ memset( frame_data_R_02, 0x04, sizeof( frame_data_R_02 ) );
+ memcpy( sender_ftds[0].frame_data, frame_data_L_01, sender_ftds[0].frame_data_length );
+ memcpy( sender_ftds[1].frame_data, frame_data_R_01, sender_ftds[1].frame_data_length );
+ memcpy( sender_ftds[2].frame_data, frame_data_L_02, sender_ftds[2].frame_data_length );
+ memcpy( sender_ftds[3].frame_data, frame_data_R_02, sender_ftds[3].frame_data_length );
+
+ uint8_t *receiverBuffer = malloc( packed_buffer_actual_size );
+ assert( NULL != receiverBuffer );
+ memcpy( receiverBuffer, packed_buffer, packed_buffer_actual_size );
+
+ LC3PLUS_RTP_PAYLOAD payload_config;
+ error = LC3PLUS_RTP_payload_deserialize( &payload_config, receiverBuffer, packed_buffer_actual_size );
+ if ( error != LC3PLUS_RTP_ERR_NO_ERROR )
+ {
+ return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_payload_deserialize failed\n" );
+ }
+
+ assert( payload_config.fdl_request == fdl_req );
+ assert( payload_config.frame_duration_us == 10000 );
+ assert( payload_config.high_resolution_enabled == 0 );
+ assert( payload_config.sampling_rate_hz == 48000 );
+ assert( payload_config.num_ftds == 4 );
+ assert( payload_config.num_media_times == 2 );
+ assert( payload_config.num_channels == 2 );
+ for ( int32_t i = 0; i < payload_config.num_ftds; ++i )
+ {
+ assert( payload_config.ftds[i].frame_data_length == sender_ftds[i].frame_data_length );
+ assert( payload_config.ftds[i].h == sender_ftds[i].h );
+ assert( payload_config.ftds[i].fdi == sender_ftds[i].fdi );
+ assert( payload_config.ftds[i].bwr == sender_ftds[i].bwr );
+ assert( payload_config.ftds[i].fc == sender_ftds[i].fc );
+ assert( payload_config.ftds[i].frame_data_length == sender_ftds[i].frame_data_length );
+ assert( payload_config.ftds[i].frame_data != sender_ftds[i].frame_data );
+ assert( 0 == memcmp( payload_config.ftds[i].frame_data, sender_ftds[i].frame_data, sender_ftds[i].frame_data_length ) );
+ }
+
+ free( receiverBuffer );
+ return 0;
+}
+
+static int pack_and_unpack_payload_config_2ch_5ms_lc3plus_20ms_ivas( void )
+{
+ LC3PLUS_RTP_FTD sender_ftds[LC3PLUS_MAX_NUM_CODERS];
+ int32_t sender_ftds_num = 0;
+ const LC3PLUS_RTP_FDL fdl_req = LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA;
+
+ LC3PLUS_RTP_FTD *ftd_L_01 = &sender_ftds[0];
+ ftd_L_01->fc = LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL;
+ ftd_L_01->fdi = LC3PLUS_RTP_FTD_FDI_5000_US;
+ ftd_L_01->bwr = LC3PLUS_RTP_FTD_BWR_FB;
+ ftd_L_01->h = LC3PLUS_RTP_FTD_H_PRIMARY;
+ ftd_L_01->frame_data = NULL;
+ ftd_L_01->frame_data_length = SIZE_70;
+ sender_ftds_num++;
+
+ LC3PLUS_RTP_FTD *ftd_R_01 = &sender_ftds[1];
+ ftd_R_01->fc = LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME;
+ ftd_R_01->fdi = LC3PLUS_RTP_FTD_FDI_5000_US;
+ ftd_R_01->bwr = LC3PLUS_RTP_FTD_BWR_FB;
+ ftd_R_01->h = LC3PLUS_RTP_FTD_H_PRIMARY;
+ ftd_R_01->frame_data = NULL;
+ ftd_R_01->frame_data_length = SIZE_320;
+ sender_ftds_num++;
+
+ LC3PLUS_RTP_FTD *ftd_L_02 = &sender_ftds[2];
+ ftd_L_02->fc = LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL;
+ ftd_L_02->fdi = LC3PLUS_RTP_FTD_FDI_5000_US;
+ ftd_L_02->bwr = LC3PLUS_RTP_FTD_BWR_FB;
+ ftd_L_02->h = LC3PLUS_RTP_FTD_H_PRIMARY;
+ ftd_L_02->frame_data = NULL;
+ ftd_L_02->frame_data_length = SIZE_70;
+ sender_ftds_num++;
+
+ LC3PLUS_RTP_FTD *ftd_R_02 = &sender_ftds[3];
+ ftd_R_02->fc = LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME;
+ ftd_R_02->fdi = LC3PLUS_RTP_FTD_FDI_5000_US;
+ ftd_R_02->bwr = LC3PLUS_RTP_FTD_BWR_FB;
+ ftd_R_02->h = LC3PLUS_RTP_FTD_H_PRIMARY;
+ ftd_R_02->frame_data = NULL;
+ ftd_R_02->frame_data_length = SIZE_160;
+ sender_ftds_num++;
+
+ LC3PLUS_RTP_FTD *ftd_L_03 = &sender_ftds[4];
+ ftd_L_03->fc = LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL;
+ ftd_L_03->fdi = LC3PLUS_RTP_FTD_FDI_5000_US;
+ ftd_L_03->bwr = LC3PLUS_RTP_FTD_BWR_FB;
+ ftd_L_03->h = LC3PLUS_RTP_FTD_H_PRIMARY;
+ ftd_L_03->frame_data = NULL;
+ ftd_L_03->frame_data_length = SIZE_70;
+ sender_ftds_num++;
+
+ LC3PLUS_RTP_FTD *ftd_R_03 = &sender_ftds[5];
+ ftd_R_03->fc = LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME;
+ ftd_R_03->fdi = LC3PLUS_RTP_FTD_FDI_5000_US;
+ ftd_R_03->bwr = LC3PLUS_RTP_FTD_BWR_FB;
+ ftd_R_03->h = LC3PLUS_RTP_FTD_H_PRIMARY;
+ ftd_R_03->frame_data = NULL;
+ ftd_R_03->frame_data_length = SIZE_320;
+ sender_ftds_num++;
+
+ LC3PLUS_RTP_FTD *ftd_L_04 = &sender_ftds[6];
+ ftd_L_04->fc = LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL;
+ ftd_L_04->fdi = LC3PLUS_RTP_FTD_FDI_5000_US;
+ ftd_L_04->bwr = LC3PLUS_RTP_FTD_BWR_FB;
+ ftd_L_04->h = LC3PLUS_RTP_FTD_H_PRIMARY;
+ ftd_L_04->frame_data = NULL;
+ ftd_L_04->frame_data_length = SIZE_70;
+ sender_ftds_num++;
+
+ LC3PLUS_RTP_FTD *ftd_R_04 = &sender_ftds[7];
+ ftd_R_04->fc = LC3PLUS_RTP_FTD_FC_LAST_OVERALL;
+ ftd_R_04->fdi = LC3PLUS_RTP_FTD_FDI_5000_US;
+ ftd_R_04->bwr = LC3PLUS_RTP_FTD_BWR_FB;
+ ftd_R_04->h = LC3PLUS_RTP_FTD_H_PRIMARY;
+ ftd_R_04->frame_data = NULL;
+ ftd_R_04->frame_data_length = SIZE_160;
+ sender_ftds_num++;
+
+ const size_t packed_buffer_capacity = LC3PLUS_MAX_BS_SIZE;
+ size_t packed_buffer_actual_size;
+ uint8_t packed_buffer[LC3PLUS_MAX_BS_SIZE];
+ memset( packed_buffer, 0, packed_buffer_capacity );
+ // prepare bitstream buffer headers & layout
+ LC3PLUS_RTP_ERR error = LC3PLUS_RTP_payload_serialize( packed_buffer, packed_buffer_capacity, &packed_buffer_actual_size, fdl_req, sender_ftds, sender_ftds_num );
+ if ( error != LC3PLUS_RTP_ERR_NO_ERROR )
+ {
+ return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_payload_serialize failed\n" );
+ }
+
+
+ // copy encoded frames into their expected memory locations
+ uint8_t frame_data_L_01[SIZE_70];
+ assert( ftd_L_01->frame_data_length == sizeof( frame_data_L_01 ) );
+ memset( frame_data_L_01, 0x01, sizeof( frame_data_L_01 ) );
+ uint8_t frame_data_R_01[SIZE_320];
+ assert( ftd_R_01->frame_data_length == sizeof( frame_data_R_01 ) );
+ memset( frame_data_R_01, 0x02, sizeof( frame_data_R_01 ) );
+ uint8_t frame_data_L_02[SIZE_70];
+ assert( ftd_L_02->frame_data_length == sizeof( frame_data_L_02 ) );
+ memset( frame_data_L_02, 0x03, sizeof( frame_data_L_02 ) );
+ uint8_t frame_data_R_02[SIZE_160];
+ assert( ftd_R_02->frame_data_length == sizeof( frame_data_R_02 ) );
+ memset( frame_data_R_02, 0x04, sizeof( frame_data_R_02 ) );
+ uint8_t frame_data_L_03[SIZE_70];
+ assert( ftd_L_03->frame_data_length == sizeof( frame_data_L_03 ) );
+ memset( frame_data_L_03, 0x05, sizeof( frame_data_L_03 ) );
+ uint8_t frame_data_R_03[SIZE_320];
+ assert( ftd_R_03->frame_data_length == sizeof( frame_data_R_03 ) );
+ memset( frame_data_R_03, 0x06, sizeof( frame_data_R_03 ) );
+ uint8_t frame_data_L_04[SIZE_70];
+ assert( ftd_L_04->frame_data_length == sizeof( frame_data_L_04 ) );
+ memset( frame_data_L_04, 0x07, sizeof( frame_data_L_04 ) );
+ uint8_t frame_data_R_04[SIZE_160];
+ assert( ftd_R_04->frame_data_length == sizeof( frame_data_R_04 ) );
+ memset( frame_data_R_04, 0x08, sizeof( frame_data_R_04 ) );
+ memcpy( sender_ftds[0].frame_data, frame_data_L_01, sender_ftds[0].frame_data_length );
+ memcpy( sender_ftds[1].frame_data, frame_data_R_01, sender_ftds[1].frame_data_length );
+ memcpy( sender_ftds[2].frame_data, frame_data_L_02, sender_ftds[2].frame_data_length );
+ memcpy( sender_ftds[3].frame_data, frame_data_R_02, sender_ftds[3].frame_data_length );
+ memcpy( sender_ftds[4].frame_data, frame_data_L_03, sender_ftds[4].frame_data_length );
+ memcpy( sender_ftds[5].frame_data, frame_data_R_03, sender_ftds[5].frame_data_length );
+ memcpy( sender_ftds[6].frame_data, frame_data_L_04, sender_ftds[6].frame_data_length );
+ memcpy( sender_ftds[7].frame_data, frame_data_R_04, sender_ftds[7].frame_data_length );
+
+ uint8_t *receiverBuffer = malloc( packed_buffer_actual_size );
+ assert( NULL != receiverBuffer );
+ memcpy( receiverBuffer, packed_buffer, packed_buffer_actual_size );
+
+ LC3PLUS_RTP_PAYLOAD payload_config;
+ error = LC3PLUS_RTP_payload_deserialize( &payload_config, receiverBuffer, packed_buffer_actual_size );
+ if ( error != LC3PLUS_RTP_ERR_NO_ERROR )
+ {
+ return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_payload_deserialize failed\n" );
+ }
+
+ assert( payload_config.fdl_request == fdl_req );
+ assert( payload_config.frame_duration_us == 5000 );
+ assert( payload_config.high_resolution_enabled == 0 );
+ assert( payload_config.sampling_rate_hz == 48000 );
+ assert( payload_config.num_ftds == 8 );
+ assert( payload_config.num_media_times == 4 );
+ assert( payload_config.num_channels == 2 );
+ for ( int32_t i = 0; i < payload_config.num_ftds; ++i )
+ {
+ assert( payload_config.ftds[i].frame_data_length == sender_ftds[i].frame_data_length );
+ assert( payload_config.ftds[i].h == sender_ftds[i].h );
+ assert( payload_config.ftds[i].fdi == sender_ftds[i].fdi );
+ assert( payload_config.ftds[i].bwr == sender_ftds[i].bwr );
+ assert( payload_config.ftds[i].fc == sender_ftds[i].fc );
+ assert( payload_config.ftds[i].frame_data_length == sender_ftds[i].frame_data_length );
+ assert( payload_config.ftds[i].frame_data != sender_ftds[i].frame_data );
+ assert( 0 == memcmp( payload_config.ftds[i].frame_data, sender_ftds[i].frame_data, sender_ftds[i].frame_data_length ) );
+ }
+
+ free( receiverBuffer );
+ return 0;
+}
+
+static int try_unpack_invalid_values( void )
+{
+ LC3PLUS_RTP_FTD sender_ftds[LC3PLUS_MAX_NUM_CODERS];
+ int32_t sender_ftds_num = 0;
+ const LC3PLUS_RTP_FDL fdl_req = LC3PLUS_RTP_FDL_LENGTH_3_MAX;
+
+ LC3PLUS_RTP_FTD *ftd_L_01 = &sender_ftds[0];
+ ftd_L_01->fc = LC3PLUS_RTP_FTD_FC_LAST_OVERALL;
+ ftd_L_01->fdi = LC3PLUS_RTP_FTD_FDI_5000_US;
+ ftd_L_01->bwr = LC3PLUS_RTP_FTD_BWR_FB;
+ ftd_L_01->h = LC3PLUS_RTP_FTD_H_PRIMARY;
+ ftd_L_01->frame_data = NULL;
+ ftd_L_01->frame_data_length = SIZE_70;
+ sender_ftds_num++;
+
+ const size_t packed_buffer_capacity = LC3PLUS_MAX_BS_SIZE;
+ size_t packed_buffer_actual_size;
+ uint8_t packed_buffer[LC3PLUS_MAX_BS_SIZE];
+ memset( packed_buffer, 0, packed_buffer_capacity );
+ // prepare bitstream buffer headers & layout
+ LC3PLUS_RTP_ERR error = LC3PLUS_RTP_payload_serialize( packed_buffer, packed_buffer_capacity, &packed_buffer_actual_size, fdl_req, sender_ftds, sender_ftds_num );
+ if ( error != LC3PLUS_RTP_ERR_NO_ERROR )
+ {
+ return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_payload_serialize failed\n" );
+ }
+
+ // copy encoded frames into their expected memory locations
+ uint8_t frame_data_L_01[SIZE_70];
+ assert( ftd_L_01->frame_data_length == sizeof( frame_data_L_01 ) );
+ memset( frame_data_L_01, 0x01, sizeof( frame_data_L_01 ) );
+
+ uint8_t *receiverBuffer = malloc( packed_buffer_actual_size );
+ assert( NULL != receiverBuffer );
+ memcpy( receiverBuffer, packed_buffer, packed_buffer_actual_size );
+
+ int32_t fdl_req_length;
+ error = LC3PLUS_RTP_frame_data_length_get_size( &fdl_req_length, fdl_req );
+ if ( error != LC3PLUS_RTP_ERR_NO_ERROR )
+ {
+ return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_frame_data_length_get_size error\n" );
+ }
+ for ( int16_t packed_buffer_incorrect_size = 0; packed_buffer_incorrect_size < ( fdl_req_length + 2 + SIZE_70 ); ++packed_buffer_incorrect_size )
+ {
+ LC3PLUS_RTP_PAYLOAD payload_config;
+ error = LC3PLUS_RTP_payload_deserialize( &payload_config, receiverBuffer, packed_buffer_incorrect_size );
+ if ( error == LC3PLUS_RTP_ERR_NO_ERROR )
+ {
+ free( receiverBuffer );
+ return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_payload_deserialize failed to detect error\n" );
+ }
+ }
+
+ LC3PLUS_RTP_PAYLOAD payload_config;
+ error = LC3PLUS_RTP_payload_deserialize( &payload_config, receiverBuffer, packed_buffer_actual_size );
+ if ( error != LC3PLUS_RTP_ERR_NO_ERROR )
+ {
+ free( receiverBuffer );
+ return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_payload_deserialize failed\n" );
+ }
+ free( receiverBuffer );
+ return 0;
+}
+
+#define LC3PLUS_RTP_TEST_NUM_FTDS_UT 3
+static int pack_and_unpack_different_fdl_sizes( void )
+{
+ int32_t iFtdUt;
+ LC3PLUS_RTP_FDL fdl_requests_ut[LC3PLUS_RTP_TEST_NUM_FTDS_UT];
+ fdl_requests_ut[0] = LC3PLUS_RTP_FDL_LENGTH_1_MIN;
+ fdl_requests_ut[1] = LC3PLUS_RTP_FDL_LENGTH_2_MIN;
+ fdl_requests_ut[2] = LC3PLUS_RTP_FDL_LENGTH_3_MIN;
+
+ for ( iFtdUt = 0; iFtdUt < LC3PLUS_RTP_TEST_NUM_FTDS_UT; ++iFtdUt )
+ {
+ LC3PLUS_RTP_FTD sender_ftds[LC3PLUS_MAX_NUM_CODERS];
+ int32_t sender_ftds_num = 0;
+
+ LC3PLUS_RTP_FTD *ftd_L_01 = &sender_ftds[0];
+ ftd_L_01->fc = LC3PLUS_RTP_FTD_FC_LAST_OVERALL;
+ ftd_L_01->fdi = LC3PLUS_RTP_FTD_FDI_5000_US;
+ ftd_L_01->bwr = LC3PLUS_RTP_FTD_BWR_FB;
+ ftd_L_01->h = LC3PLUS_RTP_FTD_H_PRIMARY;
+ ftd_L_01->frame_data = NULL;
+ ftd_L_01->frame_data_length = fdl_requests_ut[iFtdUt];
+ sender_ftds_num++;
+
+ const size_t packed_buffer_capacity = LC3PLUS_MAX_BS_SIZE;
+ size_t packed_buffer_actual_size;
+ uint8_t packed_buffer[LC3PLUS_MAX_BS_SIZE];
+ memset( packed_buffer, 0, packed_buffer_capacity );
+ // prepare bitstream buffer headers & layout
+ LC3PLUS_RTP_ERR error = LC3PLUS_RTP_payload_serialize( packed_buffer, packed_buffer_capacity, &packed_buffer_actual_size, fdl_requests_ut[iFtdUt], sender_ftds, sender_ftds_num );
+ if ( error != LC3PLUS_RTP_ERR_NO_ERROR )
+ {
+ return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_payload_serialize failed\n" );
+ }
+
+ // copy encoded frames into their expected memory locations
+ uint8_t frame_data_L_01[SIZE_600];
+ assert( ftd_L_01->frame_data_length <= sizeof( frame_data_L_01 ) );
+ memset( frame_data_L_01, 0x01, ftd_L_01->frame_data_length );
+
+ uint8_t *receiverBuffer = malloc( packed_buffer_actual_size );
+ assert( NULL != receiverBuffer );
+ memcpy( receiverBuffer, packed_buffer, packed_buffer_actual_size );
+
+ LC3PLUS_RTP_PAYLOAD payload_config;
+ error = LC3PLUS_RTP_payload_deserialize( &payload_config, receiverBuffer, packed_buffer_actual_size );
+ if ( error != LC3PLUS_RTP_ERR_NO_ERROR )
+ {
+ free( receiverBuffer );
+ return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_payload_deserialize failed\n" );
+ }
+ assert( payload_config.fdl_request == fdl_requests_ut[iFtdUt] );
+ assert( payload_config.ftds[0].frame_data_length == fdl_requests_ut[iFtdUt] );
+ free( receiverBuffer );
+ }
+ return 0;
+}
+
+static int run_all_payload_tests( void )
+{
+ if ( pack_and_unpack_payload_config_2ch_10ms_lc3plus_20ms_ivas() != 0 )
+ {
+ return IVAS_ERROR( IVAS_ERR_INTERNAL, "test failed\n" );
+ }
+ if ( pack_and_unpack_payload_config_2ch_5ms_lc3plus_20ms_ivas() != 0 )
+ {
+ return IVAS_ERROR( IVAS_ERR_INTERNAL, "test failed\n" );
+ }
+ if ( try_unpack_invalid_values() != 0 )
+ {
+ return IVAS_ERROR( IVAS_ERR_INTERNAL, "test failed\n" );
+ }
+ if ( pack_and_unpack_different_fdl_sizes() != 0 )
+ {
+ return IVAS_ERROR( IVAS_ERR_INTERNAL, "test failed\n" );
+ }
+ return 0;
+}
+#endif
diff --git a/scripts/split_rendering/lc3plus/ivas_lc3plus_unit_test_selective_decoding.c b/scripts/split_rendering/lc3plus/ivas_lc3plus_unit_test_selective_decoding.c
deleted file mode 100644
index 637ef6997b66f9ce40a91114978e6b12718a5970..0000000000000000000000000000000000000000
--- a/scripts/split_rendering/lc3plus/ivas_lc3plus_unit_test_selective_decoding.c
+++ /dev/null
@@ -1,1966 +0,0 @@
-/******************************************************************************************************
-
-(C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
-Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
-Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
-Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
-contributors to this repository. All Rights Reserved.
-
-This software is protected by copyright law and by international treaties.
-The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
-Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
-Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
-Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
-contributors to this repository retain full ownership rights in their respective contributions in
-the software. This notice grants no license of any kind, including but not limited to patent
-license, nor is any license granted by implication, estoppel or otherwise.
-
-Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
-contributions.
-
-This software is provided "AS IS", without any express or implied warranties. The software is in the
-development stage. It is intended exclusively for experts who have experience with such software and
-solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
-and fitness for a particular purpose are hereby disclaimed and excluded.
-
-Any dispute, controversy or claim arising under or in relation to providing this software shall be
-submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
-accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
-the United Nations Convention on Contracts on the International Sales of Goods.
-
-*******************************************************************************************************/
-
-#include
-#include
-#include "isar_lc3plus_enc.h"
-#include "isar_lc3plus_common.h"
-#include "isar_lc3plus_dec.h"
-#include "ivas_error_utils.h"
-
-#ifdef SPLIT_REND_WITH_HEAD_ROT
-
-#define MAX_SAMPLES_PER_CHANNEL 960
-
-/* included by ivas_lc3plus_unit_test.c */
-
-typedef int ( *ScenarioFnPtr )( const LC3PLUS_CONFIG config,
- ISAR_LC3PLUS_DEC_HANDLE dec,
- uint8_t *bitstream_in,
- int32_t bitstream_in_size,
- float **pcm_out );
-
-static void ISAR_LC3PLUS_DEC_FreeSubframeDecodingMatrix(
- int16_t **subframeChannelMatrix )
-{
- for ( int16_t i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
- {
- free( subframeChannelMatrix[i] );
- }
-
- free( subframeChannelMatrix );
-
- return;
-}
-
-static int encodeAndDecodeOne6chFrameFixture( LC3PLUS_CONFIG config, const int16_t enableCaching, const int32_t bps, ScenarioFnPtr scenarioFn )
-{
- ivas_error err;
- int32_t encDelay = -1;
- int32_t decDelay = -1;
-
- ISAR_LC3PLUS_ENC_HANDLE encHandle;
- err = ISAR_LC3PLUS_ENC_Open( config, bps, &encHandle );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- err = ISAR_LC3PLUS_ENC_GetDelay( encHandle, &encDelay );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
- if ( encDelay == -1 || encDelay == 0 )
- {
- return IVAS_ERROR( IVAS_ERR_INTERNAL, "encDelay is zero or uninitialized\n" );
- }
-
- /* encode one frame */
- int16_t numSamplesPerChannels = config.samplerate / ( 1000000 / config.ivas_frame_duration_us );
- float *pcm_in[6];
- float pcm_in_ch1[MAX_SAMPLES_PER_CHANNEL * sizeof( float )];
- memset( pcm_in_ch1, 0, numSamplesPerChannels * sizeof( float ) );
- float pcm_in_ch2[MAX_SAMPLES_PER_CHANNEL * sizeof( float )];
- memset( pcm_in_ch2, 0, numSamplesPerChannels * sizeof( float ) );
- float pcm_in_ch3[MAX_SAMPLES_PER_CHANNEL * sizeof( float )];
- memset( pcm_in_ch3, 0, numSamplesPerChannels * sizeof( float ) );
- float pcm_in_ch4[MAX_SAMPLES_PER_CHANNEL * sizeof( float )];
- memset( pcm_in_ch4, 0, numSamplesPerChannels * sizeof( float ) );
- float pcm_in_ch5[MAX_SAMPLES_PER_CHANNEL * sizeof( float )];
- memset( pcm_in_ch5, 0, numSamplesPerChannels * sizeof( float ) );
- float pcm_in_ch6[MAX_SAMPLES_PER_CHANNEL * sizeof( float )];
- memset( pcm_in_ch6, 0, numSamplesPerChannels * sizeof( float ) );
- pcm_in[0] = pcm_in_ch1;
- pcm_in[1] = pcm_in_ch2;
- pcm_in[2] = pcm_in_ch3;
- pcm_in[3] = pcm_in_ch4;
- pcm_in[4] = pcm_in_ch5;
- pcm_in[5] = pcm_in_ch6;
-
- int32_t bitstreamSizePerIvasFrame = 0;
- err = ISAR_LC3PLUS_ENC_GetOutputBitstreamSize( encHandle, &bitstreamSizePerIvasFrame );
- if ( IVAS_ERR_OK != err )
- return err;
-
- uint8_t *bitstream_out = malloc( bitstreamSizePerIvasFrame );
- memset( bitstream_out, 0, bitstreamSizePerIvasFrame );
-
- err = ISAR_LC3PLUS_ENC_Encode( encHandle, pcm_in, bitstream_out );
- if ( IVAS_ERR_OK != err )
- return err;
- ISAR_LC3PLUS_ENC_Close( &encHandle );
-
- /* decode one frame */
- ISAR_LC3PLUS_DEC_HANDLE decHandle;
- err = ISAR_LC3PLUS_DEC_Open( config,
-#ifdef LC3PLUS_DEC_ALLOW_DISABLE_CACHING
- enableCaching,
-#endif
- &decHandle );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- err = ISAR_LC3PLUS_DEC_GetDelay( decHandle, &decDelay );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
- if ( decDelay == -1 || decDelay == 0 )
- {
- return IVAS_ERROR( IVAS_ERR_INTERNAL, "decDelay is zero or uninitialized\n" );
- }
-
- uint8_t *bitstream_in = bitstream_out;
-
- float *pcm_out[6];
- float pcm_out_ch1[MAX_SAMPLES_PER_CHANNEL * sizeof( float )];
- memset( pcm_out_ch1, 0, numSamplesPerChannels * sizeof( float ) );
- float pcm_out_ch2[MAX_SAMPLES_PER_CHANNEL * sizeof( float )];
- memset( pcm_out_ch2, 0, numSamplesPerChannels * sizeof( float ) );
- float pcm_out_ch3[MAX_SAMPLES_PER_CHANNEL * sizeof( float )];
- memset( pcm_out_ch3, 0, numSamplesPerChannels * sizeof( float ) );
- float pcm_out_ch4[MAX_SAMPLES_PER_CHANNEL * sizeof( float )];
- memset( pcm_out_ch4, 0, numSamplesPerChannels * sizeof( float ) );
- float pcm_out_ch5[MAX_SAMPLES_PER_CHANNEL * sizeof( float )];
- memset( pcm_out_ch5, 0, numSamplesPerChannels * sizeof( float ) );
- float pcm_out_ch6[MAX_SAMPLES_PER_CHANNEL * sizeof( float )];
- memset( pcm_out_ch6, 0, numSamplesPerChannels * sizeof( float ) );
- pcm_out[0] = pcm_out_ch1;
- pcm_out[1] = pcm_out_ch2;
- pcm_out[2] = pcm_out_ch3;
- pcm_out[3] = pcm_out_ch4;
- pcm_out[4] = pcm_out_ch5;
- pcm_out[5] = pcm_out_ch6;
-
- err = ISAR_LC3PLUS_DEC_Conceal( decHandle, pcm_out );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- err = ISAR_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstreamSizePerIvasFrame, pcm_out );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- if ( NULL != scenarioFn )
- {
- err = ( *scenarioFn )( config, decHandle, bitstream_in, bitstreamSizePerIvasFrame, pcm_out );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
- }
-
- err = ISAR_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstreamSizePerIvasFrame, pcm_out );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- err = ISAR_LC3PLUS_DEC_Conceal( decHandle, pcm_out );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- ISAR_LC3PLUS_DEC_Close( &decHandle );
- free( bitstream_out );
-
- return 0;
-}
-
-/*
- * in: [dec, dec, dec, dec]
- * expected out: [dec_and_use, dec_and_use, dec_and_use, dec_and_use]
- */
-static int scenario_decode_all_subframes( const LC3PLUS_CONFIG config,
- ISAR_LC3PLUS_DEC_HANDLE decHandle, /* i: decoder handle */
- uint8_t *bitstream_in, /* i: pointer to input bitstream */
- int32_t bitstream_in_size, /* i: size of bitstream_in */
- float **pcm_out /* o: decoded samples */ )
-{
- ivas_error err;
- const int16_t decode = 1;
- // const int16_t skipDecoding = 0;
- uint32_t iDec = 0;
- int iLc3plusFrame = 0;
- int lc3framesPerIvasFrame;
- int16_t **selective_decoding_matrix;
- err = ISAR_LC3PLUS_DEC_AllocateSubframeDecodingMatrix( &selective_decoding_matrix, config.channels );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* Set selective decoding scenario */
- for ( int16_t iSubframeIdx = 0; iSubframeIdx < MAX_PARAM_SPATIAL_SUBFRAMES; iSubframeIdx++ )
- {
- for ( int16_t decIdx = 0; decIdx < config.channels; decIdx++ )
- {
- selective_decoding_matrix[iSubframeIdx][decIdx] = decode;
- }
- }
-
- /* Apply selective decoding scenario */
- err = ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix( decHandle, selective_decoding_matrix );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* verify correct decoder actions */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- assert( decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame == 0 );
- if(NULL != decHandle->bitstream_caches)
- {
- assert( 0 == decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- }
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
-
- err = ISAR_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstream_in_size, pcm_out );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* verify correct post decoding state */
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 0 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame);
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 == decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- }
-
- ISAR_LC3PLUS_DEC_FreeSubframeDecodingMatrix( selective_decoding_matrix );
- return IVAS_ERR_OK;
-}
-
-
-/*
- * in: [dec, dec, skip, skip]
- * expected out: [dec_and_use, dec_and_use, skip, cache]
- */
-static int scenario_dont_decode_last_2_subframes(
- const LC3PLUS_CONFIG config,
- ISAR_LC3PLUS_DEC_HANDLE decHandle, /* i: decoder handle */
- uint8_t *bitstream_in, /* i: pointer to input bitstream */
- int32_t bitstream_in_size, /* i: size of bitstream_in */
- float **pcm_out /* o: decoded samples */ )
-{
- ivas_error err;
- const int16_t decode = 1;
- const int16_t skipDecoding = 0;
- uint32_t iDec = 0;
- int iLc3plusFrame = 0;
- int lc3framesPerIvasFrame;
- int16_t **selective_decoding_matrix;
- err = ISAR_LC3PLUS_DEC_AllocateSubframeDecodingMatrix( &selective_decoding_matrix, config.channels );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* Set selective decoding scenario */
- for ( int16_t iSubframeIdx = 0; iSubframeIdx < MAX_PARAM_SPATIAL_SUBFRAMES; iSubframeIdx++ )
- {
- for ( int16_t decIdx = 0; decIdx < config.channels; decIdx++ )
- {
- assert( MAX_PARAM_SPATIAL_SUBFRAMES == 4 );
- if ( iSubframeIdx == MAX_PARAM_SPATIAL_SUBFRAMES - 1 || iSubframeIdx == MAX_PARAM_SPATIAL_SUBFRAMES - 2 ) /*only valid for MAX_PARAM_SPATIAL_SUBFRAMES == 4 */
- {
- /* skip the last two subframes */
- selective_decoding_matrix[iSubframeIdx][decIdx] = skipDecoding;
- }
- else
- {
- /* decode the previous ones */
- selective_decoding_matrix[iSubframeIdx][decIdx] = decode;
- }
- }
- }
-
- /* Apply selective decoding scenario */
- err = ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix( decHandle, selective_decoding_matrix );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* verify correct decoder actions */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- if(NULL != decHandle->bitstream_caches)
- {
- assert( 0 == decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- }
- if ( iLc3plusFrame == lc3framesPerIvasFrame - 1 )
- {
- /* last subframe is expected to be cached */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_CACHE );
- }
- else if ( iLc3plusFrame == lc3framesPerIvasFrame - 2 )
- {
- /* subframe before the last one is expected to be skipped, since only the last one is required to flush the decoder after a pause */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_SKIP );
- }
- else
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
- }
-
- err = ISAR_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstream_in_size, pcm_out );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* verify correct decoder caching */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 1 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 != decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- /* default action after decoding should be DEC_ACTION_DECODE_AND_USE again */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
-
- ISAR_LC3PLUS_DEC_FreeSubframeDecodingMatrix( selective_decoding_matrix );
- return IVAS_ERR_OK;
-}
-
-/*
- * in: [dec, skip, skip, skip]
- * expected out: [dec_and_use, skip, skip, cache]
- */
-static int scenario_dont_decode_last_3_subframes(
- const LC3PLUS_CONFIG config,
- ISAR_LC3PLUS_DEC_HANDLE decHandle, /* i: decoder handle */
- uint8_t *bitstream_in, /* i: pointer to input bitstream */
- int32_t bitstream_in_size, /* i: size of bitstream_in */
- float **pcm_out /* o: decoded samples */ )
-{
- ivas_error err;
- const int16_t decode = 1;
- const int16_t skipDecoding = 0;
- uint32_t iDec = 0;
- int iLc3plusFrame = 0;
- int lc3framesPerIvasFrame;
- int16_t **selective_decoding_matrix;
- err = ISAR_LC3PLUS_DEC_AllocateSubframeDecodingMatrix( &selective_decoding_matrix, config.channels );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* Set selective decoding scenario */
- for ( int16_t iSubframeIdx = 0; iSubframeIdx < MAX_PARAM_SPATIAL_SUBFRAMES; iSubframeIdx++ )
- {
- for ( int16_t decIdx = 0; decIdx < config.channels; decIdx++ )
- {
- assert( MAX_PARAM_SPATIAL_SUBFRAMES == 4 );
- if ( iSubframeIdx == MAX_PARAM_SPATIAL_SUBFRAMES - 1 || iSubframeIdx == MAX_PARAM_SPATIAL_SUBFRAMES - 2 || iSubframeIdx == MAX_PARAM_SPATIAL_SUBFRAMES - 3 ) /*only valid for MAX_PARAM_SPATIAL_SUBFRAMES == 4 */
- {
- /* skip the last three subframes */
- selective_decoding_matrix[iSubframeIdx][decIdx] = skipDecoding;
- }
- else
- {
- /* decode the previous ones */
- selective_decoding_matrix[iSubframeIdx][decIdx] = decode;
- }
- }
- }
-
- /* Apply selective decoding scenario */
- err = ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix( decHandle, selective_decoding_matrix );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* verify correct decoder actions */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 0 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 == decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- if ( iLc3plusFrame == lc3framesPerIvasFrame - 1 )
- {
- /* last subframe is expected to be cached */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_CACHE );
- }
- else if ( iLc3plusFrame == lc3framesPerIvasFrame - 2 )
- {
- /* subframes before the last one is expected to be skipped, since only the last one is required to flush the decoder after a pause */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_SKIP );
- }
- else if ( iLc3plusFrame == lc3framesPerIvasFrame - 3 )
- {
- /* subframes before the last one is expected to be skipped, since only the last one is required to flush the decoder after a pause */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_SKIP );
- }
- else
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
- }
-
- err = ISAR_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstream_in_size, pcm_out );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* verify correct decoder caching */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 1 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 != decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- /* default action after decoding should be DEC_ACTION_DECODE_AND_USE again */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
-
- ISAR_LC3PLUS_DEC_FreeSubframeDecodingMatrix( selective_decoding_matrix );
- return IVAS_ERR_OK;
-}
-
-
-/*
- * in: [skip, dec, dec, dec]
- * expected out: [dec_and_drop, dec_and_use, dec_and_use, dec_and_use]
- */
-static int scenario_skip_first_subframe(
- const LC3PLUS_CONFIG config,
- ISAR_LC3PLUS_DEC_HANDLE decHandle, /* i: decoder handle */
- uint8_t *bitstream_in, /* i: pointer to input bitstream */
- int32_t bitstream_in_size, /* i: size of bitstream_in */
- float **pcm_out /* o: decoded samples */ )
-{
- ivas_error err;
- const int16_t decode = 1;
- const int16_t skipDecoding = 0;
- uint32_t iDec = 0;
- int iLc3plusFrame = 0;
- int lc3framesPerIvasFrame;
- int16_t **selective_decoding_matrix;
- err = ISAR_LC3PLUS_DEC_AllocateSubframeDecodingMatrix( &selective_decoding_matrix, config.channels );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* Set selective decoding scenario */
- for ( int16_t iSubframeIdx = 0; iSubframeIdx < MAX_PARAM_SPATIAL_SUBFRAMES; iSubframeIdx++ )
- {
- for ( int16_t decIdx = 0; decIdx < config.channels; decIdx++ )
- {
- if ( iSubframeIdx == 0 )
- {
- /* skip the first subframe */
- selective_decoding_matrix[iSubframeIdx][decIdx] = skipDecoding;
- }
- else
- {
- /* decode the following subframes */
- selective_decoding_matrix[iSubframeIdx][decIdx] = decode;
- }
- }
- }
-
- /* Apply selective decoding scenario */
- err = ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix( decHandle, selective_decoding_matrix );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* verify correct decoder actions */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 == decHandle->bitstream_caches[iDec]->bitstream_cache_size );
-
- if ( iLc3plusFrame == 0 )
- {
- /* first subframe is expected to be decoded and dropped */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_DROP );
- }
- else
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
- }
-
- err = ISAR_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstream_in_size, pcm_out );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* verify correct decoder caching */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 0 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 == decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- /* default action after decoding should be DEC_ACTION_DECODE_AND_USE again */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
-
- ISAR_LC3PLUS_DEC_FreeSubframeDecodingMatrix( selective_decoding_matrix );
- return IVAS_ERR_OK;
-}
-
-/*
- * Step1:
- * in: [dec, dec, skip, skip]
- * expected out: [dec_and_use, dec_and_use, skip, cache]
- *
- * Step2:
- * in: [dec, dec, dec, dec]
- * expected out: [dec_cache & dec_and_use, dec_and_use, dec_and_use, dec_and_use]
- */
-static int scenario_decode_cache(
- const LC3PLUS_CONFIG config,
- ISAR_LC3PLUS_DEC_HANDLE decHandle, /* i: decoder handle */
- uint8_t *bitstream_in, /* i: pointer to input bitstream */
- int32_t bitstream_in_size, /* i: size of bitstream_in */
- float **pcm_out /* o: decoded samples */ )
-{
- ivas_error err;
- const int16_t decode = 1;
- const int16_t skipDecoding = 0;
- uint32_t iDec = 0;
- int iLc3plusFrame = 0;
- int lc3framesPerIvasFrame;
- int16_t **selective_decoding_matrix;
- err = ISAR_LC3PLUS_DEC_AllocateSubframeDecodingMatrix( &selective_decoding_matrix, config.channels );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* Set selective decoding scenario */
- for ( int16_t iSubframeIdx = 0; iSubframeIdx < MAX_PARAM_SPATIAL_SUBFRAMES; iSubframeIdx++ )
- {
- for ( int16_t decIdx = 0; decIdx < config.channels; decIdx++ )
- {
- assert( MAX_PARAM_SPATIAL_SUBFRAMES == 4 );
- if ( iSubframeIdx == MAX_PARAM_SPATIAL_SUBFRAMES - 1 || iSubframeIdx == MAX_PARAM_SPATIAL_SUBFRAMES - 2 ) /*only valid for MAX_PARAM_SPATIAL_SUBFRAMES == 4 */
- {
- /* skip the last two subframes */
- selective_decoding_matrix[iSubframeIdx][decIdx] = skipDecoding;
- }
- else
- {
- /* decode the previous ones */
- selective_decoding_matrix[iSubframeIdx][decIdx] = decode;
- }
- }
- }
-
- /* Apply selective decoding scenario */
- err = ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix( decHandle, selective_decoding_matrix );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* verify correct decoder actions */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 0 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 == decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
-
- if ( iLc3plusFrame == lc3framesPerIvasFrame - 1 )
- {
- /* last subframe is expected to be cached */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_CACHE );
- }
- else if ( iLc3plusFrame == lc3framesPerIvasFrame - 2 )
- {
- /* subframe before the last one is expected to be skipped, since only the last one is required to flush the decoder after a pause */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_SKIP );
- }
- else
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
- }
-
- err = ISAR_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstream_in_size, pcm_out );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* verify correct decoder caching */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 1 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 != decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- /* default action after decoding should be DEC_ACTION_DECODE_AND_USE again */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
-
- /* Step 2, ensure that the cache is used */
- for ( int16_t iSubframeIdx = 0; iSubframeIdx < MAX_PARAM_SPATIAL_SUBFRAMES; iSubframeIdx++ )
- {
- for ( int16_t decIdx = 0; decIdx < config.channels; decIdx++ )
- {
- /* decode all */
- selective_decoding_matrix[iSubframeIdx][decIdx] = decode;
- }
- }
- /* Apply selective decoding scenario */
- err = ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix( decHandle, selective_decoding_matrix );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
- /* verify correct decoder actions */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 1 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 1 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 != decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
- err = ISAR_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstream_in_size, pcm_out );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
- /* verify correct post-decoding state */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 0 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 == decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- /* default action after decoding should be DEC_ACTION_DECODE_AND_USE again */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
-
- ISAR_LC3PLUS_DEC_FreeSubframeDecodingMatrix( selective_decoding_matrix );
- return IVAS_ERR_OK;
-}
-
-/*
- * Step1:
- * in: [skip, skip, dec, dec]
- * expected out: [skip, dec_and_drop, dec_and_use, dec_and_use]
- *
- * Step2:
- * in: [dec, dec, dec, dec]
- * expected out: [no_cache & dec_and_use, dec_and_use, dec_and_use, dec_and_use]
- */
-static int scenario_get_active_dont_cache(
- const LC3PLUS_CONFIG config,
- ISAR_LC3PLUS_DEC_HANDLE decHandle, /* i: decoder handle */
- uint8_t *bitstream_in, /* i: pointer to input bitstream */
- int32_t bitstream_in_size, /* i: size of bitstream_in */
- float **pcm_out /* o: decoded samples */ )
-{
- ivas_error err;
- const int16_t decode = 1;
- const int16_t skipDecoding = 0;
- uint32_t iDec = 0;
- int iLc3plusFrame = 0;
- int lc3framesPerIvasFrame;
- int16_t **selective_decoding_matrix;
- err = ISAR_LC3PLUS_DEC_AllocateSubframeDecodingMatrix( &selective_decoding_matrix, config.channels );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* Set selective decoding scenario */
- for ( int16_t iSubframeIdx = 0; iSubframeIdx < MAX_PARAM_SPATIAL_SUBFRAMES; iSubframeIdx++ )
- {
- for ( int16_t decIdx = 0; decIdx < config.channels; decIdx++ )
- {
- assert( MAX_PARAM_SPATIAL_SUBFRAMES == 4 );
- if ( iSubframeIdx == MAX_PARAM_SPATIAL_SUBFRAMES - 1 || iSubframeIdx == MAX_PARAM_SPATIAL_SUBFRAMES - 2 ) /*only valid for MAX_PARAM_SPATIAL_SUBFRAMES == 4 */
- {
- /* skip the last two subframes */
- selective_decoding_matrix[iSubframeIdx][decIdx] = decode;
- }
- else
- {
- /* decode the previous ones */
- selective_decoding_matrix[iSubframeIdx][decIdx] = skipDecoding;
- }
- }
- }
-
- /* Apply selective decoding scenario */
- err = ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix( decHandle, selective_decoding_matrix );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* verify correct decoder actions
- * * expected out: [skip, dec_and_drop, dec_and_use, dec_and_use] */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 0 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 == decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- if ( iLc3plusFrame == lc3framesPerIvasFrame - 1 )
- {
- /* last subframe is expected to be cached */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- else if ( iLc3plusFrame == lc3framesPerIvasFrame - 2 )
- {
- /* subframe before the last one is expected to be skipped, since only the last one is required to flush the decoder after a pause */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- else if ( iLc3plusFrame == lc3framesPerIvasFrame - 3 )
- {
- /* subframe before the last one is expected to be skipped, since only the last one is required to flush the decoder after a pause */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_DROP );
- }
- else
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_SKIP );
- }
- }
- }
-
- err = ISAR_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstream_in_size, pcm_out );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* verify correct decoder caching */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 0 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 == decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- /* default action after decoding should be DEC_ACTION_DECODE_AND_USE again */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
-
- /* Step 2, ensure that there is no cache */
- for ( int16_t iSubframeIdx = 0; iSubframeIdx < MAX_PARAM_SPATIAL_SUBFRAMES; iSubframeIdx++ )
- {
- for ( int16_t decIdx = 0; decIdx < config.channels; decIdx++ )
- {
- /* decode all [dec, dec, dec, dec]*/
- selective_decoding_matrix[iSubframeIdx][decIdx] = decode;
- }
- }
- /* Apply selective decoding scenario */
- err = ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix( decHandle, selective_decoding_matrix );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
- /* verify correct decoder actions
- * expected out: [no_cache & dec_and_use, dec_and_use, dec_and_use, dec_and_use]*/
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 0 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 == decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
- err = ISAR_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstream_in_size, pcm_out );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
- /* verify correct post-decoding state */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 0 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 == decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- /* default action after decoding should be DEC_ACTION_DECODE_AND_USE again */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
-
- ISAR_LC3PLUS_DEC_FreeSubframeDecodingMatrix( selective_decoding_matrix );
- return IVAS_ERR_OK;
-}
-
-
-/*
- * Step1:
- * in: [dec, dec, skip, skip]
- * expected out: [dec_and_use, dec_and_use, skip, cache]
- *
- * Step2:
- * in: [skip, dec, skip, dec]
- * expected out: [drop_cache & dec_and_drop, dec_and_use, dec_and_drop, dec_and_use]
- * */
-static int scenario_per_subframe_switches_skip_first(
- const LC3PLUS_CONFIG config,
- ISAR_LC3PLUS_DEC_HANDLE decHandle, /* i: decoder handle */
- uint8_t *bitstream_in, /* i: pointer to input bitstream */
- int32_t bitstream_in_size, /* i: size of bitstream_in */
- float **pcm_out /* o: decoded samples */ )
-{
- ivas_error err;
- const int16_t decode = 1;
- const int16_t skipDecoding = 0;
- uint32_t iDec = 0;
- int iLc3plusFrame = 0;
- int lc3framesPerIvasFrame;
- int16_t **selective_decoding_matrix;
- err = ISAR_LC3PLUS_DEC_AllocateSubframeDecodingMatrix( &selective_decoding_matrix, config.channels );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* Set selective decoding scenario */
- for ( int16_t iSubframeIdx = 0; iSubframeIdx < MAX_PARAM_SPATIAL_SUBFRAMES; iSubframeIdx++ )
- {
- for ( int16_t decIdx = 0; decIdx < config.channels; decIdx++ )
- {
- assert( MAX_PARAM_SPATIAL_SUBFRAMES == 4 );
- if ( iSubframeIdx == MAX_PARAM_SPATIAL_SUBFRAMES - 1 || iSubframeIdx == MAX_PARAM_SPATIAL_SUBFRAMES - 2 ) /*only valid for MAX_PARAM_SPATIAL_SUBFRAMES == 4 */
- {
- /* skip the last two subframes */
- selective_decoding_matrix[iSubframeIdx][decIdx] = skipDecoding;
- }
- else
- {
- /* decode the previous ones */
- selective_decoding_matrix[iSubframeIdx][decIdx] = decode;
- }
- }
- }
-
- /* Apply selective decoding scenario */
- err = ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix( decHandle, selective_decoding_matrix );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* verify correct decoder actions */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 0 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 == decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- if ( iLc3plusFrame == lc3framesPerIvasFrame - 1 )
- {
- /* last subframe is expected to be cached */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_CACHE );
- }
- else if ( iLc3plusFrame == lc3framesPerIvasFrame - 2 )
- {
- /* subframe before the last one is expected to be skipped, since only the last one is required to flush the decoder after a pause */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_SKIP );
- }
- else
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
- }
-
- err = ISAR_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstream_in_size, pcm_out );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* verify correct decoder caching */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 1 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 != decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- /* default action after decoding should be DEC_ACTION_DECODE_AND_USE again */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
-
- /* Step 2
- * in: [skip, dec, skip, dec]
- * */
- for ( int16_t iSubframeIdx = 0; iSubframeIdx < MAX_PARAM_SPATIAL_SUBFRAMES; iSubframeIdx++ )
- {
- for ( int16_t decIdx = 0; decIdx < config.channels; decIdx++ )
- {
- if(iSubframeIdx == 0 || iSubframeIdx == 2)
- {
- selective_decoding_matrix[iSubframeIdx][decIdx] = skipDecoding;
- }
- else if(iSubframeIdx == 1 || iSubframeIdx == 3)
- {
- selective_decoding_matrix[iSubframeIdx][decIdx] = decode;
- }
- else
- {
- //unsupported iSubframeIdx count;
- return 1;
- }
-
- }
- }
- /* Apply selective decoding scenario */
- err = ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix( decHandle, selective_decoding_matrix );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* verify correct decoder actions
- * expected out: [drop_cache & dec_and_drop, dec_and_use, dec_and_drop, dec_and_use]
- * */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 1 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 != decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- if ( iLc3plusFrame == 1 || iLc3plusFrame == 3)
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- else if ( iLc3plusFrame == 0 || iLc3plusFrame == 2)
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_DROP );
- }
- else
- {
- assert(0);
- }
- }
- }
- err = ISAR_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstream_in_size, pcm_out );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
- /* verify correct post-decoding state */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 0 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 == decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- /* default action after decoding should be DEC_ACTION_DECODE_AND_USE again */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
-
- ISAR_LC3PLUS_DEC_FreeSubframeDecodingMatrix( selective_decoding_matrix );
- return IVAS_ERR_OK;
-}
-
-/*
- * Step1:
- * in: [dec, dec, skip, skip]
- * expected out: [dec_and_use, dec_and_use, skip, cache]
- *
- * Step2:
- * in: [dec, skip, dec, skip]
- * expected out: [dec_cache & dec_and_use, dec_and_drop, dec_and_use, cache]
- * */
-static int scenario_per_subframe_switches_dec_first(
- const LC3PLUS_CONFIG config,
- ISAR_LC3PLUS_DEC_HANDLE decHandle, /* i: decoder handle */
- uint8_t *bitstream_in, /* i: pointer to input bitstream */
- int32_t bitstream_in_size, /* i: size of bitstream_in */
- float **pcm_out /* o: decoded samples */ )
-{
- ivas_error err;
- const int16_t decode = 1;
- const int16_t skipDecoding = 0;
- uint32_t iDec = 0;
- int iLc3plusFrame = 0;
- int lc3framesPerIvasFrame;
- int16_t **selective_decoding_matrix;
- err = ISAR_LC3PLUS_DEC_AllocateSubframeDecodingMatrix( &selective_decoding_matrix, config.channels );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* Set selective decoding scenario */
- for ( int16_t iSubframeIdx = 0; iSubframeIdx < MAX_PARAM_SPATIAL_SUBFRAMES; iSubframeIdx++ )
- {
- for ( int16_t decIdx = 0; decIdx < config.channels; decIdx++ )
- {
- assert( MAX_PARAM_SPATIAL_SUBFRAMES == 4 );
- if ( iSubframeIdx == MAX_PARAM_SPATIAL_SUBFRAMES - 1 || iSubframeIdx == MAX_PARAM_SPATIAL_SUBFRAMES - 2 ) /*only valid for MAX_PARAM_SPATIAL_SUBFRAMES == 4 */
- {
- /* skip the last two subframes */
- selective_decoding_matrix[iSubframeIdx][decIdx] = skipDecoding;
- }
- else
- {
- /* decode the previous ones */
- selective_decoding_matrix[iSubframeIdx][decIdx] = decode;
- }
- }
- }
-
- /* Apply selective decoding scenario */
- err = ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix( decHandle, selective_decoding_matrix );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* verify correct decoder actions */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 0 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 == decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- if ( iLc3plusFrame == lc3framesPerIvasFrame - 1 )
- {
- /* last subframe is expected to be cached */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_CACHE );
- }
- else if ( iLc3plusFrame == lc3framesPerIvasFrame - 2 )
- {
- /* subframe before the last one is expected to be skipped, since only the last one is required to flush the decoder after a pause */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_SKIP );
- }
- else
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
- }
-
- err = ISAR_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstream_in_size, pcm_out );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* verify correct decoder caching */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 1 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 != decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- /* default action after decoding should be DEC_ACTION_DECODE_AND_USE again */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
-
- /* Step 2
- * in: [dec, skip, dec, skip]
- * */
- for ( int16_t iSubframeIdx = 0; iSubframeIdx < MAX_PARAM_SPATIAL_SUBFRAMES; iSubframeIdx++ )
- {
- for ( int16_t decIdx = 0; decIdx < config.channels; decIdx++ )
- {
- if(iSubframeIdx == 0 || iSubframeIdx == 2)
- {
- selective_decoding_matrix[iSubframeIdx][decIdx] = decode;
- }
- else if(iSubframeIdx == 1 || iSubframeIdx == 3)
- {
- selective_decoding_matrix[iSubframeIdx][decIdx] = skipDecoding;
- }
- else
- {
- // unsupported iSubframeIdx count
- return 1;
- }
-
- }
- }
- /* Apply selective decoding scenario */
- err = ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix( decHandle, selective_decoding_matrix );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* verify correct decoder actions
- * expected out: [dec_cache & dec_and_use, dec_and_drop, dec_and_use, cache]
- * */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 1 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 1 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 != decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- if ( iLc3plusFrame == 0 )
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- else if ( iLc3plusFrame == 1 )
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_DROP );
- }
- else if ( iLc3plusFrame == 2 )
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- else if ( iLc3plusFrame == 3)
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_CACHE );
- }
- else
- {
- assert(0);
- }
- }
- }
- err = ISAR_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstream_in_size, pcm_out );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
- /* verify correct post-decoding state */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 1 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 != decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- /* default action after decoding should be DEC_ACTION_DECODE_AND_USE again */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
-
- ISAR_LC3PLUS_DEC_FreeSubframeDecodingMatrix( selective_decoding_matrix );
- return IVAS_ERR_OK;
-}
-
-#ifdef LC3PLUS_DEC_ALLOW_DISABLE_CACHING
-/*
- * Step1:
- * in: [dec, dec, skip, skip]
- * expected out: [dec_and_use, dec_and_use, skip, skip]
- *
- * Step2:
- * in: [dec, skip, dec, skip]
- * expected out: [drop_cache & dec_and_use, skip, dec_and_use, skip]
- * */
-static int scenario_per_subframe_switches_dec_first_no_caching(
- const LC3PLUS_CONFIG config,
- ISAR_LC3PLUS_DEC_HANDLE decHandle, /* i: decoder handle */
- uint8_t *bitstream_in, /* i: pointer to input bitstream */
- int32_t bitstream_in_size, /* i: size of bitstream_in */
- float **pcm_out /* o: decoded samples */ )
-{
- ivas_error err;
- const int16_t decode = 1;
- const int16_t skipDecoding = 0;
- uint32_t iDec = 0;
- int iLc3plusFrame = 0;
- int lc3framesPerIvasFrame;
- int16_t **selective_decoding_matrix;
- err = ISAR_LC3PLUS_DEC_AllocateSubframeDecodingMatrix( &selective_decoding_matrix, config.channels );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* Set selective decoding scenario */
- for ( int16_t iSubframeIdx = 0; iSubframeIdx < MAX_PARAM_SPATIAL_SUBFRAMES; iSubframeIdx++ )
- {
- for ( int16_t decIdx = 0; decIdx < config.channels; decIdx++ )
- {
- assert( MAX_PARAM_SPATIAL_SUBFRAMES == 4 );
- if ( iSubframeIdx == MAX_PARAM_SPATIAL_SUBFRAMES - 1 || iSubframeIdx == MAX_PARAM_SPATIAL_SUBFRAMES - 2 ) /*only valid for MAX_PARAM_SPATIAL_SUBFRAMES == 4 */
- {
- /* skip the last two subframes */
- selective_decoding_matrix[iSubframeIdx][decIdx] = skipDecoding;
- }
- else
- {
- /* decode the previous ones */
- selective_decoding_matrix[iSubframeIdx][decIdx] = decode;
- }
- }
- }
-
- /* Apply selective decoding scenario */
- err = ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix( decHandle, selective_decoding_matrix );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* verify correct decoder actions */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 0 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( NULL == decHandle->bitstream_caches );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- if ( iLc3plusFrame == lc3framesPerIvasFrame - 1 )
- {
- /* last subframe is expected to be cached */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_SKIP );
- }
- else if ( iLc3plusFrame == lc3framesPerIvasFrame - 2 )
- {
- /* subframe before the last one is expected to be skipped, since only the last one is required to flush the decoder after a pause */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_SKIP );
- }
- else
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
- }
-
- err = ISAR_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstream_in_size, pcm_out );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* verify correct decoder caching */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 1 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( NULL == decHandle->bitstream_caches );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- /* default action after decoding should be DEC_ACTION_DECODE_AND_USE again */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
-
- /* Step 2
- * in: [dec, skip, dec, skip]
- * */
- for ( int16_t iSubframeIdx = 0; iSubframeIdx < MAX_PARAM_SPATIAL_SUBFRAMES; iSubframeIdx++ )
- {
- for ( int16_t decIdx = 0; decIdx < config.channels; decIdx++ )
- {
- if(iSubframeIdx == 0 || iSubframeIdx == 2)
- {
- selective_decoding_matrix[iSubframeIdx][decIdx] = decode;
- }
- else if(iSubframeIdx == 1 || iSubframeIdx == 3)
- {
- selective_decoding_matrix[iSubframeIdx][decIdx] = skipDecoding;
- }
- else
- {
- // unsupported iSubframeIdx count
- return 1;
- }
-
- }
- }
- /* Apply selective decoding scenario */
- err = ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix( decHandle, selective_decoding_matrix );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* verify correct decoder actions
- * expected out: [drop_cache & dec_and_use, skip, dec_and_use, skip]
- * */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 1 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( NULL == decHandle->bitstream_caches );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- if ( iLc3plusFrame == 0 )
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- else if ( iLc3plusFrame == 1 )
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_SKIP );
- }
- else if ( iLc3plusFrame == 2 )
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- else if ( iLc3plusFrame == 3)
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_SKIP );
- }
- else
- {
- assert(0);
- }
- }
- }
- err = ISAR_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstream_in_size, pcm_out );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
- /* verify correct post-decoding state */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 1 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( NULL == decHandle->bitstream_caches );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- /* default action after decoding should be DEC_ACTION_DECODE_AND_USE again */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
-
- ISAR_LC3PLUS_DEC_FreeSubframeDecodingMatrix( selective_decoding_matrix );
- return IVAS_ERR_OK;
-}
-#endif
-
-/*
- * Step1:
- * in: [dec, dec, skip, skip]
- * expected out: [dec_and_use, dec_and_use, skip, cache]
- *
- * Step2:
- * in: [dec, skip, skip, dec]
- * expected out: [dec_cache & dec_and_use, skip, dec_and_drop, dec_and_use]
- * */
-static int scenario_per_subframe_bundle_switches_dec_first(
- const LC3PLUS_CONFIG config,
- ISAR_LC3PLUS_DEC_HANDLE decHandle, /* i: decoder handle */
- uint8_t *bitstream_in, /* i: pointer to input bitstream */
- int32_t bitstream_in_size, /* i: size of bitstream_in */
- float **pcm_out /* o: decoded samples */ )
-{
- ivas_error err;
- const int16_t decode = 1;
- const int16_t skipDecoding = 0;
- uint32_t iDec = 0;
- int iLc3plusFrame = 0;
- int lc3framesPerIvasFrame;
- int16_t **selective_decoding_matrix;
- err = ISAR_LC3PLUS_DEC_AllocateSubframeDecodingMatrix( &selective_decoding_matrix, config.channels );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* Set selective decoding scenario */
- for ( int16_t iSubframeIdx = 0; iSubframeIdx < MAX_PARAM_SPATIAL_SUBFRAMES; iSubframeIdx++ )
- {
- for ( int16_t decIdx = 0; decIdx < config.channels; decIdx++ )
- {
- assert( MAX_PARAM_SPATIAL_SUBFRAMES == 4 );
- if ( iSubframeIdx == MAX_PARAM_SPATIAL_SUBFRAMES - 1 || iSubframeIdx == MAX_PARAM_SPATIAL_SUBFRAMES - 2 ) /*only valid for MAX_PARAM_SPATIAL_SUBFRAMES == 4 */
- {
- /* skip the last two subframes */
- selective_decoding_matrix[iSubframeIdx][decIdx] = skipDecoding;
- }
- else
- {
- /* decode the previous ones */
- selective_decoding_matrix[iSubframeIdx][decIdx] = decode;
- }
- }
- }
-
- /* Apply selective decoding scenario */
- err = ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix( decHandle, selective_decoding_matrix );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* verify correct decoder actions */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 0 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 == decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- if ( iLc3plusFrame == lc3framesPerIvasFrame - 1 )
- {
- /* last subframe is expected to be cached */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_CACHE );
- }
- else if ( iLc3plusFrame == lc3framesPerIvasFrame - 2 )
- {
- /* subframe before the last one is expected to be skipped, since only the last one is required to flush the decoder after a pause */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_SKIP );
- }
- else
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
- }
-
- err = ISAR_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstream_in_size, pcm_out );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* verify correct decoder caching */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 1 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 != decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- /* default action after decoding should be DEC_ACTION_DECODE_AND_USE again */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
-
- /* Step 2
- * in: [dec, skip, skip, dec]
- * */
- for ( int16_t iSubframeIdx = 0; iSubframeIdx < MAX_PARAM_SPATIAL_SUBFRAMES; iSubframeIdx++ )
- {
- for ( int16_t decIdx = 0; decIdx < config.channels; decIdx++ )
- {
- if(iSubframeIdx == 0 || iSubframeIdx == 3)
- {
- selective_decoding_matrix[iSubframeIdx][decIdx] = decode;
- }
- else if(iSubframeIdx == 1 || iSubframeIdx == 2)
- {
- selective_decoding_matrix[iSubframeIdx][decIdx] = skipDecoding;
- }
- else
- {
- // unsupported iSubframeIdx count
- return 1;
- }
-
- }
- }
- /* Apply selective decoding scenario */
- err = ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix( decHandle, selective_decoding_matrix );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* verify correct decoder actions
- * expected out: [dec_cache & dec_and_use, skip, dec_and_drop, dec_and_use]
- * */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 1 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 1 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 != decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- if ( iLc3plusFrame == 0 )
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- else if ( iLc3plusFrame == 1 )
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_SKIP );
- }
- else if ( iLc3plusFrame == 2 )
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_DROP );
- }
- else if ( iLc3plusFrame == 3)
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- else
- {
- assert(0);
- }
- }
- }
- err = ISAR_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstream_in_size, pcm_out );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
- /* verify correct post-decoding state */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 0 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 == decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- /* default action after decoding should be DEC_ACTION_DECODE_AND_USE again */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
-
- ISAR_LC3PLUS_DEC_FreeSubframeDecodingMatrix( selective_decoding_matrix );
- return IVAS_ERR_OK;
-}
-
-/*
- * Step1:
- * in: [dec, dec, skip, skip]
- * expected out: [dec_and_use, dec_and_use, skip, cache]
- *
- * Step2:
- * in: [skip, dec, dec, skip]
- * expected out: [drop_cache & dec_and_drop, dec_and_use, dec_and_use, cache]
- * */
-static int scenario_per_subframe_bundle_switches_skip_first(
- const LC3PLUS_CONFIG config,
- ISAR_LC3PLUS_DEC_HANDLE decHandle, /* i: decoder handle */
- uint8_t *bitstream_in, /* i: pointer to input bitstream */
- int32_t bitstream_in_size, /* i: size of bitstream_in */
- float **pcm_out /* o: decoded samples */ )
-{
- ivas_error err;
- const int16_t decode = 1;
- const int16_t skipDecoding = 0;
- uint32_t iDec = 0;
- int iLc3plusFrame = 0;
- int lc3framesPerIvasFrame;
- int16_t **selective_decoding_matrix;
- err = ISAR_LC3PLUS_DEC_AllocateSubframeDecodingMatrix( &selective_decoding_matrix, config.channels );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* Set selective decoding scenario */
- for ( int16_t iSubframeIdx = 0; iSubframeIdx < MAX_PARAM_SPATIAL_SUBFRAMES; iSubframeIdx++ )
- {
- for ( int16_t decIdx = 0; decIdx < config.channels; decIdx++ )
- {
- assert( MAX_PARAM_SPATIAL_SUBFRAMES == 4 );
- if ( iSubframeIdx == MAX_PARAM_SPATIAL_SUBFRAMES - 1 || iSubframeIdx == MAX_PARAM_SPATIAL_SUBFRAMES - 2 ) /*only valid for MAX_PARAM_SPATIAL_SUBFRAMES == 4 */
- {
- /* skip the last two subframes */
- selective_decoding_matrix[iSubframeIdx][decIdx] = skipDecoding;
- }
- else
- {
- /* decode the previous ones */
- selective_decoding_matrix[iSubframeIdx][decIdx] = decode;
- }
- }
- }
-
- /* Apply selective decoding scenario */
- err = ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix( decHandle, selective_decoding_matrix );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* verify correct decoder actions */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 0 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 == decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- if ( iLc3plusFrame == lc3framesPerIvasFrame - 1 )
- {
- /* last subframe is expected to be cached */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_CACHE );
- }
- else if ( iLc3plusFrame == lc3framesPerIvasFrame - 2 )
- {
- /* subframe before the last one is expected to be skipped, since only the last one is required to flush the decoder after a pause */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_SKIP );
- }
- else
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
- }
-
- err = ISAR_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstream_in_size, pcm_out );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* verify correct decoder caching */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 1 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 != decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- /* default action after decoding should be DEC_ACTION_DECODE_AND_USE again */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
-
- /* Step 2
- * in: [skip, dec, dec, skip]
- * */
- for ( int16_t iSubframeIdx = 0; iSubframeIdx < MAX_PARAM_SPATIAL_SUBFRAMES; iSubframeIdx++ )
- {
- for ( int16_t decIdx = 0; decIdx < config.channels; decIdx++ )
- {
- if(iSubframeIdx == 1 || iSubframeIdx == 2)
- {
- selective_decoding_matrix[iSubframeIdx][decIdx] = decode;
- }
- else if(iSubframeIdx == 0 || iSubframeIdx == 3)
- {
- selective_decoding_matrix[iSubframeIdx][decIdx] = skipDecoding;
- }
- else
- {
- // unsupported iSubframeIdx count
- return 1;
- }
-
- }
- }
- /* Apply selective decoding scenario */
- err = ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix( decHandle, selective_decoding_matrix );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
-
- /* verify correct decoder actions
- * expected out: [drop_cache & dec_and_drop, dec_and_use, dec_and_use, cache]
- * */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 1 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 != decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- if ( iLc3plusFrame == 0 )
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_DROP );
- }
- else if ( iLc3plusFrame == 1 )
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- else if ( iLc3plusFrame == 2 )
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- else if ( iLc3plusFrame == 3)
- {
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_CACHE );
- }
- else
- {
- assert(0);
- }
- }
- }
- err = ISAR_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstream_in_size, pcm_out );
- if ( IVAS_ERR_OK != err )
- {
- return err;
- }
- /* verify correct post-decoding state */
- lc3framesPerIvasFrame = decHandle->config.ivas_frame_duration_us / decHandle->config.lc3plus_frame_duration_us;
- for ( iDec = 0; iDec < decHandle->num_decs; iDec++ )
- {
- assert( 1 == decHandle->selective_decoding_states[iDec]->has_skipped_a_frame );
- assert( 0 == decHandle->selective_decoding_states[iDec]->shall_decode_cached_frame );
- assert( 0 != decHandle->bitstream_caches[iDec]->bitstream_cache_size );
- for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
- {
- /* default action after decoding should be DEC_ACTION_DECODE_AND_USE again */
- assert( decHandle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] == DEC_ACTION_DECODE_AND_USE );
- }
- }
-
- ISAR_LC3PLUS_DEC_FreeSubframeDecodingMatrix( selective_decoding_matrix );
- return IVAS_ERR_OK;
-}
-
-
-static int selectiveDecIvas20msLc3plus5ms_48kHz_scenario_decode_all_subframes( void )
-{
- int err;
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .ivas_frame_duration_us = 20 * 1000, .channels = 6, .samplerate = 48000 };
- const int16_t enableCaching = 1;
- err = encodeAndDecodeOne6chFrameFixture( config, enableCaching, 768000, &scenario_decode_all_subframes );
- if ( 0 != err )
- {
- return IVAS_ERROR( IVAS_ERR_INTERNAL, "test failed\n" );
- }
- return err;
-}
-
-static int selectiveDecIvas20msLc3plus5ms_48kHz_scenario_dont_decode_last_2_subframes( void )
-{
- int err = 0;
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .ivas_frame_duration_us = 20 * 1000, .channels = 6, .samplerate = 48000 };
- const int16_t enableCaching = 1;
- err = encodeAndDecodeOne6chFrameFixture( config, enableCaching, 768000, &scenario_dont_decode_last_2_subframes );
- if ( 0 != err )
- {
- return IVAS_ERROR( IVAS_ERR_INTERNAL, "test failed\n" );
- }
- return err;
-}
-
-static int selectiveDecIvas20msLc3plus5ms_48kHz_scenario_dont_decode_last_3_subframes( void )
-{
- int err = 0;
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .ivas_frame_duration_us = 20 * 1000, .channels = 6, .samplerate = 48000 };
- const int16_t enableCaching = 1;
- err = encodeAndDecodeOne6chFrameFixture( config, enableCaching, 768000, &scenario_dont_decode_last_3_subframes );
- if ( 0 != err )
- {
- return IVAS_ERROR( IVAS_ERR_INTERNAL, "test failed\n" );
- }
- return err;
-}
-
-static int selectiveDecIvas20msLc3plus5ms_48kHz_scenario_skip_first_subframe( void )
-{
- int err = 0;
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .ivas_frame_duration_us = 20 * 1000, .channels = 6, .samplerate = 48000 };
- const int16_t enableCaching = 1;
- err = encodeAndDecodeOne6chFrameFixture( config, enableCaching, 768000, &scenario_skip_first_subframe );
- if ( 0 != err )
- {
- return IVAS_ERROR( IVAS_ERR_INTERNAL, "test failed\n" );
- }
- return err;
-}
-
-static int selectiveDecIvas20msLc3plus5ms_48kHz_scenario_decode_cache( void )
-{
- int err = 0;
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .ivas_frame_duration_us = 20 * 1000, .channels = 6, .samplerate = 48000 };
- const int16_t enableCaching = 1;
- err = encodeAndDecodeOne6chFrameFixture( config, enableCaching, 768000, &scenario_decode_cache );
- if ( 0 != err )
- {
- return IVAS_ERROR( IVAS_ERR_INTERNAL, "test failed\n" );
- }
- return err;
-}
-
-static int selectiveDecIvas20msLc3plus5ms_48kHz_scenario_per_subframe_switches_skip_first( void )
-{
- int err = 0;
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .ivas_frame_duration_us = 20 * 1000, .channels = 6, .samplerate = 48000 };
- const int16_t enableCaching = 1;
- err = encodeAndDecodeOne6chFrameFixture( config, enableCaching, 768000, &scenario_per_subframe_switches_skip_first );
- if ( 0 != err )
- {
- return IVAS_ERROR( IVAS_ERR_INTERNAL, "test failed\n" );
- }
- return err;
-}
-
-static int selectiveDecIvas20msLc3plus5ms_48kHz_scenario_per_subframe_switches_dec_first( void )
-{
- int err = 0;
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .ivas_frame_duration_us = 20 * 1000, .channels = 6, .samplerate = 48000 };
- const int16_t enableCaching = 1;
- err = encodeAndDecodeOne6chFrameFixture( config, enableCaching, 768000, &scenario_per_subframe_switches_dec_first );
- if ( 0 != err )
- {
- return IVAS_ERROR( IVAS_ERR_INTERNAL, "test failed\n" );
- }
- return err;
-}
-
-static int selectiveDecIvas20msLc3plus5ms_48kHz_scenario_per_subframe_bundle_switches_dec_first( void )
-{
- int err = 0;
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .ivas_frame_duration_us = 20 * 1000, .channels = 6, .samplerate = 48000 };
- const int16_t enableCaching = 1;
- err = encodeAndDecodeOne6chFrameFixture( config, enableCaching, 768000, &scenario_per_subframe_bundle_switches_dec_first );
- if ( 0 != err )
- {
- return IVAS_ERROR( IVAS_ERR_INTERNAL, "test failed\n" );
- }
- return err;
-}
-
-static int selectiveDecIvas20msLc3plus5ms_48kHz_scenario_per_subframe_bundle_switches_skip_first( void )
-{
- int err = 0;
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .ivas_frame_duration_us = 20 * 1000, .channels = 6, .samplerate = 48000 };
- const int16_t enableCaching = 1;
- err = encodeAndDecodeOne6chFrameFixture( config, enableCaching, 768000, &scenario_per_subframe_bundle_switches_skip_first );
- if ( 0 != err )
- {
- return IVAS_ERROR( IVAS_ERR_INTERNAL, "test failed\n" );
- }
- return err;
-}
-
-#ifdef LC3PLUS_DEC_ALLOW_DISABLE_CACHING
-static int selectiveDecIvas20msLc3plus5ms_48kHz_scenario_per_subframe_switches_dec_first_no_caching( void )
-{
- int err = 0;
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .ivas_frame_duration_us = 20 * 1000, .channels = 6, .samplerate = 48000 };
- const int16_t enableCaching = 0;
- err = encodeAndDecodeOne6chFrameFixture( config, enableCaching, 768000, &scenario_per_subframe_switches_dec_first_no_caching );
- if ( 0 != err )
- {
- return IVAS_ERROR( IVAS_ERR_INTERNAL, "test failed\n" );
- }
- return err;
-}
-#endif
-
-static int selectiveDecIvas20msLc3plus5ms_48kHz_scenario_get_active_dont_cache( void )
-{
- int err = 0;
- LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .ivas_frame_duration_us = 20 * 1000, .channels = 6, .samplerate = 48000 };
- const int16_t enableCaching = 1;
- err = encodeAndDecodeOne6chFrameFixture( config, enableCaching, 768000, &scenario_get_active_dont_cache );
- if ( 0 != err )
- {
- return IVAS_ERROR( IVAS_ERR_INTERNAL, "test failed\n" );
- }
- return err;
-}
-#endif /* SPLIT_REND_WITH_HEAD_ROT */
diff --git a/tests/codec_be_on_mr_nonselection/test_param_file.py b/tests/codec_be_on_mr_nonselection/test_param_file.py
index 12e9208da89f6d57edf4e4cc486ffcdadea4ae5b..137000976fd2fc3e5533231f58f26cb7fc2e00ca 100644
--- a/tests/codec_be_on_mr_nonselection/test_param_file.py
+++ b/tests/codec_be_on_mr_nonselection/test_param_file.py
@@ -352,7 +352,12 @@ def test_param_file_tests(
max_diff =0
if output_differs:
search_result = re.search(MAX_DIFF_PATTERN, reason)
- max_diff = search_result.groups(1)[0]
+ if search_result:
+ max_diff = search_result.groups(1)[0]
+ else:
+ msg = "Error " + MAX_DIFF_PATTERN + " not found"
+ print(msg)
+ pytest.fail(msg)
record_property("MAXIMUM ABS DIFF", max_diff)
metadata_differs = False
diff --git a/tests/split_rendering/constants.py b/tests/split_rendering/constants.py
index 2c2530d3c61acc7a9339c9af476ac51ffe28a034..11c76e3d62db933effdf30eea2c852e42c98971e 100644
--- a/tests/split_rendering/constants.py
+++ b/tests/split_rendering/constants.py
@@ -44,6 +44,7 @@ from tests.renderer.constants import (
""" Set up paths """
TESTS_DIR = Path(__file__).parent
RENDER_CFG_DIR = TESTS_DIR.joinpath("renderer_configs").resolve()
+RENDER_FRAMING_CFG_DIR = TESTS_DIR.joinpath("renderer_configs").joinpath("framing").resolve()
ERROR_PATTERNS_DIR = TESTS_DIR.joinpath("error_patterns").resolve()
OUTPUT_PATH_REF = TESTS_DIR.joinpath("ref")
@@ -69,6 +70,10 @@ RENDERER_CONFIGS_FASTCONV_RENDERER = [
str(cfg.stem) for cfg in RENDER_CFG_DIR.glob("*_fastconv.txt")
]
+RENDERER_CONFIGS_FRAMING = [
+ str(cfg.stem) for cfg in RENDER_FRAMING_CFG_DIR.glob("framing*.txt")
+]
+
RENDERER_CONFIGS_TO_TEST_AMBI = (
RENDERER_CONFIGS_DEFAULT_CODEC + RENDERER_CONFIGS_LC3PLUS_CODEC
)
@@ -159,6 +164,8 @@ IVAS_MAX_ISM_BITRATE = {
}
RENDERER_FORMATS = ["BINAURAL_SPLIT_CODED", "BINAURAL_SPLIT_PCM"]
+SPLIT_RENDERER_PRE_FRAMINGS = ["5", "10", "20"]
+SPLIT_RENDERER_POST_FRAMINGS = ["5", "10", "20"]
INPUT_DURATION_SEC = 5
@@ -181,10 +188,12 @@ SPLIT_PRE_DEC_CMD = [
"", # 2 -> pre-trajectory file
"-render_config",
"", # 4 -> render config file
- "", # 5 -> renderer format
+ "-fr",
+ "", # 6 -> pre_rend_fs
+ "", # 7 -> renderer format
"48",
- "", # 7 -> encoder bitstream
- "", # 8 -> split rendering bitstream
+ "", # 9 -> encoder bitstream
+ "", # 10 -> split rendering bitstream
]
""" Split-pre Renderer commandline template """
@@ -204,6 +213,8 @@ SPLIT_PRE_REND_CMD = [
"", # 12 -> renderer format
"-T",
"", # 14 -> post-trajectory file
+ "-fr",
+ "", # 16 -> pre rend framing
]
""" Split-post Renderer commandline template """
@@ -219,4 +230,6 @@ SPLIT_POST_REND_CMD = [
"", # 8 -> output file
"-T",
"", # 10 -> post-trajectory file
+ "-fr",
+ "", # 12 -> frame size
]
diff --git a/tests/split_rendering/renderer_configs/framing/framing_lc3plus_0dof_10ms.txt b/tests/split_rendering/renderer_configs/framing/framing_lc3plus_0dof_10ms.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6b2aaca70ee8feed8c2f6932d2d05ddef719ff94
--- /dev/null
+++ b/tests/split_rendering/renderer_configs/framing/framing_lc3plus_0dof_10ms.txt
@@ -0,0 +1,6 @@
+[SPLITREND]
+BITRATE = 256000;
+DOF = 0;
+HQMODE = 0;
+FRAMESIZE = 10;
+CODEC = LC3PLUS;
diff --git a/tests/split_rendering/renderer_configs/framing/framing_lc3plus_0dof_5ms.txt b/tests/split_rendering/renderer_configs/framing/framing_lc3plus_0dof_5ms.txt
new file mode 100644
index 0000000000000000000000000000000000000000..1a9ea0b076213f675b86d3dee36e493b24b6f3eb
--- /dev/null
+++ b/tests/split_rendering/renderer_configs/framing/framing_lc3plus_0dof_5ms.txt
@@ -0,0 +1,6 @@
+[SPLITREND]
+BITRATE = 256000;
+DOF = 0;
+HQMODE = 0;
+FRAMESIZE = 5;
+CODEC = LC3PLUS;
diff --git a/tests/split_rendering/renderer_configs/framing/framing_lc3plus_1dof_10ms.txt b/tests/split_rendering/renderer_configs/framing/framing_lc3plus_1dof_10ms.txt
new file mode 100644
index 0000000000000000000000000000000000000000..568e62039665bc9231088f9a6d41ff704c917665
--- /dev/null
+++ b/tests/split_rendering/renderer_configs/framing/framing_lc3plus_1dof_10ms.txt
@@ -0,0 +1,7 @@
+[SPLITREND]
+BITRATE = 384000;
+DOF = 1;
+HQMODE = 0;
+FRAMESIZE = 10;
+CODEC = LC3PLUS;
+
diff --git a/tests/split_rendering/renderer_configs/framing/framing_lc3plus_1dof_5ms.txt b/tests/split_rendering/renderer_configs/framing/framing_lc3plus_1dof_5ms.txt
new file mode 100644
index 0000000000000000000000000000000000000000..bbbfa32168e96abc32ef0493cb3b667de73b283f
--- /dev/null
+++ b/tests/split_rendering/renderer_configs/framing/framing_lc3plus_1dof_5ms.txt
@@ -0,0 +1,7 @@
+[SPLITREND]
+BITRATE = 384000;
+DOF = 1;
+HQMODE = 0;
+FRAMESIZE = 5;
+CODEC = LC3PLUS;
+
diff --git a/tests/split_rendering/renderer_configs/framing/framing_lcld_0dof_10ms.txt b/tests/split_rendering/renderer_configs/framing/framing_lcld_0dof_10ms.txt
new file mode 100644
index 0000000000000000000000000000000000000000..2c8a639d15a819c94648f88286f8fc96f4a60e34
--- /dev/null
+++ b/tests/split_rendering/renderer_configs/framing/framing_lcld_0dof_10ms.txt
@@ -0,0 +1,7 @@
+[SPLITREND]
+BITRATE = 256000;
+DOF = 0;
+HQMODE = 0;
+FRAMESIZE = 10;
+CODEC = LCLD;
+
diff --git a/tests/split_rendering/renderer_configs/framing/framing_lcld_0dof_20ms.txt b/tests/split_rendering/renderer_configs/framing/framing_lcld_0dof_20ms.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9aff176960b60d662cd560da6b9bfc134ac7e06f
--- /dev/null
+++ b/tests/split_rendering/renderer_configs/framing/framing_lcld_0dof_20ms.txt
@@ -0,0 +1,7 @@
+[SPLITREND]
+BITRATE = 256000;
+DOF = 0;
+HQMODE = 0;
+FRAMESIZE = 20;
+CODEC = LCLD;
+
diff --git a/tests/split_rendering/renderer_configs/framing/framing_lcld_0dof_5ms.txt b/tests/split_rendering/renderer_configs/framing/framing_lcld_0dof_5ms.txt
new file mode 100644
index 0000000000000000000000000000000000000000..23ffd6a05e593da0516164a2af03a7c0f6f6fa9f
--- /dev/null
+++ b/tests/split_rendering/renderer_configs/framing/framing_lcld_0dof_5ms.txt
@@ -0,0 +1,7 @@
+[SPLITREND]
+BITRATE = 256000;
+DOF = 0;
+HQMODE = 0;
+FRAMESIZE = 5;
+CODEC = LCLD;
+
diff --git a/tests/split_rendering/renderer_configs/framing/framing_lcld_1dof_20ms.txt b/tests/split_rendering/renderer_configs/framing/framing_lcld_1dof_20ms.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b8b5856edfc04ad081de5860d04cf42a041c37dc
--- /dev/null
+++ b/tests/split_rendering/renderer_configs/framing/framing_lcld_1dof_20ms.txt
@@ -0,0 +1,7 @@
+[SPLITREND]
+BITRATE = 384000;
+DOF = 1;
+HQMODE = 0;
+FRAMESIZE = 20;
+CODEC = LCLD;
+
diff --git a/tests/split_rendering/test_split_rendering.py b/tests/split_rendering/test_split_rendering.py
index 96fcdf2d5b9328972efff249a3398b4e4bb70abb..b5886e478fdca4d5ef3647b231f1484d2bc93efe 100644
--- a/tests/split_rendering/test_split_rendering.py
+++ b/tests/split_rendering/test_split_rendering.py
@@ -35,37 +35,6 @@ import pytest
from tests.split_rendering.utils import *
-def check_xfail(test_info, in_fmt, render_config, bitrate=None):
- if (
- "768k" in render_config
- and "0dof" in render_config
- and (
- "lc3plus" in render_config
- or (
- in_fmt in INPUT_FORMATS_ISM_SPLIT_REND
- or in_fmt in INPUT_FORMATS_MC_SPLIT_REND
- )
- or (
- "external_split" in test_info.node.name
- and in_fmt in INPUT_FORMATS_AMBI_SPLIT_REND
- ) # CREND for external renderer ambisonics rendering uses LC3plus by default
- )
- ):
- pytest.xfail("0DOF 768kbps LC3plus codec is unsupported")
-
- if (
- "256k" in render_config or "320k" in render_config
- ) and "0dof" not in render_config:
- pytest.xfail("320kbps and lower are only supported with 0DOF")
-
- if (
- bitrate
- and (in_fmt in INPUT_FORMATS_ISM_SPLIT_REND)
- and (int(bitrate) > int(IVAS_MAX_ISM_BITRATE[in_fmt[-1]]))
- ):
- pytest.skip(f"Unsupported configuration with {in_fmt} at {bitrate}bps")
-
-
""" Ambisonics """
@@ -76,8 +45,6 @@ def check_xfail(test_info, in_fmt, render_config, bitrate=None):
def test_ambisonics_full_chain_split(
test_info, in_fmt, bitrate, render_config, trajectory
):
- check_xfail(test_info, in_fmt, render_config, bitrate)
-
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
@@ -95,8 +62,6 @@ def test_ambisonics_full_chain_split(
@pytest.mark.parametrize("render_config", RENDERER_CONFIGS_TO_TEST_AMBI)
@pytest.mark.parametrize("in_fmt", INPUT_FORMATS_AMBI_SPLIT_REND)
def test_ambisonics_external_split(test_info, in_fmt, render_config, trajectory):
- check_xfail(test_info, in_fmt, render_config)
-
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
@@ -119,8 +84,6 @@ def test_ambisonics_external_split(test_info, in_fmt, render_config, trajectory)
def test_multichannel_full_chain_split(
test_info, in_fmt, bitrate, render_config, trajectory
):
- check_xfail(test_info, in_fmt, render_config, bitrate)
-
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
@@ -138,8 +101,6 @@ def test_multichannel_full_chain_split(
@pytest.mark.parametrize("render_config", RENDERER_CONFIGS_TO_TEST_MC)
@pytest.mark.parametrize("in_fmt", INPUT_FORMATS_MC_SPLIT_REND)
def test_multichannel_external_split(test_info, in_fmt, render_config, trajectory):
- check_xfail(test_info, in_fmt, render_config)
-
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
@@ -160,8 +121,6 @@ def test_multichannel_external_split(test_info, in_fmt, render_config, trajector
@pytest.mark.parametrize("bitrate", IVAS_BITRATES_ISM)
@pytest.mark.parametrize("in_fmt", INPUT_FORMATS_ISM_SPLIT_REND)
def test_ism_full_chain_split(test_info, in_fmt, bitrate, render_config, trajectory):
- check_xfail(test_info, in_fmt, render_config, bitrate)
-
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
@@ -179,8 +138,6 @@ def test_ism_full_chain_split(test_info, in_fmt, bitrate, render_config, traject
@pytest.mark.parametrize("render_config", RENDERER_CONFIGS_TO_TEST_ISM)
@pytest.mark.parametrize("in_fmt", INPUT_FORMATS_ISM_SPLIT_REND)
def test_ism_external_split(test_info, in_fmt, render_config, trajectory):
- check_xfail(test_info, in_fmt, render_config)
-
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
@@ -201,8 +158,6 @@ def test_ism_external_split(test_info, in_fmt, render_config, trajectory):
@pytest.mark.parametrize("bitrate", IVAS_BITRATES_MASA)
@pytest.mark.parametrize("in_fmt", INPUT_FORMATS_MASA_SPLIT_REND)
def test_masa_full_chain_split(test_info, in_fmt, bitrate, render_config, trajectory):
- check_xfail(test_info, in_fmt, render_config, bitrate)
-
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
@@ -220,8 +175,6 @@ def test_masa_full_chain_split(test_info, in_fmt, bitrate, render_config, trajec
@pytest.mark.parametrize("render_config", RENDERER_CONFIGS_TO_TEST_MASA)
@pytest.mark.parametrize("in_fmt", INPUT_FORMATS_MASA_SPLIT_REND)
def test_masa_external_split(test_info, in_fmt, render_config, trajectory):
- check_xfail(test_info, in_fmt, render_config)
-
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
@@ -242,8 +195,6 @@ def test_masa_external_split(test_info, in_fmt, render_config, trajectory):
@pytest.mark.parametrize("bitrate", IVAS_BITRATES_OMASA)
@pytest.mark.parametrize("in_fmt", INPUT_FORMATS_OMASA_SPLIT_REND)
def test_omasa_full_chain_split(test_info, in_fmt, bitrate, render_config, trajectory):
- check_xfail(test_info, in_fmt, render_config, bitrate)
-
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
@@ -265,8 +216,6 @@ def test_omasa_full_chain_split(test_info, in_fmt, bitrate, render_config, traje
@pytest.mark.parametrize("bitrate", IVAS_BITRATES_OSBA)
@pytest.mark.parametrize("in_fmt", INPUT_FORMATS_OSBA_SPLIT_REND)
def test_osba_full_chain_split(test_info, in_fmt, bitrate, render_config, trajectory):
- check_xfail(test_info, in_fmt, render_config, bitrate)
-
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
@@ -288,8 +237,6 @@ def test_osba_full_chain_split(test_info, in_fmt, bitrate, render_config, trajec
@pytest.mark.parametrize("render_config", RENDERER_CONFIGS_TO_TEST_PLC)
@pytest.mark.parametrize("in_fmt", INPUT_FORMATS_AMBI_SPLIT_REND[-1:])
def test_post_rend_plc(test_info, in_fmt, render_config, trajectory, error_pattern):
- check_xfail(test_info, in_fmt, render_config)
-
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
@@ -317,8 +264,6 @@ full_chain_split_pcm_params = [
@pytest.mark.parametrize("in_fmt,bitrate,render_config", full_chain_split_pcm_params)
def test_full_chain_split_pcm(test_info, in_fmt, bitrate, render_config):
- check_xfail(test_info, in_fmt, render_config, bitrate)
-
trajectory = SPLIT_REND_HR_TRAJECTORIES_TO_TEST[0]
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
@@ -343,8 +288,6 @@ external_split_pcm_params = [
@pytest.mark.parametrize("in_fmt,render_config", external_split_pcm_params)
def test_external_split_pcm(test_info, in_fmt, render_config):
- check_xfail(test_info, in_fmt, render_config)
-
trajectory = SPLIT_REND_HR_TRAJECTORIES_TO_TEST[0]
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
@@ -357,3 +300,43 @@ def test_external_split_pcm(test_info, in_fmt, render_config):
post_trajectory=post_trajectory,
renderer_fmt="BINAURAL_SPLIT_PCM",
)
+
+@pytest.mark.parametrize("trajectory", SPLIT_REND_HR_TRAJECTORIES_TO_TEST)
+@pytest.mark.parametrize("render_config", RENDERER_CONFIGS_FRAMING)
+@pytest.mark.parametrize("in_fmt", ["5_1"])
+@pytest.mark.parametrize("pre_rend_fr", SPLIT_RENDERER_PRE_FRAMINGS)
+@pytest.mark.parametrize("post_rend_fr", SPLIT_RENDERER_POST_FRAMINGS)
+def test_framing_combinations_external_split(test_info, in_fmt, render_config, trajectory, post_rend_fr, pre_rend_fr):
+ post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
+ pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
+
+ run_external_split_rendering(
+ test_info,
+ in_fmt=in_fmt,
+ render_config=RENDER_FRAMING_CFG_DIR.joinpath(f"{render_config}.txt"),
+ pre_trajectory=pre_trajectory,
+ post_trajectory=post_trajectory,
+ post_rend_fr=post_rend_fr,
+ pre_rend_fr=pre_rend_fr,
+ )
+@pytest.mark.parametrize("trajectory", SPLIT_REND_HR_TRAJECTORIES_TO_TEST)
+@pytest.mark.parametrize("render_config", RENDERER_CONFIGS_FRAMING)
+@pytest.mark.parametrize("in_fmt", ["5_1"])
+@pytest.mark.parametrize("pre_rend_fr", SPLIT_RENDERER_PRE_FRAMINGS)
+@pytest.mark.parametrize("post_rend_fr", SPLIT_RENDERER_POST_FRAMINGS)
+def test_framing_combinations_full_chain_split(
+ test_info, in_fmt, render_config, trajectory, post_rend_fr, pre_rend_fr
+):
+ post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
+ pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
+
+ run_full_chain_split_rendering(
+ test_info,
+ in_fmt=in_fmt,
+ render_config=RENDER_FRAMING_CFG_DIR.joinpath(f"{render_config}.txt"),
+ pre_trajectory=pre_trajectory,
+ bitrate="256000",
+ post_trajectory=post_trajectory,
+ post_rend_fr=post_rend_fr,
+ pre_rend_fr=pre_rend_fr,
+ )
diff --git a/tests/split_rendering/utils.py b/tests/split_rendering/utils.py
index 9c7f290c4d346c29f12f86a7920263f8fbac92fc..270746b0d5f55c47c4f8c5dd178f17b6c583f34d 100644
--- a/tests/split_rendering/utils.py
+++ b/tests/split_rendering/utils.py
@@ -31,6 +31,7 @@
"""
import sys
+import re
from pathlib import Path
from tempfile import TemporaryDirectory
from typing import Tuple
@@ -45,6 +46,90 @@ sys.path.append(SCRIPTS_DIR)
from pyaudio3dtools.audiofile import readfile, writefile
+def lc3plus_used(test_info, in_fmt, render_config):
+ return (
+ # LC3plus used explicitly
+ "lc3plus" in render_config
+ # or default codec resolving to LC3plus in decoder
+ or (
+ "default" in render_config
+ and "full_chain" in test_info.node.name
+ and in_fmt in [*INPUT_FORMATS_ISM_SPLIT_REND, *INPUT_FORMATS_MC_SPLIT_REND]
+ )
+ # or default codec resolving to LC3plus in IVAS_rend
+ or ("default" in render_config and "external_split" in test_info.node.name)
+ )
+
+FRAME_SIZE_RE = re.compile(r"(\d+)ms")
+
+def transport_codec_frame_size_ms(test_info, in_fmt, render_config, pre_rend_fr):
+ explicit_frame_size_ms = FRAME_SIZE_RE.search(render_config)
+
+ # If explicit frame size set in config file, return that
+ if explicit_frame_size_ms:
+ return int(explicit_frame_size_ms[1])
+
+ # Otherwise infer default ISAR frame size.
+ if lc3plus_used(test_info, in_fmt, render_config):
+ # LC3plus always uses 5 ms
+ return 5
+
+ # LCLD adjusts to prerenderer frame size
+ return int(pre_rend_fr)
+
+
+def check_xfail(
+ test_info, in_fmt, render_config, pre_rend_fr, post_rend_fr, ivas_bitrate=None
+):
+ pre_rend_fr = int(pre_rend_fr)
+ post_rend_fr = int(post_rend_fr)
+
+ lc3plus_in_use = lc3plus_used(test_info, in_fmt, render_config)
+
+ if (
+ "256k" in render_config or "320k" in render_config
+ ) and "0dof" not in render_config:
+ pytest.xfail("320kbps and lower are only supported with 0DOF")
+
+ if (
+ ivas_bitrate
+ and (in_fmt in INPUT_FORMATS_ISM_SPLIT_REND)
+ and (int(ivas_bitrate) > int(IVAS_MAX_ISM_BITRATE[in_fmt[-1]]))
+ ):
+ pytest.skip(
+ f"Unsupported configuration with {in_fmt} at IVAS bitrate {ivas_bitrate}bps"
+ )
+
+ if not "0dof" in render_config and pre_rend_fr != 20:
+ pytest.xfail("pose correction (== !0dof) is expected to use 20ms")
+
+ if (
+ "1dof" in render_config or "2dof" in render_config or "3dof" in render_config
+ ) and pre_rend_fr != 20:
+ pytest.xfail(
+ "unsupported framing: for 1+dof pre_rend_fr framing shall always be 20ms"
+ )
+
+ if pre_rend_fr < post_rend_fr:
+ pytest.xfail(
+ # This would require decoding multiple ISAR frames for one post renderer output frame, which is not supported.
+ "unsupported framing: Post-renderer frame size must be equal or smaller than ISAR codec frame size"
+ )
+
+ transport_codec_frame_size = transport_codec_frame_size_ms(
+ test_info, in_fmt, render_config, pre_rend_fr
+ )
+ if pre_rend_fr < transport_codec_frame_size:
+ pytest.xfail(
+ "unsupported framing: ISAR codec frame must fit in one output frame"
+ )
+
+ if not lc3plus_in_use and transport_codec_frame_size != pre_rend_fr:
+ pytest.xfail(
+ "unsupported framing: LCLD codec doesn't support aggregation. Pre-renderer (ISAR) frame size must match LCLD frame size."
+ )
+
+
def truncate_signal(
in_file: Path,
out_file: Path,
@@ -74,11 +159,16 @@ def run_full_chain_split_rendering(
post_trajectory: Path,
renderer_fmt: str = "BINAURAL_SPLIT_CODED",
binary_suffix: str = "",
+ post_rend_fr: str = "20",
+ pre_rend_fr: str = "20",
) -> str:
"""
Runs the full split rendering chain consisting of
the IVAS encoder, decoder and split renderer
"""
+
+ check_xfail(test_info, in_fmt, render_config.name, pre_rend_fr, post_rend_fr, bitrate)
+
with TemporaryDirectory() as tmp_dir:
tmp_dir = Path(tmp_dir)
cut_in_file = tmp_dir.joinpath("cut_input.wav")
@@ -86,7 +176,7 @@ def run_full_chain_split_rendering(
split_bitstream = tmp_dir.joinpath("split.bit")
if renderer_fmt == "BINAURAL_SPLIT_PCM":
split_md_file = tmp_dir.joinpath("split_md.bin")
- out_file_stem = f"{in_fmt}_{bitrate}bps_{renderer_fmt}_{pre_trajectory.stem}_split_full_{post_trajectory.stem}_config_{render_config.stem}.wav"
+ out_file_stem = f"{in_fmt}_{bitrate}bps_{renderer_fmt}_{pre_trajectory.stem}_split_full_{post_trajectory.stem}_config_{render_config.stem}_prerfr_{pre_rend_fr}_postrfr_{post_rend_fr}_.wav"
if test_info.config.option.create_ref:
output_path_base = OUTPUT_PATH_REF
@@ -136,9 +226,10 @@ def run_full_chain_split_rendering(
cmd[0] += binary_suffix
cmd[2] = str(pre_trajectory)
cmd[4] = str(render_config)
- cmd[5] = renderer_fmt
- cmd[7] = str(ivas_bitstream)
- cmd[8] = str(split_bitstream)
+ cmd[6] = str(pre_rend_fr)
+ cmd[7] = renderer_fmt
+ cmd[9] = str(ivas_bitstream)
+ cmd[10] = str(split_bitstream)
if renderer_fmt == "BINAURAL_SPLIT_PCM":
cmd[5:5] = ["-om", str(split_md_file)]
@@ -155,6 +246,7 @@ def run_full_chain_split_rendering(
cmd[6] = renderer_fmt
cmd[8] = str(out_file)
cmd[10] = str(post_trajectory)
+ cmd[12] = post_rend_fr
if renderer_fmt == "BINAURAL_SPLIT_PCM":
cmd[7:7] = ["-im", str(split_md_file)]
@@ -189,19 +281,23 @@ def run_external_split_rendering(
renderer_fmt: str = "BINAURAL_SPLIT_CODED",
binary_suffix: str = "",
is_comparetest: bool = False,
+ post_rend_fr: str = "20",
+ pre_rend_fr: str = "20",
) -> Tuple[np.ndarray, int]:
"""
Runs the exeternal split rendering chain consisting of
the IVAS renderer in split-pre and split-post rendering mode
"""
+ check_xfail(test_info, in_fmt, render_config.name, pre_rend_fr, post_rend_fr)
+
with TemporaryDirectory() as tmp_dir:
tmp_dir = Path(tmp_dir)
cut_in_file = tmp_dir.joinpath("cut_input.wav")
split_bitstream = tmp_dir.joinpath("split.bit")
if renderer_fmt == "BINAURAL_SPLIT_PCM":
split_md_file = tmp_dir.joinpath("split_md.bin")
- out_file_stem = f"{in_fmt}_{renderer_fmt}_{pre_trajectory.stem}_split_ext_{post_trajectory.stem}_config_{render_config.stem}.wav"
+ out_file_stem = f"{in_fmt}_{renderer_fmt}_{pre_trajectory.stem}_split_ext_{post_trajectory.stem}_config_{render_config.stem}_postrfr_{pre_rend_fr}_prerfr_{post_rend_fr}.wav"
if test_info.config.option.create_ref:
output_path_base = OUTPUT_PATH_REF
@@ -239,6 +335,7 @@ def run_external_split_rendering(
cmd[10] = str(split_bitstream)
cmd[12] = renderer_fmt
cmd[14] = str(pre_trajectory)
+ cmd[16] = pre_rend_fr
if renderer_fmt == "BINAURAL_SPLIT_PCM":
cmd[13:13] = ["-om", str(split_md_file)]
@@ -258,6 +355,7 @@ def run_external_split_rendering(
cmd[6] = renderer_fmt
cmd[8] = str(out_file)
cmd[10] = str(post_trajectory)
+ cmd[12] = post_rend_fr
if renderer_fmt == "BINAURAL_SPLIT_PCM":
cmd[7:7] = ["-im", str(split_md_file)]