Skip to content
......@@ -62,7 +62,7 @@ fi
c_header_new=\
'/*====================================================================================
3GPP TS26.258 Aug 24, 2023. IVAS Codec Version IVAS-FL-1.0
3GPP TS26.258 May 14, 2024. IVAS Codec Version IVAS-FL-2.0
====================================================================================*/'
......@@ -139,7 +139,7 @@ rm -f $tmpfile
# Patch Printout
#
sed -i.bak -e "s/IVAS\ Codec\ Baseline/IVAS\ Codec\ Version\ IVAS-FL-1\.0/g" $WORKDIR/lib_com/disclaimer.c
sed -i.bak -e "s/IVAS\ Codec\ Baseline/IVAS\ Codec\ Version\ IVAS-FL-2\.0/g" $WORKDIR/lib_com/disclaimer.c
#
......
......@@ -35,7 +35,6 @@ DATE=`eval date +%Y_%m_%d`
OUTDIR=c-code
TMPCLEANDIR=clean-c-code
ROOT=$(dirname $0)/..
STRIP_SPLITREND=0
PREPARE_ZIP=1
# check, whether coan exists
......@@ -56,9 +55,6 @@ while getopts "$ALL_OPTS" OPTION; do
case "${OPTION}" in
-)
case "${OPTARG}" in
strip_sr)
STRIP_SPLITREND=1
;;
no_zip)
PREPARE_ZIP=0
;;
......@@ -69,7 +65,7 @@ while getopts "$ALL_OPTS" OPTION; do
;;
esac;;
h)
echo "usage: $0 [--strip_sr] [--no_zip]" >&2
echo "usage: $0 [--no_zip]" >&2
exit -1
;;
*)
......@@ -98,6 +94,7 @@ cp -R ${ROOT}/lib_dec $OUTDIR
cp -R ${ROOT}/lib_enc $OUTDIR
cp -R ${ROOT}/lib_util $OUTDIR
cp -R ${ROOT}/lib_rend $OUTDIR
cp -R ${ROOT}/lib_isar $OUTDIR
cp -R ${ROOT}/lib_lc3plus $OUTDIR
cp -R ${ROOT}/apps $OUTDIR
mkdir $OUTDIR/lib_debug
......@@ -127,63 +124,10 @@ recode lat1..ibmpc ${OUTDIR}/readme_split_rendering.txt # unix2dos ...
cp ${ROOT}/LICENSE.md ${OUTDIR}
recode lat1..ibmpc ${OUTDIR}/LICENSE.md # unix2dos ...
# include .clang_format, since this is a VS dependency
cp ${ROOT}/.clang-format ${OUTDIR}
# enable split rendering againg by default
# in case we strip it later, it will be explicitly disabled again belo
# in case we strip it later, it will be explicitly disabled again below
sed -i.bak -e "s/\/\*\ *\(#define\ *SPLIT_REND_WITH_HEAD_ROT\ *\)\*\//\1/g" ${OUTDIR}/lib_com/options.h
##########################
# #
# Strip Split Rendering #
# #
##########################
if [ $STRIP_SPLITREND -ne 0 ]; then
echo "Stripping Split Rendering"
${ROOT}/scripts/strip_split_rendering.sh ${OUTDIR}
# strip macros
declare -a sr_macros=(
"SPLIT_REND_WITH_HEAD_ROT"
)
if coan_exists; then
for macro in ${sr_macros[@]}; do
coan source --replace --no-transients -K -U${macro} $OUTDIR/lib_{com,dec,enc,util,rend}/*.[hc]
coan source --replace --no-transients -K -U${macro} $OUTDIR/apps/*.[hc]
sed -i.bak "/#define\ *$macro/d" $OUTDIR/lib_com/options.h
done
else
echo "Coan required in path; Aborting. Available at https://coan2.sourceforge.net/"
exit -1
fi
# patch Makefile
patch ${OUTDIR}/Makefile < ${ROOT}/scripts/makefile_noSR.patch
# delete readme_split_rendering
rm ${OUTDIR}/readme_split_rendering.txt
# clean-up *.bak-files
find $OUTDIR -name "*.bak" -exec rm \{\} \;
else
# patch Makefile so that split rendering sources are built by default
patch ${OUTDIR}/Makefile < ${ROOT}/scripts/makefile_SR.patch
fi
##########################
# #
# Stripping #
......@@ -206,7 +150,7 @@ if coan_exists; then
${ROOT}/scripts/parse_options_h.sh -c $tmpfile >> $COAN_LIST
# apply coan
coan source --replace --no-transients -K --file $COAN_LIST $OUTDIR/lib_{com,dec,enc,util,rend}/*.[hc]
coan source --replace --no-transients -K --file $COAN_LIST $OUTDIR/lib_{com,dec,enc,util,rend,isar}/*.[hc]
coan source --replace --no-transients -K --file $COAN_LIST $OUTDIR/apps/*.[hc]
# remove rejected switches from options.h
......@@ -292,6 +236,7 @@ if coan_exists; then
echo "-UDEBUG_AGC_ENCODER_CMD_OPTION" >> $COAN_LIST
echo "-UDEBUG_JBM_CMD_OPTION" >> $COAN_LIST
echo "-UVARIABLE_SPEED_DECODING" >> $COAN_LIST
echo "-UDISABLE_LIMITER" >> $COAN_LIST
echo "-UDBG_WAV_WRITER" >> $COAN_LIST
echo "-USPLIT_REND_WITH_HEAD_ROT_DEBUG" >> $COAN_LIST
echo "-USPLIT_POSE_CORRECTION_DEBUG" >> $COAN_LIST
......@@ -306,7 +251,7 @@ if coan_exists; then
rm -f $tmpfile
# apply coan
coan source --replace --no-transients -K --file $COAN_LIST $OUTDIR/lib_{com,dec,enc,util,rend}/*.[hc]
coan source --replace --no-transients -K --file $COAN_LIST $OUTDIR/lib_{com,dec,enc,util,rend,isar}/*.[hc]
coan source --replace --no-transients -K --file $COAN_LIST $OUTDIR/apps/*.[hc]
# remove rejected switches from options.h
......
......@@ -39,13 +39,7 @@ function usage {
exit
}
if [ -z "$1" ] || [ "$1" == "sr_off" ]; then
INCLUDE_SPLIT=0
elif [ "$1" == "sr_on" ]; then
INCLUDE_SPLIT=1
else
usage
fi
system=`uname -s`
......@@ -93,6 +87,35 @@ fi
rm -f $ifdef_list
touch $ifdef_list
# Add LC3plus feature defines to options.h so that they are stripped correctly
if [ $INCLUDE_SPLIT -eq 1 ]; then
# Generate list of active defines in LC3plus defines.h
lc3plus_defines=$(
gcc -E -dM $targetdir/lib_lc3plus/defines.h -I $targetdir/lib_com -I $targetdir/lib_debug |
sed '/^#define [[:alnum:]][[:alnum:]_]\+[[:space:]]*$/! d' |
sed '/#define DEFINES_H/ d'
)
# Filter defines that come from outside of the header lib_lc3plus/defines.h
lc3plus_defines_filtered=""
while IFS=' \n' read -r line;
do
line=`echo $line | tr -d '\n'`
if grep -wqF "$line" "$targetdir/lib_lc3plus/defines.h"; then
lc3plus_defines_filtered+=$line$'\n'
fi
done <<< $lc3plus_defines
# Append LC3plus defines to options.h
echo "
/* LC3plus switches */
#ifndef OPTIONS_H_LC3_DEFINES
#define OPTIONS_H_LC3_DEFINES
$lc3plus_defines_filtered
#endif /* OPTIONS_H_LC3_DEFINES */
" >>$targetdir/lib_com/options.h
fi
# get switches from options.h and append it to $ifdef_list
parse_options_opt=""
if coan_exists; then
......@@ -113,8 +136,10 @@ if coan_exists; then
sed -i "/-DWMOPS/d" $ifdef_list
sed -i "/-UMEM_COUNT_DETAILS/d" $ifdef_list
coan source --replace --no-transients -E -K --file $ifdef_list $targetdir/lib_{com,dec,enc,rend,util,debug}/!(wmc_auto*).[hc]
coan source --replace --no-transients -E -K --file $ifdef_list $targetdir/lib_{com,dec,enc,isar,rend,util,debug}/!(wmc_auto*).[hc]
coan source --replace --no-transients -E -K --file $ifdef_list $targetdir/apps/*.[hc]
coan source --replace --no-transients -E -K --file $ifdef_list $targetdir/lib_lc3plus/!(wmc_auto*).[hc]
coan source --replace --no-transients -E -K --file $ifdef_list $targetdir/lib_lc3plus/fft/!(wmc_auto*).[hc]
else
./strip_defines_cppp.sh $targetdir $ifdef_list
fi
......@@ -128,6 +153,7 @@ find $targetdir -name "*.[ch]" -exec sed -i.bak -e "s/\(0x[0-9a-fA-F]*\)UL/\(\(u
"tools/$system/wmc_tool" -m "$targetdir/apps/decoder.c" "$targetdir/lib_dec/*.c" "$targetdir/lib_rend/*.c" >> /dev/null
if [ $INCLUDE_SPLIT -eq 1 ]; then
"tools/$system/wmc_tool" -m "$targetdir/apps/renderer.c" "$targetdir/lib_rend/*.c" "$targetdir/lib_lc3plus/*.c" "$targetdir/lib_lc3plus/fft/*.c" >> /dev/null
"tools/$system/wmc_tool" -m "$targetdir/apps/isar_post_rend.c" "$targetdir/lib_isar/*.c" "$targetdir/lib_lc3plus/*.c" "$targetdir/lib_lc3plus/fft/*.c" >> /dev/null
fi
# automatically enable #define WMOPS in options.h
......
......@@ -334,8 +334,8 @@ def compare(
for i in range(nchannels):
tmpfile_ref = Path(tmpdir).joinpath(f"ref_ch{i+1}.wav")
tmpfile_test = Path(tmpdir).joinpath(f"test_ch{i+1}.wav")
r48 = resample(ref[:, i], fs, 48000)
t48 = resample(test[:, i], fs, 48000)
r48 = np.clip( resample(ref[:, i].astype(float), fs, 48000), -32768, 32767 ).astype(np.int16) # Convert to float for resample, then to int16 for wavfile.write
t48 = np.clip( resample(test[:, i].astype(float), fs, 48000), -32768, 32767 ).astype(np.int16)
wavfile.write(str(tmpfile_ref), 48000, r48)
wavfile.write(str(tmpfile_test), 48000, t48)
out = subprocess.check_output([mld, tmpfile_ref, tmpfile_test])
......
......@@ -731,6 +731,17 @@ def get_angle_code(angle):
assert 0 <= angle <= 360
return usquant(angle, 0, 20, 19)
def get_refdist_code(dist):
assert 0 <= dist
return usquant(dist, 0.1, 0.1, 64)
def get_maxdist_code(dist):
assert 0 <= dist
return usquant(dist, 1, 1, 64)
def get_rolloff_code(rollof):
assert 0 <= rollof
return usquant(rollof, 0, 0.1, 41)
def get_outer_attenuation_code(att):
assert 0 <= att <= 1
......
......@@ -84,6 +84,7 @@ def parse_reverb_text_configuration_and_generate_binary_payload(file):
"acousticEnvironment",
"directivitySetting",
"directivityPattern",
"distanceAttenuation",
]
}
for section_name in config.sections():
......@@ -99,6 +100,7 @@ def parse_reverb_text_configuration_and_generate_binary_payload(file):
assert section_name in [
"roomAcoustics",
"directivitySetting",
"distanceAttenuation",
], f"unknown section name: {section_name}"
sections[section_name] = config[section_name]
......@@ -229,10 +231,19 @@ def parse_reverb_text_configuration_and_generate_binary_payload(file):
+ get_angle_code(dir_values[1]) # Directivity outer angle
+ get_outer_attenuation_code(dir_values[2])
) # Directivity outer attenuation
# parse distance attenuation
hasDistanceAttenuation = len(sections["distanceAttenuation"]) > 0
data += get_bool_code(hasDistanceAttenuation)
if hasDistanceAttenuation:
data += bitarray(
get_maxdist_code(eval_option(sections["distanceAttenuation"]["maxDist"])) # Distance attenuation Max Distance
+ get_refdist_code(eval_option(sections["distanceAttenuation"]["refDist"])) # Distance attenuation Ref Distance
+ get_rolloff_code(eval_option(sections["distanceAttenuation"]["rolloffFactor"])) # Distance attenuation Rolloff Factor
)
# generate binary file
data.tofile(open(file.split(".")[0] + ".dat", "wb"))
if __name__ == "__main__":
import argparse
......
......@@ -30,44 +30,53 @@ the United Nations Convention on Contracts on the International Sales of Goods.
*******************************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "options.h"
#include "ivas_lc3plus_enc.h"
#include "ivas_lc3plus_common.h"
#include "ivas_lc3plus_dec.h"
#include "isar_lc3plus_enc.h"
#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;
IVAS_LC3PLUS_ENC_HANDLE encHandle;
err = IVAS_LC3PLUS_ENC_Open( config, bps, &encHandle );
ISAR_LC3PLUS_ENC_HANDLE encHandle;
err = ISAR_LC3PLUS_ENC_Open( config, bps, &encHandle );
if ( IVAS_ERR_OK != err )
{
return err;
}
err = IVAS_LC3PLUS_ENC_GetDelay( encHandle, &encDelay );
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 ) );
......@@ -77,37 +86,66 @@ static int encodeAndDecodeOneStereoFrame( LC3PLUS_CONFIG config )
pcm_in[1] = pcm_in_ch2;
int32_t bitstreamSizePerIvasFrame = 0;
err = IVAS_LC3PLUS_ENC_GetOutputBitstreamSize( encHandle, &bitstreamSizePerIvasFrame );
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 );
err = IVAS_LC3PLUS_ENC_Encode( encHandle, pcm_in, bitstream_out );
#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;
IVAS_LC3PLUS_ENC_Close( &encHandle );
}
ISAR_LC3PLUS_ENC_Close( &encHandle );
/* decode one frame */
IVAS_LC3PLUS_DEC_HANDLE decHandle;
err = IVAS_LC3PLUS_DEC_Open( config,
ISAR_LC3PLUS_DEC_HANDLE decHandle;
err = ISAR_LC3PLUS_DEC_Open( config,
#ifdef LC3PLUS_DEC_ALLOW_DISABLE_CACHING
1 /*caching enabled*/,
#endif
&decHandle );
if ( IVAS_ERR_OK != err )
{
free( bitstream_out );
return err;
}
err = IVAS_LC3PLUS_DEC_GetDelay( decHandle, &decDelay );
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" );
}
......@@ -121,25 +159,31 @@ static int encodeAndDecodeOneStereoFrame( LC3PLUS_CONFIG config )
pcm_out[0] = pcm_out_ch1;
pcm_out[1] = pcm_out_ch2;
err = IVAS_LC3PLUS_DEC_Conceal( decHandle, pcm_out );
err = ISAR_LC3PLUS_DEC_Conceal( decHandle, pcm_out );
if ( IVAS_ERR_OK != err )
{
ISAR_LC3PLUS_DEC_Close( &decHandle );
free( bitstream_out );
return err;
}
err = IVAS_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstreamSizePerIvasFrame, pcm_out );
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 = IVAS_LC3PLUS_DEC_Conceal( decHandle, pcm_out );
err = ISAR_LC3PLUS_DEC_Conceal( decHandle, pcm_out );
if ( IVAS_ERR_OK != err )
{
ISAR_LC3PLUS_DEC_Close( &decHandle );
free( bitstream_out );
return err;
}
IVAS_LC3PLUS_DEC_Close( &decHandle );
ISAR_LC3PLUS_DEC_Close( &decHandle );
free( bitstream_out );
return 0;
......@@ -149,53 +193,81 @@ 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;
IVAS_LC3PLUS_ENC_HANDLE encHandle;
err = IVAS_LC3PLUS_ENC_Open( config, bps, &encHandle );
ISAR_LC3PLUS_ENC_HANDLE encHandle;
err = ISAR_LC3PLUS_ENC_Open( config, bps, &encHandle );
if ( IVAS_ERR_OK != err )
{
return err;
}
IVAS_LC3PLUS_ENC_Close( &encHandle );
ISAR_LC3PLUS_ENC_Close( &encHandle );
return 0;
}
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;
IVAS_LC3PLUS_ENC_HANDLE encHandle;
err = IVAS_LC3PLUS_ENC_Open( config, invalid_high_bps, &encHandle );
#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;
}
err = IVAS_LC3PLUS_ENC_Open( config, invalid_low_bps, &encHandle );
#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;
IVAS_LC3PLUS_ENC_HANDLE encHandle;
err = IVAS_LC3PLUS_ENC_Open( config, bps, &encHandle );
ISAR_LC3PLUS_ENC_HANDLE encHandle;
err = ISAR_LC3PLUS_ENC_Open( config, bps, &encHandle );
/* setting an invalid fame duration should trigger an error - which is what we expect */
if ( IVAS_ERR_OK == err )
{
......@@ -207,12 +279,16 @@ 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;
IVAS_LC3PLUS_ENC_HANDLE encHandle;
err = IVAS_LC3PLUS_ENC_Open( config, bps, &encHandle );
ISAR_LC3PLUS_ENC_HANDLE encHandle;
err = ISAR_LC3PLUS_ENC_Open( config, bps, &encHandle );
/* setting an invalid sample rate should trigger an error - which is what we expect */
if ( IVAS_ERR_OK == err )
{
......@@ -223,7 +299,7 @@ static int tryOpenEncoderWithInvalidSampleRate( void )
static int tryCallEncoderApiWithInvalidParams( void )
{
IVAS_LC3PLUS_ENC_HANDLE invalidEncHandle = NULL;
ISAR_LC3PLUS_ENC_HANDLE invalidEncHandle = NULL;
int32_t *invalidBsSize = NULL;
int32_t bsSize;
int32_t *invalidDelayInSamples = NULL;
......@@ -238,20 +314,28 @@ static int tryCallEncoderApiWithInvalidParams( void )
pcm_in[0] = pcm_in_ch1;
uint8_t bitstream_out[1200];
if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != IVAS_LC3PLUS_ENC_GetDelay( invalidEncHandle, invalidDelayInSamples ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != IVAS_LC3PLUS_ENC_GetDelay( invalidEncHandle, &delayInSamples ) )
if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_GetDelay( invalidEncHandle, invalidDelayInSamples ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_GetDelay( invalidEncHandle, &delayInSamples ) )
{
return 1;
}
if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != IVAS_LC3PLUS_ENC_GetOutputBitstreamSize( invalidEncHandle, invalidBsSize ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != IVAS_LC3PLUS_ENC_GetOutputBitstreamSize( invalidEncHandle, &bsSize ) )
if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_GetOutputBitstreamSize( invalidEncHandle, invalidBsSize ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_GetOutputBitstreamSize( invalidEncHandle, &bsSize ) )
{
return 1;
}
IVAS_LC3PLUS_ENC_Close( &invalidEncHandle );
if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != IVAS_LC3PLUS_ENC_Encode( invalidEncHandle, invalidPcm_in, invalidBitstream_out ) )
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;
}
if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != IVAS_LC3PLUS_ENC_Encode( invalidEncHandle, pcm_in, invalidBitstream_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != IVAS_LC3PLUS_ENC_Encode( invalidEncHandle, invalidPcm_in, bitstream_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != IVAS_LC3PLUS_ENC_Encode( invalidEncHandle, pcm_in, bitstream_out ) )
#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;
}
......@@ -261,7 +345,7 @@ static int tryCallEncoderApiWithInvalidParams( void )
static int tryCallDecoderApiWithInvalidParams( void )
{
IVAS_LC3PLUS_DEC_HANDLE invalidDecHandle = NULL;
ISAR_LC3PLUS_DEC_HANDLE invalidDecHandle = NULL;
int32_t *invalidDelayInSamples = NULL;
int32_t delayInSamples;
......@@ -277,17 +361,17 @@ static int tryCallDecoderApiWithInvalidParams( void )
pcm_out[0] = pcm_out_ch1;
uint8_t bitstream_in[1200];
if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != IVAS_LC3PLUS_DEC_GetDelay( invalidDecHandle, invalidDelayInSamples ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != IVAS_LC3PLUS_DEC_GetDelay( invalidDecHandle, &delayInSamples ) )
if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_GetDelay( invalidDecHandle, invalidDelayInSamples ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_GetDelay( invalidDecHandle, &delayInSamples ) )
{
return 1;
}
IVAS_LC3PLUS_DEC_Close( &invalidDecHandle );
if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != IVAS_LC3PLUS_DEC_Decode( invalidDecHandle, invalidBitstream_in, invalidBitstream_in_size, invalidPcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != IVAS_LC3PLUS_DEC_Decode( invalidDecHandle, invalidBitstream_in, invalidBitstream_in_size, pcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != IVAS_LC3PLUS_DEC_Decode( invalidDecHandle, invalidBitstream_in, bitstream_in_size, invalidPcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != IVAS_LC3PLUS_DEC_Decode( invalidDecHandle, invalidBitstream_in, bitstream_in_size, pcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != IVAS_LC3PLUS_DEC_Decode( invalidDecHandle, bitstream_in, invalidBitstream_in_size, invalidPcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != IVAS_LC3PLUS_DEC_Decode( invalidDecHandle, bitstream_in, invalidBitstream_in_size, pcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != IVAS_LC3PLUS_DEC_Decode( invalidDecHandle, bitstream_in, bitstream_in_size, pcm_out ) )
ISAR_LC3PLUS_DEC_Close( &invalidDecHandle );
if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_Decode( invalidDecHandle, invalidBitstream_in, invalidBitstream_in_size, invalidPcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_Decode( invalidDecHandle, invalidBitstream_in, invalidBitstream_in_size, pcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_Decode( invalidDecHandle, invalidBitstream_in, bitstream_in_size, invalidPcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_Decode( invalidDecHandle, invalidBitstream_in, bitstream_in_size, pcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_Decode( invalidDecHandle, bitstream_in, invalidBitstream_in_size, invalidPcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_Decode( invalidDecHandle, bitstream_in, invalidBitstream_in_size, pcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_Decode( invalidDecHandle, bitstream_in, bitstream_in_size, pcm_out ) )
{
return 1;
}
if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != IVAS_LC3PLUS_DEC_Conceal( invalidDecHandle, invalidPcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != IVAS_LC3PLUS_DEC_Conceal( invalidDecHandle, pcm_out ) )
if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_Conceal( invalidDecHandle, invalidPcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_Conceal( invalidDecHandle, pcm_out ) )
{
return 1;
}
......@@ -297,10 +381,13 @@ 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 };
IVAS_LC3PLUS_DEC_HANDLE decHandle;
err = IVAS_LC3PLUS_DEC_Open( config,
#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
1 /*caching enabled*/,
#endif
......@@ -310,17 +397,20 @@ static int openCloseDecoderWithCaching( void )
return err;
}
IVAS_LC3PLUS_DEC_Close( &decHandle );
ISAR_LC3PLUS_DEC_Close( &decHandle );
return 0;
}
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 };
IVAS_LC3PLUS_DEC_HANDLE decHandle;
err = IVAS_LC3PLUS_DEC_Open( config,
#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
1 /*caching enabled*/,
#endif
......@@ -330,7 +420,7 @@ static int openCloseDecoderWithoutCaching( void )
return err;
}
IVAS_LC3PLUS_DEC_Close( &decHandle );
ISAR_LC3PLUS_DEC_Close( &decHandle );
return 0;
}
......@@ -338,11 +428,15 @@ 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*/
IVAS_LC3PLUS_DEC_HANDLE decHandle;
err = IVAS_LC3PLUS_DEC_Open( config,
ISAR_LC3PLUS_DEC_HANDLE decHandle;
err = ISAR_LC3PLUS_DEC_Open( config,
#ifdef LC3PLUS_DEC_ALLOW_DISABLE_CACHING
1 /*caching enabled*/,
#endif
......@@ -358,11 +452,15 @@ 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*/
IVAS_LC3PLUS_DEC_HANDLE decHandle;
err = IVAS_LC3PLUS_DEC_Open( config,
ISAR_LC3PLUS_DEC_HANDLE decHandle;
err = ISAR_LC3PLUS_DEC_Open( config,
#ifdef LC3PLUS_DEC_ALLOW_DISABLE_CACHING
1 /*caching enabled*/,
#endif
......@@ -378,15 +476,19 @@ 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;
IVAS_LC3PLUS_ENC_HANDLE encHandle;
err = IVAS_LC3PLUS_ENC_Open( config, bps, &encHandle );
ISAR_LC3PLUS_ENC_HANDLE encHandle;
err = ISAR_LC3PLUS_ENC_Open( config, bps, &encHandle );
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 )];
......@@ -394,17 +496,20 @@ static int encodeOneFrame( void )
pcm[0] = pcm_ch1;
int32_t bitstreamSizePerIvasFrame = 0;
err = IVAS_LC3PLUS_ENC_GetOutputBitstreamSize( encHandle, &bitstreamSizePerIvasFrame );
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 = IVAS_LC3PLUS_ENC_Encode( encHandle, pcm, bitstream_out );
#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;
IVAS_LC3PLUS_ENC_Close( &encHandle );
ISAR_LC3PLUS_ENC_Close( &encHandle );
free( bitstream_out );
return 0;
}
......@@ -413,39 +518,46 @@ 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;
IVAS_LC3PLUS_ENC_HANDLE encHandle;
err = IVAS_LC3PLUS_ENC_Open( config, bps, &encHandle );
ISAR_LC3PLUS_ENC_HANDLE encHandle;
err = ISAR_LC3PLUS_ENC_Open( config, bps, &encHandle );
if ( IVAS_ERR_OK != err )
{
return err;
}
/* 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 ) );
pcm_in[0] = pcm_in_ch1;
int32_t bitstreamSizePerIvasFrame = 0;
err = IVAS_LC3PLUS_ENC_GetOutputBitstreamSize( encHandle, &bitstreamSizePerIvasFrame );
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 = IVAS_LC3PLUS_ENC_Encode( encHandle, pcm_in, bitstream_out );
#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;
IVAS_LC3PLUS_ENC_Close( &encHandle );
ISAR_LC3PLUS_ENC_Close( &encHandle );
/* decode one frame */
IVAS_LC3PLUS_DEC_HANDLE decHandle;
err = IVAS_LC3PLUS_DEC_Open( config,
ISAR_LC3PLUS_DEC_HANDLE decHandle;
err = ISAR_LC3PLUS_DEC_Open( config,
#ifdef LC3PLUS_DEC_ALLOW_DISABLE_CACHING
1 /*caching enabled*/,
#endif
......@@ -461,19 +573,19 @@ static int encodeAndDecodeOneMonoFrame( void )
float pcm_out_ch1[MAX_SAMPLES_PER_CHANNEL * sizeof( float )];
memset( pcm_out_ch1, 0, numSamplesPerChannels * sizeof( float ) );
pcm_out[0] = pcm_out_ch1;
err = IVAS_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstreamSizePerIvasFrame, pcm_out );
err = ISAR_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstreamSizePerIvasFrame, pcm_out );
if ( IVAS_ERR_OK != err )
{
return err;
}
err = IVAS_LC3PLUS_DEC_Conceal( decHandle, pcm_out );
err = ISAR_LC3PLUS_DEC_Conceal( decHandle, pcm_out );
if ( IVAS_ERR_OK != err )
{
return err;
}
IVAS_LC3PLUS_DEC_Close( &decHandle );
ISAR_LC3PLUS_DEC_Close( &decHandle );
free( bitstream_out );
return 0;
......@@ -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 )
......
/******************************************************************************************************
(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 <assert.h>
#include <stdlib.h>
#include <string.h>
#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
/******************************************************************************************************
(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 <stdlib.h>
#include <string.h>
#include "ivas_lc3plus_enc.h"
#include "ivas_lc3plus_common.h"
#include "ivas_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,
IVAS_LC3PLUS_DEC_HANDLE dec,
uint8_t *bitstream_in,
int32_t bitstream_in_size,
float **pcm_out );
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;
IVAS_LC3PLUS_ENC_HANDLE encHandle;
err = IVAS_LC3PLUS_ENC_Open( config, bps, &encHandle );
if ( IVAS_ERR_OK != err )
{
return err;
}
err = IVAS_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 = IVAS_LC3PLUS_ENC_GetOutputBitstreamSize( encHandle, &bitstreamSizePerIvasFrame );
if ( IVAS_ERR_OK != err )
return err;
uint8_t *bitstream_out = malloc( bitstreamSizePerIvasFrame );
memset( bitstream_out, 0, bitstreamSizePerIvasFrame );
err = IVAS_LC3PLUS_ENC_Encode( encHandle, pcm_in, bitstream_out );
if ( IVAS_ERR_OK != err )
return err;
IVAS_LC3PLUS_ENC_Close( &encHandle );
/* decode one frame */
IVAS_LC3PLUS_DEC_HANDLE decHandle;
err = IVAS_LC3PLUS_DEC_Open( config,
#ifdef LC3PLUS_DEC_ALLOW_DISABLE_CACHING
enableCaching,
#endif
&decHandle );
if ( IVAS_ERR_OK != err )
{
return err;
}
err = IVAS_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 = IVAS_LC3PLUS_DEC_Conceal( decHandle, pcm_out );
if ( IVAS_ERR_OK != err )
{
return err;
}
err = IVAS_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 = IVAS_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstreamSizePerIvasFrame, pcm_out );
if ( IVAS_ERR_OK != err )
{
return err;
}
err = IVAS_LC3PLUS_DEC_Conceal( decHandle, pcm_out );
if ( IVAS_ERR_OK != err )
{
return err;
}
IVAS_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,
IVAS_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 = IVAS_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 = IVAS_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 = IVAS_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 );
}
IVAS_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,
IVAS_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 = IVAS_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 = IVAS_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 = IVAS_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 );
}
}
IVAS_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,
IVAS_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 = IVAS_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 = IVAS_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 = IVAS_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 );
}
}
IVAS_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,
IVAS_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 = IVAS_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 = IVAS_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 = IVAS_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 );
}
}
IVAS_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,
IVAS_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 = IVAS_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 = IVAS_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 = IVAS_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 = IVAS_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 = IVAS_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 );
}
}
IVAS_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,
IVAS_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 = IVAS_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 = IVAS_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 = IVAS_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 = IVAS_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 = IVAS_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 );
}
}
IVAS_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,
IVAS_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 = IVAS_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 = IVAS_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 = IVAS_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 = IVAS_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 = IVAS_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 );
}
}
IVAS_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,
IVAS_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 = IVAS_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 = IVAS_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 = IVAS_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 = IVAS_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 = IVAS_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 );
}
}
IVAS_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,
IVAS_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 = IVAS_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 = IVAS_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 = IVAS_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 = IVAS_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 = IVAS_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 );
}
}
IVAS_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,
IVAS_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 = IVAS_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 = IVAS_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 = IVAS_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 = IVAS_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 = IVAS_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 );
}
}
IVAS_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,
IVAS_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 = IVAS_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 = IVAS_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 = IVAS_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 = IVAS_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 = IVAS_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 );
}
}
IVAS_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 */
"""
Generate command lines for split rendering with LC3plus
"""
import itertools
import os
# Paths
ENC_PATH = "./IVAS_cod"
DEC_PATH = "./IVAS_dec"
REND_PATH = "./IVAS_rend"
TEMP_DIR = "tmp"
# Config values to iterate over
ISM_CONFIGS_NUM_OBJECTS = [1, 2, 3, 4]
IVAS_BITRATES = [128000]
PRE_HEAD_ROT_FILES = [
"Workspace_msvc/trajectories/pre-renderer_pose_files/pre_yaw-20static.csv"
]
POST_HEAD_ROT_FILES = [
"Workspace_msvc/trajectories/post-renderer_pose_files/post_0static.csv"
]
RENDER_CONFIG_FILES = [
#######################################################
# Alternative 2 - LC3plus with CLDFB pose correction
"Workspace_msvc/renderer_configs/split_renderer_config_768_1dof.txt",
"Workspace_msvc/renderer_configs/split_renderer_config_512_2dof.txt",
None, # Alternative 2 is the default when no rendering config file is given on command line
#######################################################
# Alternative 3 - LC3plus with multi-stream (TD) pose correction
"Workspace_msvc/renderer_configs/split_renderer_config_768_1dof_tdposecorr.txt",
"Workspace_msvc/renderer_configs/split_renderer_config_1536_2dof_tdposecorr.txt",
]
def audio_for_ism(num_objects):
return f"scripts/testv/stv{num_objects}ISM48s.wav"
def metadata_for_ism(num_objects):
return f"scripts/testv/stvISM{num_objects}.csv"
def basename(file_path):
basename_w_ext = os.path.basename(file_path)
return os.path.splitext(basename_w_ext)[0]
# Full chain: IVAS_cod -> IVAS_dec -> IVAS_rend(post)
def full_chain(
num_objects, ivas_bitrate, pre_head_rot_file, render_config_file, post_head_rot_file
):
bs_name = f"{TEMP_DIR}/ism{num_objects}_b{ivas_bitrate}_full_chain.g192"
cod = [
ENC_PATH,
"-ism",
str(num_objects),
*[metadata_for_ism(i + 1) for i in range(num_objects)],
str(ivas_bitrate),
"48",
audio_for_ism(num_objects),
bs_name,
]
render_config_infix = (
f"##{basename(render_config_file)}" if render_config_file else ""
)
split_bs_name = bs_name.replace(
".g192", f"##{basename(pre_head_rot_file)}{render_config_infix}##split.bs"
)
render_config_args = (
["-render_config", render_config_file] if render_config_file else []
)
dec = [
DEC_PATH,
"-T",
pre_head_rot_file,
*render_config_args,
"SPLIT_BINAURAL",
"48",
bs_name,
split_bs_name,
]
binaural_output_name = split_bs_name.replace(
".bs", f"##{basename(post_head_rot_file)}##binaural.wav"
)
rend = [
REND_PATH,
"-i",
split_bs_name,
"-if",
"BINAURAL_SPLIT_CODED",
"-of",
"BINAURAL",
"-fs",
"48",
"-tf",
post_head_rot_file,
"-o",
binaural_output_name,
]
return [cod, dec, rend]
# Renderer chain: IVAS_rend(pre) -> IVAS_rend(post)
def rend_chain(num_objects, pre_head_rot_file, render_config_file, post_head_rot_file):
render_config_infix = (
f"##{basename(render_config_file)}" if render_config_file else ""
)
split_bs_name = f"{TEMP_DIR}/ism{num_objects}_rend_chain##{basename(pre_head_rot_file)}{render_config_infix}##split.bs"
render_config_args = (
["-render_config", render_config_file] if render_config_file else []
)
pre = [
REND_PATH,
"-i",
audio_for_ism(num_objects),
"-if",
f"ISM{num_objects}",
"-im",
*[metadata_for_ism(i + 1) for i in range(num_objects)],
"-of",
"BINAURAL_SPLIT_CODED",
"-fs",
"48",
*render_config_args,
"-tf",
pre_head_rot_file,
"-o",
split_bs_name,
]
binaural_output_name = split_bs_name.replace(
".bs", f"##{basename(post_head_rot_file)}##binaural.wav"
)
post = [
REND_PATH,
"-i",
split_bs_name,
"-if",
"BINAURAL_SPLIT_CODED",
"-of",
"BINAURAL",
"-fs",
"48",
"-tf",
post_head_rot_file,
"-o",
binaural_output_name,
]
return [pre, post]
def print_command_list(list_of_lists):
for lst in list_of_lists:
print(" ".join(lst))
print("") # newline
def main():
print("\n##########################################")
print("# Full chain: enc -> dec -> rend(post)")
print("##########################################\n")
for args_full_chain in itertools.product(
# Ordering here must match argument order in function call below!
ISM_CONFIGS_NUM_OBJECTS,
IVAS_BITRATES,
PRE_HEAD_ROT_FILES,
RENDER_CONFIG_FILES,
POST_HEAD_ROT_FILES,
):
print_command_list(full_chain(*args_full_chain))
print("\n##########################################")
print("# Renderer chain: rend(pre) -> rend(post)")
print("##########################################\n")
for args_rend_chain in itertools.product(
# Ordering here must match argument order in function call below!
ISM_CONFIGS_NUM_OBJECTS,
PRE_HEAD_ROT_FILES,
RENDER_CONFIG_FILES,
POST_HEAD_ROT_FILES,
):
print_command_list(rend_chain(*args_rend_chain))
if __name__ == "__main__":
main()
......@@ -32,92 +32,3 @@
import glob
import os
# remove other split rendering files
sr_files_rend = [
"lib_rend\\ivas_MSPred.c",
"lib_rend\\ivas_NoiseGen.c",
"lib_rend\\ivas_PerceptualModel.c",
"lib_rend\\ivas_PredDecoder.c",
"lib_rend\\ivas_PredEncoder.c",
"lib_rend\\ivas_RMSEnvGrouping.c",
"lib_rend\\ivas_lc3plus_common.c",
"lib_rend\\ivas_lc3plus_common.h",
"lib_rend\\ivas_lc3plus_dec.c",
"lib_rend\\ivas_lc3plus_dec.h",
"lib_rend\\ivas_lc3plus_enc.c",
"lib_rend\\ivas_lc3plus_enc.h",
"lib_rend\\ivas_lcld_decoder.c",
"lib_rend\\ivas_lcld_encoder.c",
"lib_rend\\ivas_lcld_prot.h",
"lib_rend\\ivas_lcld_rom_tables.c"
"lib_rend\\ivas_lcld_rom_tables.h"
"lib_rend\\ivas_splitRend_lcld_dec.c",
"lib_rend\\ivas_splitRend_lcld_enc.c",
"lib_rend\\ivas_splitRendererPLC.c",
"lib_rend\\ivas_splitRendererPost.c",
"lib_rend\\ivas_splitRendererPre.c",
"lib_rend\\ivas_splitRenderer_utils.c",
]
sr_files_util = [
"lib_util\\split_rend_bfi_file_reader.c",
"lib_util\\split_rend_bfi_file_reader.h",
"lib_util\\split_render_file_read_write.c",
"lib_util\\split_render_file_read_write.h",
]
if __name__ == "__main__":
wsfile = ".\Workspace_msvc\Workspace_msvc.sln"
rendproj = ".\Workspace_msvc\lib_rend.vcxproj"
utilproj = ".\Workspace_msvc\lib_util.vcxproj"
lc3proj = ".\Workspace_msvc\lib_lc3plus.vcxproj"
# Remove lc3plus project
os.remove(lc3proj)
# Patch Workspace_msvc.sln
with open(wsfile, "r") as f:
lines = f.readlines()
with open(wsfile, "w") as f:
skip = 0
for line in lines:
if "lib_lc3plus.vcxproj" in line:
skip = 1
else:
if skip == 0:
f.write(line)
else:
skip = skip - 1
# Patch lib_rend.vcxproj
with open(rendproj, "r") as f:
lines = f.readlines()
with open(rendproj, "w") as f:
skip = 0
for line in lines:
if any([x in line for x in sr_files_rend]):
skip = 1
if "lib_lc3plus.vcxproj" in line:
skip = 4
if skip == 0:
f.write(line)
else:
skip = skip - 1
# Patch lib_util.vcxproj
with open(utilproj, "r") as f:
lines = f.readlines()
with open(utilproj, "w") as f:
for line in lines:
if not any([x in line for x in sr_files_util]):
f.write(line)
# Remove include libraries
for proj in glob.glob(".\Workspace_msvc\*.vcxproj"):
with open(proj, "r") as f:
lines = f.readlines()
with open(proj, "w") as f:
for line in lines:
f.write(line.replace("..\lib_lc3plus;", ""))
......@@ -31,61 +31,3 @@
#
OUTDIR=$1
# remove complete lc3plus folder
rm -R $OUTDIR/lib_lc3plus
# remove other split rendering files
declare -a sr_files_rend=(
"lib_rend/ivas_MSPred.c"
"lib_rend/ivas_NoiseGen.c"
"lib_rend/ivas_PerceptualModel.c"
"lib_rend/ivas_PredDecoder.c"
"lib_rend/ivas_PredEncoder.c"
"lib_rend/ivas_RMSEnvGrouping.c"
"lib_rend/ivas_lc3plus_common.c"
"lib_rend/ivas_lc3plus_common.h"
"lib_rend/ivas_lc3plus_dec.c"
"lib_rend/ivas_lc3plus_dec.h"
"lib_rend/ivas_lc3plus_enc.c"
"lib_rend/ivas_lc3plus_enc.h"
"lib_rend/ivas_lcld_decoder.c"
"lib_rend/ivas_lcld_encoder.c"
"lib_rend/ivas_lcld_prot.h"
"lib_rend/ivas_lcld_rom_tables.c"
"lib_rend/ivas_lcld_rom_tables.h"
"lib_rend/ivas_splitRend_lcld_dec.c"
"lib_rend/ivas_splitRend_lcld_enc.c"
"lib_rend/ivas_splitRendererPLC.c"
"lib_rend/ivas_splitRendererPost.c"
"lib_rend/ivas_splitRendererPre.c"
"lib_rend/ivas_splitRenderer_utils.c"
)
for file in ${sr_files_rend[@]}; do
rm $OUTDIR/$file
file_windows=${file//\//'\\'}
sed -i.bak -e "/${file_windows}/d" ${OUTDIR}/Workspace_msvc/lib_rend.vcxproj
done
declare -a sr_files_util=(
"lib_util/split_rend_bfi_file_reader.c"
"lib_util/split_rend_bfi_file_reader.h"
"lib_util/split_render_file_read_write.c"
"lib_util/split_render_file_read_write.h"
)
for file in ${sr_files_util[@]}; do
rm $OUTDIR/$file
file_windows=${file//\//'\\'}
sed -i.bak -e "/${file_windows}/d" ${OUTDIR}/Workspace_msvc/lib_util.vcxproj
done
# delete project file
rm ${OUTDIR}/Workspace_msvc/lib_lc3plus.vcxproj
# patch project/solution files
sed -i.bak "/lib_lc3plus.vcxproj/,+1d" ${OUTDIR}/Workspace_msvc/Workspace_msvc.sln
find ${OUTDIR}/Workspace_msvc -name "*.vcxproj" -exec sed -i.bak -e "s/..\\lib_lc3plus\;//g" \{\} \;
sed -i.bak "/lib_lc3plus.vcxproj/,+3d" ${OUTDIR}/Workspace_msvc/lib_rend.vcxproj # patch dependency
......@@ -111,7 +111,7 @@ if dataSpec.genRomFile
' *------------------------------------------------------------------------*/'
'/* TD renderer default HRIR model */'
'extern const float defaultHRIR_rom_latency_s;'
['extern const int16_t defaultHRIR_rom_azimDim2[' int2str(size(mod_hrf_org.elevBf{1}, 3)) '];']
['extern const int16_t defaultHRIR_rom_model_configuration[6];']
['extern const int16_t defaultHRIR_rom_azimDim3[' int2str(size(mod_hrf_org.elevBf{1}, 3)) '];']
['extern const int16_t defaultHRIR_rom_azim_start_idx[' int2str(size(mod_hrf_org.elevBf{1}, 3)) '];']
'extern const int16_t defaultHRIR_rom_azimSegSamples[1];'
......@@ -372,20 +372,14 @@ for fs = [48000 32000 16000]
fwrite(fileID, fs_khz, 'short');
% General - model-specific parts
fwrite(fileID, size(mod_hrf.elevBf{1}, 1), 'short'); % N = 4 i.e. coefficients for cubic including zeroth order
fwrite(fileID, size(mod_hrf.WR{1}, 2), 'short'); % K, filter length
% Elevation model structure
elevDim2 = size(mod_hrf.elevBf{1}, 2);
elevDim3 = size(mod_hrf.elevBf{1}, 3);
fwrite(fileID, elevDim2, 'short'); % elevDim2
fwrite(fileID, elevDim3, 'short'); % elevDim3 = P
fwrite(fileID, mod_hrf.elevKSeq{1}, 'float'); % length = elevDim3-2
% Azimuth model structure
azim_start_idx = 0;
c_file_content_dim2 = {
['const int16_t defaultHRIR_rom_azimDim2[' num2str(elevDim3) '] = {']
};
c_file_content_dim3 = {
['const int16_t defaultHRIR_rom_azimDim3[' num2str(elevDim3) '] = {']
};
......@@ -399,8 +393,6 @@ for fs = [48000 32000 16000]
for i = 1:elevDim3
azimDim2 = size(mod_hrf.azimBf{i}, 2);
azimDim3 = size(mod_hrf.azimBf{i}, 3);
fwrite(fileID, azimDim2, 'short'); % azimDim2
content_dim2 = [content_dim2 int2str(azimDim2) ', '];
fwrite(fileID, azimDim3, 'short'); % azimDim3 = Q
content_dim3 = [content_dim3 int2str(azimDim3) ', '];
fwrite(fileID, azim_start_idx, 'short'); % start azim index per elevation
......@@ -410,9 +402,6 @@ for fs = [48000 32000 16000]
end
if fs == fs_orig && dataSpec.genRomFile
fileID_c = fopen(c_file_name,'at');
c_file_content_dim2{size(c_file_content_dim2,2)+1} = content_dim2;
c_file_content_dim2{size(c_file_content_dim2,2)+1} = '};';
c_file_content_dim2{size(c_file_content_dim2,2)+1} = '';
c_file_content_dim3{size(c_file_content_dim3,2)+1} = content_dim3;
c_file_content_dim3{size(c_file_content_dim3,2)+1} = '};';
c_file_content_dim3{size(c_file_content_dim3,2)+1} = '';
......@@ -420,14 +409,64 @@ for fs = [48000 32000 16000]
c_file_content_start_idx{size(c_file_content_start_idx,2)+1} = '};';
c_file_content_start_idx{size(c_file_content_start_idx,2)+1} = '';
c_file_content = string(join(c_file_content_dim2,newline));
c_file_content = ...
['const int16_t defaultHRIR_rom_model_configuration[6] = {' newline ];
fprintf(fileID_c,'%s', c_file_content);
c_file_content = [ num2str(useITD) ', /* UseItdModel */' newline ];
fprintf(fileID_c,'%s', c_file_content);
c_file_content = [ num2str(elevDim3) ', /* elevDim3 */' newline ];
fprintf(fileID_c,'%s', c_file_content);
c_file_content = [ num2str(size(mod_hrf_org.WL{1}, 1)) ', /* AlphaN */' newline ];
fprintf(fileID_c,'%s', c_file_content);
c_file_content = [ num2str(num_unique_splines) ', /* num_unique_azim_splines */' newline ];
fprintf(fileID_c,'%s', c_file_content);
c_file_content = [ num2str(e_num_points) ', /* elevSegSamples */' newline ];
fprintf(fileID_c,'%s', c_file_content);
c_file_content = [ num2str(size(mod_hrf_org.WL{1}, 2)) ', /* K_48k */' newline ];
fprintf(fileID_c,'%s', c_file_content);
c_file_content = ['};' newline ];
fprintf(fileID_c,'%s', c_file_content);
arr_str = join(mat2str((single(len_e))));
arr_str = arr_str(2:end);
arr_str(end) = ';';
arr_str = replace(arr_str, ";",',');
arr_str = replace(arr_str, " ",', ');
c_file_content = ...
['const int16_t defaultHRIR_rom_elevBsLen[' num2str(length(len_e)) '] = {' newline ...
arr_str ...
newline '};' newline ...
];
fprintf(fileID_c,'%s', c_file_content);
arr_str = join(mat2str((single(start_e))));
arr_str = arr_str(2:end);
arr_str(end) = ';';
arr_str = replace(arr_str, ";",',');
arr_str = replace(arr_str, " ",', ');
c_file_content = ...
['const int16_t defaultHRIR_rom_elevBsStart[' num2str(length(start_e)) '] = {' newline ...
arr_str ...
newline '};' newline ...
];
fprintf(fileID_c,'%s', c_file_content);
c_file_content = string(join(c_file_content_dim3,newline));
fprintf(fileID_c,'%s', c_file_content);
c_file_content = string(join(c_file_content_start_idx,newline));
fprintf(fileID_c,'%s', c_file_content);
c_file_content = ['const int16_t defaultHRIR_rom_azimSegSamples[1] = {' newline num2str(mod_hrf_org.azimKmSeq{1,2}(2)) ',' newline '};' newline];
arr_str = join(mat2str((single(a_num_points(1:num_unique_splines)))));
if(num_unique_splines>1)
arr_str = arr_str(2:end);
arr_str(end) = ';';
arr_str = replace(arr_str, ";",',');
arr_str = replace(arr_str, " ",', ');
else
arr_str(end+1) = ',';
end
c_file_content = ['const int16_t defaultHRIR_rom_azimSegSamples[' num2str(num_unique_splines) '] = {' newline arr_str newline '};' newline];
fprintf(fileID_c,'%s', c_file_content);
arr_str = mat2str(azimShapeIdx);
......@@ -662,20 +701,15 @@ for fs = [48000 32000 16000]
% If ITD model is used, parameters are stored in 2nd part of the same file
if useITD
% General
fwrite(fileID, size(mod_itd.elevBf, 1), 'short'); % N = 4 i.e. coefficients for cubic including zeroth order
%fwrite(fileID, size(mod_itd.W, 2), 'short'); % K = 1 always for ITD, so do not need to write.
% Elevation model structure
elevDim2 = size(mod_itd.elevBf, 2);
elevDim3 = size(mod_itd.elevBf, 3);
fwrite(fileID, elevDim2, 'short'); % elevDim2
fwrite(fileID, elevDim3, 'short'); % elevDim3 = P
fwrite(fileID, mod_itd.elevKSeq, 'float'); % length = elevDim3-2
% Azimuth model structure
azimDim2 = size(mod_itd.azimBf{2}, 2);
azimDim3 = size(mod_itd.azimBf{2}, 3);
fwrite(fileID, azimDim2, 'short'); % azimDim2
fwrite(fileID, azimDim3, 'short'); % azimDim3 = Q
fwrite(fileID, mod_itd.azimKSeq{2}, 'float'); % length = azimDim3+1
......@@ -725,6 +759,68 @@ for fs = [48000 32000 16000]
c_file_content = [ arr_str newline '};' newline];
fprintf(fileID_c,'%s', c_file_content);
c_file_content = ...
['const int16_t defaultHRIR_rom_ITD_model_configuration[4] = {' newline ];
fprintf(fileID_c,'%s', c_file_content);
c_file_content = [ num2str(elevDim3) ', /* elevDim3 */' newline ];
fprintf(fileID_c,'%s', c_file_content);
c_file_content = [ num2str(azimDim3) ', /* azimDim3 */' newline ];
fprintf(fileID_c,'%s', c_file_content);
c_file_content = [ num2str(e_num_points_ITD) ', /* elevSegSamples */' newline ];
fprintf(fileID_c,'%s', c_file_content);
c_file_content = [ num2str(a_num_points_ITD) ', /* azimSegSamples */' newline ];
fprintf(fileID_c,'%s', c_file_content);
c_file_content = ['};' newline ];
fprintf(fileID_c,'%s', c_file_content);
arr_str = join(mat2str((single(len_e_ITD))));
arr_str = arr_str(2:end);
arr_str(end) = ';';
arr_str = replace(arr_str, ";",',');
arr_str = replace(arr_str, " ",', ');
c_file_content = ...
['const int16_t defaultHRIR_rom_ITD_elevBsLen[' num2str(length(len_e_ITD)) '] = {' newline ...
arr_str ...
newline '};' newline ...
];
fprintf(fileID_c,'%s', c_file_content);
arr_str = join(mat2str((single(start_e_ITD))));
arr_str = arr_str(2:end);
arr_str(end) = ';';
arr_str = replace(arr_str, ";",',');
arr_str = replace(arr_str, " ",', ');
c_file_content = ...
['const int16_t defaultHRIR_rom_ITD_elevBsStart[' num2str(length(start_e_ITD)) '] = {' newline ...
arr_str ...
newline '};' newline ...
];
fprintf(fileID_c,'%s', c_file_content);
arr_str = join(mat2str((single(len_a_ITD))));
arr_str = arr_str(2:end);
arr_str(end) = ';';
arr_str = replace(arr_str, ";",',');
arr_str = replace(arr_str, " ",', ');
c_file_content = ...
['const int16_t defaultHRIR_rom_ITD_azimBsLen[' num2str(length(len_a_ITD)) '] = {' newline ...
arr_str ...
newline '};' newline ...
];
fprintf(fileID_c,'%s', c_file_content);
arr_str = join(mat2str((single(start_a_ITD))));
arr_str = arr_str(2:end);
arr_str(end) = ';';
arr_str = replace(arr_str, ";",',');
arr_str = replace(arr_str, " ",', ');
c_file_content = ...
['const int16_t defaultHRIR_rom_ITD_azimBsStart[' num2str(length(start_a_ITD)) '] = {' newline ...
arr_str ...
newline '};' newline ...
];
fprintf(fileID_c,'%s', c_file_content);
arr_str_all = num2hex(single(azimSplineShapeITD_all));
numCol = 25;
numIter = floor(length(azimSplineShapeITD_all)/numCol);
......@@ -809,6 +905,8 @@ end % fs loop
if dataSpec.genRomFile
h_file_content = string(join({''
['extern const int16_t defaultHRIR_rom_elevBsLen[' int2str(length(len_e)) '];']
['extern const int16_t defaultHRIR_rom_elevBsStart[' int2str(length(start_e)) '];']
['extern const uint32_t defaultHRIR_rom_elevBsShape[' int2str(length(elevSplineShape_all)) '];']
['extern const uint32_t defaultHRIR_rom_azimBsShape[' int2str(length(azimSplineShape{1})) '];']
['extern const uint32_t defaultHRIR_rom_ITD_W[' int2str(mod_itd.angleBfNum) '];']
......@@ -816,6 +914,11 @@ if dataSpec.genRomFile
['extern const float defaultHRIR_rom_ITD_azimKSeq[19];']
['extern const uint32_t defaultHRIR_rom_ITD_elevBsShape[' int2str(length(elevSplineShapeITD_all)) '];']
['extern const float defaultHRIR_rom_ITD_elevKSeq[16];']
['extern const int16_t defaultHRIR_rom_ITD_model_configuration[4];']
['extern const int16_t defaultHRIR_rom_ITD_elevBsLen[' int2str(length(len_e_ITD)) '];']
['extern const int16_t defaultHRIR_rom_ITD_elevBsStart[' int2str(length(start_e_ITD)) '];']
['extern const int16_t defaultHRIR_rom_ITD_azimBsLen[' int2str(length(len_a_ITD)) '];']
['extern const int16_t defaultHRIR_rom_ITD_azimBsStart[' int2str(length(start_a_ITD)) '];']
'#endif'
''
}, newline));
......
......@@ -352,7 +352,12 @@ def test_param_file_tests(
max_diff =0
if output_differs:
search_result = re.search(MAX_DIFF_PATTERN, reason)
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
......
......@@ -54,6 +54,13 @@ def pytest_addoption(parser):
type=pathlib.Path,
default='./bin/IVAS_rend',
)
parser.addoption(
"--isar_post_renderer_path",
action="store",
help="path to renderer binary ISAR_post_rend(.exe)",
type=pathlib.Path,
default='./bin/ISAR_post_rend',
)
@pytest.fixture(scope="session")
......@@ -69,3 +76,8 @@ def decoder_path(request) -> str:
@pytest.fixture(scope="session")
def renderer_path(request) -> str:
return str(request.config.option.renderer_path.absolute())
@pytest.fixture(scope="session")
def isar_post_renderer_path(request) -> str:
return str(request.config.option.isar_post_renderer_path.absolute())
......@@ -59,7 +59,7 @@ def replace_paths(instr, testv_path, ref_path, cut_path):
test_dict = {}
TEST_DIR = "."
scripts=["Readme_IVAS_enc.txt", "Readme_IVAS_dec.txt", "Readme_IVAS_rend.txt", "Readme_IVAS_JBM_dec.txt"]
scripts=["Readme_IVAS_enc.txt", "Readme_IVAS_dec.txt", "Readme_IVAS_rend.txt", "Readme_IVAS_JBM_dec.txt", "Readme_IVAS_ISAR_dec.txt", "Readme_IVAS_ISAR_post_rend.txt"]
for s in scripts:
with open(os.path.join(TEST_DIR, s), "r", encoding="UTF-8") as fp:
......@@ -68,6 +68,7 @@ for s in scripts:
dec_opts = ""
diff_opts = ""
rend_opts = ""
isar_post_rend_opts = ""
testv_path = ""
ref_path = ""
cut_path = ""
......@@ -87,31 +88,31 @@ for s in scripts:
dec_opts = line
if line.startswith("$CUT_REND_BIN"):
rend_opts = line
if line.startswith("$CUT_ISAR_POST_REND_BIN"):
isar_post_rend_opts = line
if line.startswith("$DIFF_BIN"):
diff_opts = line
tag = s + "--" + diff_opts.split()[2].split('/')[-1]
if tag in test_dict:
print("non-unique tag found - ignoring new entry")
continue
test_dict[tag] = (enc_opts, dec_opts, rend_opts, diff_opts, testv_path, ref_path, cut_path)
test_dict[tag] = (enc_opts, dec_opts, rend_opts, isar_post_rend_opts, diff_opts, testv_path, ref_path, cut_path)
tag = ""
enc_opts = ""
dec_opts = ""
rend_opts = ""
isar_post_rend_opts = ""
diff_opts = ""
for proc in preproc:
proc = replace_paths(proc, testv_path, ref_path, cut_path)
path_arg = proc.split()[-1]
if "rm" in proc:
if os.path.exists(path_arg):
shutil.rmtree(path_arg, onerror=remove_readonly) # Needed for folder tree removal on Windows.
if "mkdir" in proc:
Path(path_arg).mkdir(parents=True, exist_ok=True)
@pytest.mark.parametrize("test_tag", list(test_dict.keys()))
def test_26252(test_tag, encoder_path, decoder_path, renderer_path):
def test_26252(test_tag, encoder_path, decoder_path, renderer_path, isar_post_renderer_path):
enc_opts, dec_opts, rend_opts, diff_opts, testv_path, ref_path, cut_path = test_dict[test_tag]
enc_opts, dec_opts, rend_opts, isar_post_rend_opts, diff_opts, testv_path, ref_path, cut_path = test_dict[test_tag]
if enc_opts:
enc_opts = replace_paths(enc_opts, testv_path, ref_path, cut_path)
......@@ -122,6 +123,9 @@ def test_26252(test_tag, encoder_path, decoder_path, renderer_path):
if rend_opts:
rend_opts = replace_paths(rend_opts, testv_path, ref_path, cut_path)
subprocess.run([renderer_path] + rend_opts.split()[1:], check = True)
if isar_post_rend_opts:
isar_post_rend_opts = replace_paths(isar_post_rend_opts, testv_path, ref_path, cut_path)
subprocess.run([isar_post_renderer_path] + isar_post_rend_opts.split()[1:], check = True)
diff_opts = replace_paths(diff_opts, testv_path, ref_path, cut_path)
result = True
......
......@@ -114,6 +114,14 @@ FORMAT_TO_FILE_SMOKETEST = {
"NDP_ISM4": NCHAN_TO_FILE[4],
"MASA1": NCHAN_TO_FILE[1],
"MASA2": NCHAN_TO_FILE[2],
"OMASA_1_1": NCHAN_TO_FILE[2],
"OMASA_1_2": NCHAN_TO_FILE[3],
"OMASA_1_3": NCHAN_TO_FILE[4],
"OMASA_1_4": NCHAN_TO_FILE[5],
"OMASA_2_1": NCHAN_TO_FILE[3],
"OMASA_2_2": NCHAN_TO_FILE[4],
"OMASA_2_3": NCHAN_TO_FILE[5],
"OMASA_2_4": NCHAN_TO_FILE[6],
"OSBA_1_1": NCHAN_TO_FILE[5],
"OSBA_2_1": NCHAN_TO_FILE[6],
"OSBA_3_1": NCHAN_TO_FILE[7],
......@@ -149,6 +157,14 @@ FORMAT_TO_FILE_COMPARETEST = {
"ISM4": TESTV_DIR.joinpath("stv4ISM48s.wav"),
"MASA1": TESTV_DIR.joinpath("stv1MASA1TC48c.wav"),
"MASA2": TESTV_DIR.joinpath("stv2MASA2TC48c.wav"),
"OMASA_1_1": TESTV_DIR.joinpath("stvOMASA_1ISM_1MASA1TC48c.wav"),
"OMASA_1_2": TESTV_DIR.joinpath("stvOMASA_2ISM_2MASA1TC48c.wav"),
"OMASA_1_3": TESTV_DIR.joinpath("stvOMASA_3ISM_1MASA1TC48c.wav"),
"OMASA_1_4": TESTV_DIR.joinpath("stvOMASA_4ISM_2MASA1TC48c.wav"),
"OMASA_2_1": TESTV_DIR.joinpath("stvOMASA_1ISM_1MASA2TC48c.wav"),
"OMASA_2_2": TESTV_DIR.joinpath("stvOMASA_2ISM_2MASA2TC48c.wav"),
"OMASA_2_3": TESTV_DIR.joinpath("stvOMASA_3ISM_1MASA2TC48c.wav"),
"OMASA_2_4": TESTV_DIR.joinpath("stvOMASA_4ISM_2MASA2TC48c.wav"),
"OSBA_1_1": TESTV_DIR.joinpath("stvOSBA_1ISM_FOA48c.wav"),
"OSBA_1_2": TESTV_DIR.joinpath("stvOSBA_1ISM_2OA48c.wav"),
"OSBA_1_3": TESTV_DIR.joinpath("stvOSBA_1ISM_3OA48c.wav"),
......@@ -192,6 +208,50 @@ FORMAT_TO_METADATA_FILES = {
],
"MASA1": [str(TESTV_DIR.joinpath("stv1MASA1TC48c.met"))],
"MASA2": [str(TESTV_DIR.joinpath("stv2MASA2TC48c.met"))],
"OMASA_1_1": [
str(TESTV_DIR.joinpath("stvISM1.csv")),
str(TESTV_DIR.joinpath("stvOMASA_1ISM_1MASA1TC48c.met")),
],
"OMASA_1_2": [
str(TESTV_DIR.joinpath("stvISM1.csv")),
str(TESTV_DIR.joinpath("stvISM2.csv")),
str(TESTV_DIR.joinpath("stvOMASA_2ISM_2MASA1TC48c.met")),
],
"OMASA_1_3": [
str(TESTV_DIR.joinpath("stvISM1.csv")),
str(TESTV_DIR.joinpath("stvISM2.csv")),
str(TESTV_DIR.joinpath("stvISM3.csv")),
str(TESTV_DIR.joinpath("stvOMASA_3ISM_1MASA1TC48c.met")),
],
"OMASA_1_4": [
str(TESTV_DIR.joinpath("stvISM1.csv")),
str(TESTV_DIR.joinpath("stvISM2.csv")),
str(TESTV_DIR.joinpath("stvISM3.csv")),
str(TESTV_DIR.joinpath("stvISM4.csv")),
str(TESTV_DIR.joinpath("stvOMASA_4ISM_2MASA1TC48c.met")),
],
"OMASA_2_1": [
str(TESTV_DIR.joinpath("stvISM1.csv")),
str(TESTV_DIR.joinpath("stvOMASA_1ISM_1MASA2TC48c.met")),
],
"OMASA_2_2": [
str(TESTV_DIR.joinpath("stvISM1.csv")),
str(TESTV_DIR.joinpath("stvISM2.csv")),
str(TESTV_DIR.joinpath("stvOMASA_2ISM_2MASA2TC48c.met")),
],
"OMASA_2_3": [
str(TESTV_DIR.joinpath("stvISM1.csv")),
str(TESTV_DIR.joinpath("stvISM2.csv")),
str(TESTV_DIR.joinpath("stvISM3.csv")),
str(TESTV_DIR.joinpath("stvOMASA_3ISM_1MASA2TC48c.met")),
],
"OMASA_2_4": [
str(TESTV_DIR.joinpath("stvISM1.csv")),
str(TESTV_DIR.joinpath("stvISM2.csv")),
str(TESTV_DIR.joinpath("stvISM3.csv")),
str(TESTV_DIR.joinpath("stvISM4.csv")),
str(TESTV_DIR.joinpath("stvOMASA_4ISM_2MASA2TC48c.met")),
],
}
......
......@@ -62,6 +62,41 @@ def run_cmd(cmd, env=None):
f"Command returned non-zero exit status ({e.returncode}): {' '.join(e.cmd)}\n{e.stderr}\n{e.stdout}"
)
def run_isar_ext_rend_cmd(cmd, env=None):
logging.info(f"\nRunning ISAR EXT REND command\n{' '.join(cmd)}\n")
try:
sp.run(cmd, check=True, capture_output=True, text=True, env=env)
except sp.CalledProcessError as e:
raise SystemError(
f"Command returned non-zero exit status ({e.returncode}): {' '.join(e.cmd)}\n{e.stderr}\n{e.stdout}"
)
def run_ivas_isar_enc_cmd(cmd, env=None):
logging.info(f"\nRunning IVAS ISAR encoder command\n{' '.join(cmd)}\n")
try:
sp.run(cmd, check=True, capture_output=True, text=True, env=env)
except sp.CalledProcessError as e:
raise SystemError(
f"Command returned non-zero exit status ({e.returncode}): {' '.join(e.cmd)}\n{e.stderr}\n{e.stdout}"
)
def run_ivas_isar_dec_cmd(cmd, env=None):
logging.info(f"\nDUT decoder command:\n\t{' '.join(cmd)}\n")
try:
sp.run(cmd, check=True, capture_output=True, text=True, env=env)
except sp.CalledProcessError as e:
raise SystemError(
f"Command returned non-zero exit status ({e.returncode}): {' '.join(e.cmd)}\n{e.stderr}\n{e.stdout}"
)
def run_isar_post_rend_cmd(cmd, env=None):
logging.info(f"\nRunning ISAR post renderer command\n{' '.join(cmd)}\n")
try:
sp.run(cmd, check=True, capture_output=True, text=True, env=env)
except sp.CalledProcessError as e:
raise SystemError(
f"Command returned non-zero exit status ({e.returncode}): {' '.join(e.cmd)}\n{e.stderr}\n{e.stdout}"
)
def check_BE(
test_info,
......
<!------------------------------------------------------------------------------------------------------
(C) 2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
(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
......@@ -41,13 +41,14 @@ The tests cover the following IVAS formats:
* Multi-Channel
* ISM
* MASA
* OMASA
* OSBA
The tests include both split rendering operating modes:
* Full chain: encoder, decoder, external renderer
* External: external renderer only
Note: OSBA format only supports the full chain split rendering mode.
Note: OSBA and OMASA formats only support the full chain split rendering mode.
Furthermore, the tests iterate over the following parameters:
* Renderer config file which specifies DoF (degrees of freedom), split rendering bitrate, and split rendering codec
......