Skip to content
...@@ -34,10 +34,10 @@ ...@@ -34,10 +34,10 @@
#include "options.h" #include "options.h"
#ifdef SPLIT_REND_WITH_HEAD_ROT #ifdef SPLIT_REND_WITH_HEAD_ROT
#include <math.h> #include <math.h>
#include "ivas_lcld_prot.h" #include "isar_lcld_prot.h"
#include "ivas_lcld_rom_tables.h" #include "isar_rom_lcld_tables.h"
#include "prot.h" #include "prot.h"
#include "ivas_prot_rend.h" #include "isar_prot.h"
#include "wmc_auto.h" #include "wmc_auto.h"
...@@ -66,6 +66,14 @@ static void deactivate_bit( ...@@ -66,6 +66,14 @@ static void deactivate_bit(
( *state ) &= ( ~( 1 << bit_id ) ); ( *state ) &= ( ~( 1 << bit_id ) );
} }
void UpdatePredictionSubSetId( PredictionEncoder *psPredictionEncoder )
{
if ( ++psPredictionEncoder->iSubSetId == psPredictionEncoder->iNumSubSets )
{
psPredictionEncoder->iSubSetId = 0;
}
}
/*-------------------------------------------------------------------* /*-------------------------------------------------------------------*
* Function CreatePredictionEncoder() * Function CreatePredictionEncoder()
* *
...@@ -92,16 +100,6 @@ ivas_error CreatePredictionEncoder( ...@@ -92,16 +100,6 @@ ivas_error CreatePredictionEncoder(
psPredictionEncoder->iSubSetId = 0; psPredictionEncoder->iSubSetId = 0;
psPredictionEncoder->iMaxNumPredBands = iMaxNumPredBands; psPredictionEncoder->iMaxNumPredBands = iMaxNumPredBands;
psPredictionEncoder->iNumSubSets = iNumSubSets; psPredictionEncoder->iNumSubSets = iNumSubSets;
if ( ( psPredictionEncoder->pfWindow = (float *) malloc( sizeof( float ) * LCLD_PRED_WIN_LEN ) ) == NULL )
{
return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) );
}
for ( n = 0; n < LCLD_PRED_WIN_LEN; n++ )
{
psPredictionEncoder->pfWindow[n] = 0.54f - 0.46f * cosf( 2.0f * M_PI * ( (float) n + 0.5f ) / (float) LCLD_PRED_WIN_LEN );
}
if ( ( psPredictionEncoder->piPredChanEnable = (int32_t *) malloc( sizeof( int32_t ) * iChannels ) ) == NULL ) if ( ( psPredictionEncoder->piPredChanEnable = (int32_t *) malloc( sizeof( int32_t ) * iChannels ) ) == NULL )
{ {
...@@ -115,7 +113,7 @@ ivas_error CreatePredictionEncoder( ...@@ -115,7 +113,7 @@ ivas_error CreatePredictionEncoder(
for ( n = 0; n < psPredictionEncoder->iChannels; n++ ) for ( n = 0; n < psPredictionEncoder->iChannels; n++ )
{ {
psPredictionEncoder->piPredChanEnable[n] = 0; psPredictionEncoder->piPredChanEnable[n] = 0;
psPredictionEncoder->piNumPredBands[n] = 40; // Will need to be set correctly psPredictionEncoder->piNumPredBands[n] = 40;
} }
if ( ( psPredictionEncoder->ppiPredBandEnable = (int32_t **) malloc( sizeof( int32_t * ) * iChannels ) ) == NULL ) if ( ( psPredictionEncoder->ppiPredBandEnable = (int32_t **) malloc( sizeof( int32_t * ) * iChannels ) ) == NULL )
...@@ -271,9 +269,6 @@ void DeletePredictionEncoder( ...@@ -271,9 +269,6 @@ void DeletePredictionEncoder(
PredictionEncoder *psPredictionEncoder ) PredictionEncoder *psPredictionEncoder )
{ {
int32_t n; int32_t n;
free( psPredictionEncoder->pfWindow );
for ( n = 0; n < psPredictionEncoder->iChannels; n++ ) for ( n = 0; n < psPredictionEncoder->iChannels; n++ )
{ {
int32_t k; int32_t k;
...@@ -367,8 +362,7 @@ void ComputePredictors( ...@@ -367,8 +362,7 @@ void ComputePredictors(
for ( c = 0; c < psPredictionEncoder->iChannels; c++ ) for ( c = 0; c < psPredictionEncoder->iChannels; c++ )
{ {
int32_t b; int32_t b;
psPredictionEncoder->piNumPredBands[c] = min( 50, psPredictionEncoder->iMaxNumPredBands ); for ( b = b0; b < psPredictionEncoder->iMaxNumPredBands; b += bstep )
for ( b = b0; b < psPredictionEncoder->piNumPredBands[c]; b += bstep )
{ {
int32_t n; int32_t n;
float fGain = 0.0; float fGain = 0.0;
...@@ -418,7 +412,7 @@ void ComputePredictors( ...@@ -418,7 +412,7 @@ void ComputePredictors(
/* compute these before quant */ /* compute these before quant */
/* Compute est coding gain based on quantized filter coefficients */ /* Compute est coding gain based on quantized filter coefficients */
fGain = 1.0f / ( 1.0f - fA1Real * fA1Real - fA1Imag * fA1Imag ); fGain = 1.0f / ( 1.0f - fA1Real * fA1Real - fA1Imag * fA1Imag );
fBitGain = 0.65f * log2f( fGain ) * (float) ( iNumBlocksPerPredCoef ) - (float) ( PRED_QUNAT_FILTER_MAG_BITS + PRED_QUANT_FILTER_PHASE_BITS ); // Wrong fix (iNumBlocks-1) fBitGain = 0.65f * log2f( fGain ) * (float) ( iNumBlocksPerPredCoef ) - (float) ( PRED_QUNAT_FILTER_MAG_BITS + PRED_QUANT_FILTER_PHASE_BITS );
fA1Mag = sqrtf( fA1Real * fA1Real + fA1Imag * fA1Imag ); fA1Mag = sqrtf( fA1Real * fA1Real + fA1Imag * fA1Imag );
fA1Mag = fMagScale * asinf( fA1Mag ); fA1Mag = fMagScale * asinf( fA1Mag );
iA1Mag = (int32_t) ( fA1Mag + 0.5f ); iA1Mag = (int32_t) ( fA1Mag + 0.5f );
...@@ -430,14 +424,14 @@ void ComputePredictors( ...@@ -430,14 +424,14 @@ void ComputePredictors(
fA1Phase = fPhaseScale * fA1Phase; fA1Phase = fPhaseScale * fA1Phase;
iA1Phase = ( fA1Phase > 0.0f ) ? (int32_t) ( fA1Phase + 0.5f ) : (int32_t) ( fA1Phase - 0.5f ); iA1Phase = ( fA1Phase > 0.0f ) ? (int32_t) ( fA1Phase + 0.5f ) : (int32_t) ( fA1Phase - 0.5f );
iA1Phase = ( iA1Phase > PRED_QUANT_FILTER_PHASE_MIN ) ? iA1Phase : PRED_QUANT_FILTER_PHASE_MIN; iA1Phase = ( iA1Phase > PRED_QUANT_FILTER_PHASE_MIN ) ? iA1Phase : PRED_QUANT_FILTER_PHASE_MIN;
iA1Phase = ( iA1Phase < PRED_QUANT_FILTER_PHASE_MAX ) ? iA1Phase : PRED_QUANT_FILTER_PHASE_MAX; // Is this the correct way to deal with this? should wrap? iA1Phase = ( iA1Phase < PRED_QUANT_FILTER_PHASE_MAX ) ? iA1Phase : PRED_QUANT_FILTER_PHASE_MAX;
fA1Phase = fInvPhaseScale * (float) iA1Phase; fA1Phase = fInvPhaseScale * (float) iA1Phase;
fA1Real = fA1Mag * cosf( fA1Phase ); fA1Real = fA1Mag * cosf( fA1Phase );
fA1Imag = fA1Mag * sinf( fA1Phase ); fA1Imag = fA1Mag * sinf( fA1Phase );
fGain2 = 1.0f / ( 1.0f - fA1Real * fA1Real - fA1Imag * fA1Imag ); fGain2 = 1.0f / ( 1.0f - fA1Real * fA1Real - fA1Imag * fA1Imag );
fBitGain2 = 0.65f * log2f( fGain ) * (float) ( iNumBlocksPerPredCoef ) - (float) ( PRED_QUNAT_FILTER_MAG_BITS + PRED_QUANT_FILTER_PHASE_BITS ); // Wrong fix (iNumBlocks-1) fBitGain2 = 0.65f * log2f( fGain ) * (float) ( iNumBlocksPerPredCoef ) - (float) ( PRED_QUNAT_FILTER_MAG_BITS + PRED_QUANT_FILTER_PHASE_BITS );
fGain = ( fGain < fGain2 ) ? fGain : fGain2; fGain = ( fGain < fGain2 ) ? fGain : fGain2;
fBitGain = ( fBitGain < fBitGain2 ) ? fBitGain : fBitGain2; fBitGain = ( fBitGain < fBitGain2 ) ? fBitGain : fBitGain2;
} }
...@@ -447,11 +441,11 @@ void ComputePredictors( ...@@ -447,11 +441,11 @@ void ComputePredictors(
fA1Imag = 0.0f; fA1Imag = 0.0f;
iA1Mag = 0; iA1Mag = 0;
iA1Phase = 0; iA1Phase = 0;
fGain = -10.0f; // Fix this fGain = -10.0f;
} }
pfEstPredBitGain[b] = fBitGain; pfEstPredBitGain[b] = fBitGain;
psPredictionEncoder->ppiPredBandEnable[c][b] = ( fBitGain > 0.0f ); // Initial prediction enable psPredictionEncoder->ppiPredBandEnable[c][b] = ( fBitGain > 0.0f );
psPredictionEncoder->ppfA1Real[c][b] = fA1Real; psPredictionEncoder->ppfA1Real[c][b] = fA1Real;
psPredictionEncoder->ppfA1Imag[c][b] = fA1Imag; psPredictionEncoder->ppfA1Imag[c][b] = fA1Imag;
psPredictionEncoder->ppiA1Mag[c][b] = iA1Mag; psPredictionEncoder->ppiA1Mag[c][b] = iA1Mag;
...@@ -467,8 +461,8 @@ void ComputePredictors( ...@@ -467,8 +461,8 @@ void ComputePredictors(
fBestCost = 0.0; fBestCost = 0.0;
iPredBands = 0; iPredBands = 0;
fBitGain = -7.0; fBitGain = -7.0;
for ( b = b0; b < 50; b += bstep ) for ( b = b0; b < psPredictionEncoder->iMaxNumPredBands; b += bstep )
{ // still getting this decision wrong! {
fBitGain -= 1.0; fBitGain -= 1.0;
if ( psPredictionEncoder->ppiPredBandEnable[c][b] == 1 ) if ( psPredictionEncoder->ppiPredBandEnable[c][b] == 1 )
{ {
...@@ -491,15 +485,6 @@ void ComputePredictors( ...@@ -491,15 +485,6 @@ void ComputePredictors(
activate_bit( &psPredictionEncoder->piPredChanEnable[c], psPredictionEncoder->iSubSetId ); activate_bit( &psPredictionEncoder->piPredChanEnable[c], psPredictionEncoder->iSubSetId );
psPredictionEncoder->piNumPredBands[c] = iPredBands + bstep; psPredictionEncoder->piNumPredBands[c] = iPredBands + bstep;
} }
else if ( iPredBands > 0 )
{
for ( b = iPredBands; b < LCLD_BANDS; b += bstep )
{
psPredictionEncoder->ppiPredBandEnable[c][b] = 0;
}
activate_bit( &psPredictionEncoder->piPredChanEnable[c], psPredictionEncoder->iSubSetId );
psPredictionEncoder->piNumPredBands[c] = iPredBands;
}
else else
{ {
for ( b = b0; b < LCLD_BANDS; b += bstep ) for ( b = b0; b < LCLD_BANDS; b += bstep )
...@@ -520,61 +505,6 @@ void ComputePredictors( ...@@ -520,61 +505,6 @@ void ComputePredictors(
* *
*-------------------------------------------------------------------*/ *-------------------------------------------------------------------*/
void ApplyForwardPredictors(
PredictionEncoder *psPredictionEncoder,
float ***pppfReal,
float ***pppfImag )
{
int32_t c;
for ( c = 0; c < psPredictionEncoder->iChannels; c++ )
{
int32_t b;
if ( psPredictionEncoder->piPredChanEnable[c] > 0 )
{
for ( b = 0; b < LCLD_BANDS; b++ )
{
if ( psPredictionEncoder->ppiPredBandEnable[c][b] == 1 )
{
int32_t n;
float fOldReal = 0.0f;
float fOldImag = 0.0f;
float fA1Real;
float fA1Imag;
int32_t iSubset = b % psPredictionEncoder->iNumSubSets;
if ( iSubset != psPredictionEncoder->iSubSetId )
{
fOldReal = psPredictionEncoder->ppfInpPrevReal[c][b];
fOldImag = psPredictionEncoder->ppfInpPrevImag[c][b];
}
psPredictionEncoder->ppfInpPrevReal[c][b] = pppfReal[c][psPredictionEncoder->iNumBlocks - 1][b];
psPredictionEncoder->ppfInpPrevImag[c][b] = pppfImag[c][psPredictionEncoder->iNumBlocks - 1][b];
fA1Real = psPredictionEncoder->ppfA1Real[c][b];
fA1Imag = psPredictionEncoder->ppfA1Imag[c][b];
for ( n = 0; n < psPredictionEncoder->iNumBlocks; n++ )
{
float fReal;
float fImag;
fReal = pppfReal[c][n][b] + fA1Real * fOldReal - fA1Imag * fOldImag;
fImag = pppfImag[c][n][b] + fA1Real * fOldImag + fA1Imag * fOldReal;
fOldReal = pppfReal[c][n][b];
fOldImag = pppfImag[c][n][b];
pppfReal[c][n][b] = fReal;
pppfImag[c][n][b] = fImag;
}
}
}
}
}
return;
}
/*-------------------------------------------------------------------* /*-------------------------------------------------------------------*
* Function WritePredictors() * Function WritePredictors()
* *
...@@ -583,7 +513,7 @@ void ApplyForwardPredictors( ...@@ -583,7 +513,7 @@ void ApplyForwardPredictors(
int32_t WritePredictors( int32_t WritePredictors(
PredictionEncoder *psPredictionEncoder, PredictionEncoder *psPredictionEncoder,
IVAS_SPLIT_REND_BITS_HANDLE pBits ) ISAR_SPLIT_REND_BITS_HANDLE pBits )
{ {
int32_t iBitsWritten = 0; int32_t iBitsWritten = 0;
int32_t c; int32_t c;
...@@ -593,13 +523,13 @@ int32_t WritePredictors( ...@@ -593,13 +523,13 @@ int32_t WritePredictors(
const int16_t iSubSetBits = ( LCLD_MAX_NUM_PRED_SUBSETS > 4 ? 3 : 2 ); const int16_t iSubSetBits = ( LCLD_MAX_NUM_PRED_SUBSETS > 4 ? 3 : 2 );
/* number of subsets */ /* number of subsets */
ivas_split_rend_bitstream_write_int32( pBits, iNumSubSets - 1, iSubSetBits ); /* otherwise use default */ ISAR_SPLIT_REND_BITStream_write_int32( pBits, iNumSubSets - 1, iSubSetBits ); /* otherwise use default */
iBitsWritten += iSubSetBits; iBitsWritten += iSubSetBits;
if ( iNumSubSets > 1 ) if ( iNumSubSets > 1 )
{ {
/* write current subset */ /* write current subset */
ivas_split_rend_bitstream_write_int32( pBits, iSubSetId, iSubSetBits ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, iSubSetId, iSubSetBits );
iBitsWritten += iSubSetBits; iBitsWritten += iSubSetBits;
iNumPredBandBits = ( iNumSubSets >= 4 ? 4 : 5 ); iNumPredBandBits = ( iNumSubSets >= 4 ? 4 : 5 );
} }
...@@ -609,19 +539,19 @@ int32_t WritePredictors( ...@@ -609,19 +539,19 @@ int32_t WritePredictors(
int32_t b; int32_t b;
int32_t b0 = iSubSetId; int32_t b0 = iSubSetId;
ivas_split_rend_bitstream_write_int32( pBits, psPredictionEncoder->piPredChanEnable[c], iNumSubSets ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, psPredictionEncoder->piPredChanEnable[c], iNumSubSets );
iBitsWritten += iNumSubSets; iBitsWritten += iNumSubSets;
if ( get_bit( psPredictionEncoder->piPredChanEnable[c], iSubSetId ) ) if ( get_bit( psPredictionEncoder->piPredChanEnable[c], iSubSetId ) )
{ {
int32_t iNumPredBands = ( psPredictionEncoder->piNumPredBands[c] - b0 ) / iNumSubSets; int32_t iNumPredBands = ( psPredictionEncoder->piNumPredBands[c] - b0 ) / iNumSubSets;
ivas_split_rend_bitstream_write_int32( pBits, iNumPredBands, iNumPredBandBits ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, iNumPredBands, iNumPredBandBits );
iBitsWritten += iNumPredBandBits; iBitsWritten += iNumPredBandBits;
for ( b = b0; b < psPredictionEncoder->piNumPredBands[c]; b += iNumSubSets ) for ( b = b0; b < psPredictionEncoder->piNumPredBands[c]; b += iNumSubSets )
{ {
ivas_split_rend_bitstream_write_int32( pBits, psPredictionEncoder->ppiPredBandEnable[c][b], 1 ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, psPredictionEncoder->ppiPredBandEnable[c][b], 1 );
iBitsWritten += 1; iBitsWritten += 1;
if ( psPredictionEncoder->ppiPredBandEnable[c][b] == 1 ) if ( psPredictionEncoder->ppiPredBandEnable[c][b] == 1 )
...@@ -632,10 +562,10 @@ int32_t WritePredictors( ...@@ -632,10 +562,10 @@ int32_t WritePredictors(
iA1Mag = psPredictionEncoder->ppiA1Mag[c][b]; iA1Mag = psPredictionEncoder->ppiA1Mag[c][b];
iA1Phase = psPredictionEncoder->ppiA1Phase[c][b] - PRED_QUANT_FILTER_PHASE_MIN; iA1Phase = psPredictionEncoder->ppiA1Phase[c][b] - PRED_QUANT_FILTER_PHASE_MIN;
ivas_split_rend_bitstream_write_int32( pBits, iA1Mag, PRED_QUNAT_FILTER_MAG_BITS ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, iA1Mag, PRED_QUNAT_FILTER_MAG_BITS );
iBitsWritten += PRED_QUNAT_FILTER_MAG_BITS; iBitsWritten += PRED_QUNAT_FILTER_MAG_BITS;
ivas_split_rend_bitstream_write_int32( pBits, iA1Phase, PRED_QUANT_FILTER_PHASE_BITS ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, iA1Phase, PRED_QUANT_FILTER_PHASE_BITS );
iBitsWritten += PRED_QUANT_FILTER_PHASE_BITS; iBitsWritten += PRED_QUANT_FILTER_PHASE_BITS;
} }
} }
......
...@@ -30,16 +30,13 @@ ...@@ -30,16 +30,13 @@
*******************************************************************************************************/ *******************************************************************************************************/
/* Double check cost function calculation */
#include <stdlib.h> #include <stdlib.h>
#include "options.h" #include "options.h"
#ifdef SPLIT_REND_WITH_HEAD_ROT #ifdef SPLIT_REND_WITH_HEAD_ROT
#include <math.h> #include <math.h>
#include "prot.h" #include "prot.h"
#include "ivas_prot_rend.h" #include "isar_lcld_prot.h"
#include "ivas_lcld_prot.h" #include "isar_rom_lcld_tables.h"
#include "ivas_lcld_rom_tables.h"
#include "wmc_auto.h" #include "wmc_auto.h"
...@@ -244,7 +241,7 @@ static void ComputeBandEnergy( ...@@ -244,7 +241,7 @@ static void ComputeBandEnergy(
fEnergy += ( pppfReal[n][k][iFBOffset] * pppfReal[n][k][iFBOffset] + pppfImag[n][k][iFBOffset] * pppfImag[n][k][iFBOffset] ); fEnergy += ( pppfReal[n][k][iFBOffset] * pppfReal[n][k][iFBOffset] + pppfImag[n][k][iFBOffset] * pppfImag[n][k][iFBOffset] );
iFBOffset++; iFBOffset++;
} }
fEnergy /= (float) ( piBandwidths[b] ); // Correction removed normalization by 2 fEnergy /= (float) ( piBandwidths[b] ); /* Correction removed normalization by 2*/
ppfBandEnergy[k][iChanOffset + b] = fEnergy; ppfBandEnergy[k][iChanOffset + b] = fEnergy;
fWeight = 0.33f * powf( 10.0f, 0.0068f * ( 10.0f * log10f( fEnergy ) - c_afThreshQuiet48[b] ) ); fWeight = 0.33f * powf( 10.0f, 0.0068f * ( 10.0f * log10f( fEnergy ) - c_afThreshQuiet48[b] ) );
...@@ -309,7 +306,7 @@ static void ComputeMergeRMS( ...@@ -309,7 +306,7 @@ static void ComputeMergeRMS(
fRMSEnvelope = log2f( fGroupEnergy ); fRMSEnvelope = log2f( fGroupEnergy );
iQRMSEnvelope = ( fRMSEnvelope > 0.0 ) ? (int32_t) ( fRMSEnvelope + 0.5 ) : (int32_t) ( fRMSEnvelope - 0.5 ); iQRMSEnvelope = ( fRMSEnvelope > 0.0 ) ? (int32_t) ( fRMSEnvelope + 0.5 ) : (int32_t) ( fRMSEnvelope - 0.5 );
fGroupEnergy = 10.0f * log10f( fGroupEnergy ); // Note epsolon was added when computing BandEnergy; fGroupEnergy = 10.0f * log10f( fGroupEnergy ); /* Note epsilon was added when computing BandEnergy;*/
pfMergedEnergydB[b] = fGroupEnergy; pfMergedEnergydB[b] = fGroupEnergy;
piQRMSEnvelope[b] = iQRMSEnvelope; piQRMSEnvelope[b] = iQRMSEnvelope;
...@@ -398,7 +395,7 @@ static float ComputeSNRPenalty( ...@@ -398,7 +395,7 @@ static float ComputeSNRPenalty(
fDeltadB = fRMSVal - ppfBandEnergydB[k][iChanOffset + b]; fDeltadB = fRMSVal - ppfBandEnergydB[k][iChanOffset + b];
if ( fDeltadB < -9.0309f ) if ( fDeltadB < -9.0309f )
{ {
fSNRPenalty += 1e10f; // Some large number to prevent clipping fSNRPenalty += 1e10f; /* Some large number to prevent clipping*/
} }
else /*if(fDeltadB < 0.0)*/ else /*if(fDeltadB < 0.0)*/
{ {
...@@ -541,7 +538,7 @@ static void ComputeGreedyGroups3( ...@@ -541,7 +538,7 @@ static void ComputeGreedyGroups3(
} }
else else
{ {
iDone++; // This only catches a problem iDone++; /* This only catches a problem*/
} }
} }
...@@ -590,7 +587,7 @@ static void ComputeRMSEnvelope( ...@@ -590,7 +587,7 @@ static void ComputeRMSEnvelope(
fGroupEnergy /= (float) piGroupLengths[k]; fGroupEnergy /= (float) piGroupLengths[k];
fGroupEnergy = log2f( fGroupEnergy ); fGroupEnergy = log2f( fGroupEnergy );
pppiRMSEnvelope[n][k][b] = ( fGroupEnergy > 0.0 ) ? (int32_t) ( fGroupEnergy + 0.5 ) : (int32_t) ( fGroupEnergy - 0.5 ); // Bug fix pppiRMSEnvelope[n][k][b] = ( fGroupEnergy > 0.0 ) ? (int32_t) ( fGroupEnergy + 0.5 ) : (int32_t) ( fGroupEnergy - 0.5 );
pppiRMSEnvelope[n][k][b] = ( pppiRMSEnvelope[n][k][b] > ENV_MIN ) ? pppiRMSEnvelope[n][k][b] : ENV_MIN; pppiRMSEnvelope[n][k][b] = ( pppiRMSEnvelope[n][k][b] > ENV_MIN ) ? pppiRMSEnvelope[n][k][b] : ENV_MIN;
pppiRMSEnvelope[n][k][b] = ( pppiRMSEnvelope[n][k][b] < ENV_MAX ) ? pppiRMSEnvelope[n][k][b] : ENV_MAX; pppiRMSEnvelope[n][k][b] = ( pppiRMSEnvelope[n][k][b] < ENV_MAX ) ? pppiRMSEnvelope[n][k][b] : ENV_MAX;
} }
...@@ -668,7 +665,7 @@ void ComputeEnvelopeGrouping( ...@@ -668,7 +665,7 @@ void ComputeEnvelopeGrouping(
RMSEnvelopeGrouping *psRMSEnvelopeGrouping, RMSEnvelopeGrouping *psRMSEnvelopeGrouping,
const int32_t iChannels, const int32_t iChannels,
const int32_t iNumBands, const int32_t iNumBands,
const int32_t *piBandwidths, // pass in absolute thresh const int32_t *piBandwidths,
float ***pppfReal, float ***pppfReal,
float ***pppfImag, float ***pppfImag,
int32_t *piNumGroups, int32_t *piNumGroups,
......
/******************************************************************************************************
(C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
contributors to this repository. All Rights Reserved.
This software is protected by copyright law and by international treaties.
The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
contributors to this repository retain full ownership rights in their respective contributions in
the software. This notice grants no license of any kind, including but not limited to patent
license, nor is any license granted by implication, estoppel or otherwise.
Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
contributions.
This software is provided "AS IS", without any express or implied warranties. The software is in the
development stage. It is intended exclusively for experts who have experience with such software and
solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
and fitness for a particular purpose are hereby disclaimed and excluded.
Any dispute, controversy or claim arising under or in relation to providing this software shall be
submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
the United Nations Convention on Contracts on the International Sales of Goods.
*******************************************************************************************************/
#ifndef ISAR_CNST_H
#define ISAR_CNST_H
#include <stdint.h>
#include "options.h"
/* clang-format off */
#ifdef SPLIT_REND_WITH_HEAD_ROT
/*----------------------------------------------------------------------------------*
* Split Binaural Rendering Constants
*----------------------------------------------------------------------------------*/
typedef enum
{
PCM_INT16,
PCM_FLOAT32,
PCM_NOT_KNOW = 0xffff
} PCM_RESOLUTION;
typedef enum
{
ANY_YAW,
PITCH_ONLY,
ANY_ROLL,
PRED_ONLY,
PRED_ROLL_ONLY,
COM_GAIN_ONLY,
LR_GAIN_ONLY
} ISAR_SPLIT_REND_POSE_TYPE;
#define CLDFB_PLC_XF 2 /* Length of cross-fade into first good frame after frame loss in CLDFB cols. */
#define SPLIT_REND_MAX_YAW_ONLY_POSES 2
#define SPLIT_REND_MAX_PITCH_ONLY_POSES 2
#define SPLIT_REND_MAX_ROLL_ONLY_POSES 2
#define SPLIT_REND_MAX_ONE_AXIS_MD_POSES 2
#define MAX_EXTRAPOLATION_ANGLE 15.0f /* this means additional 15 degrees can be extrapolated on top of MD probing poses*/
#define MAX_HEAD_ROT_POSES ( 2 + SPLIT_REND_MAX_YAW_ONLY_POSES + SPLIT_REND_MAX_PITCH_ONLY_POSES + SPLIT_REND_MAX_ROLL_ONLY_POSES )
#define MAX_SPLIT_REND_MD_BANDS 20
#define MAX_SPLIT_MD_SUBFRAMES 1
#define COMPLEX_MD_BAND_THRESH MAX_SPLIT_REND_MD_BANDS
#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS
#define COMPLEX_MD_BAND_THRESH_LOW 4
#define COMPLEX_MD_BAND_THRESH_HIGH 10
#else
#define COMPLEX_MD_BAND_THRESH_LOW 5
#endif
#define SPLIT_REND_RO_MD_BAND_THRESH 4
#define ISAR_SPLIT_REND_NUM_QUANT_STRATS 4
#define ISAR_SPLIT_REND_PRED_63QUANT_PNTS 63
#define ISAR_SPLIT_REND_PRED_31QUANT_PNTS 31
#define ISAR_SPLIT_REND_ROLL_PRED_QUANT_PNTS 31
#define ISAR_SPLIT_REND_D_QUANT_PNTS 15
#define ISAR_SPLIT_REND_PRED_MIN_VAL -1.4f
#define ISAR_SPLIT_REND_PRED_MAX_VAL 1.4f
#define ISAR_SPLIT_REND_PITCH_G_MIN_VAL 0.5f
#define ISAR_SPLIT_REND_PITCH_G_MAX_VAL 1.5f
#define ISAR_SPLIT_REND_PITCH_G_QUANT_PNTS ISAR_SPLIT_REND_D_QUANT_PNTS
#define ISAR_SPLIT_REND_D_MIN_VAL 0.0f
#define ISAR_SPLIT_REND_D_MAX_VAL 1.0f
#define ISAR_SPLIT_REND_PRED_ROLL_Q_STEP ( ( ISAR_SPLIT_REND_PRED_MAX_VAL - ISAR_SPLIT_REND_PRED_MIN_VAL ) / ( ISAR_SPLIT_REND_ROLL_PRED_QUANT_PNTS - 1 ) )
#define ISAR_SPLIT_REND_PRED_ROLL_1BYQ_STEP ( ( ISAR_SPLIT_REND_ROLL_PRED_QUANT_PNTS - 1 ) / ( ISAR_SPLIT_REND_PRED_MAX_VAL - ISAR_SPLIT_REND_PRED_MIN_VAL ) )
#define ISAR_SPLIT_REND_PRED31_Q_STEP ( ( ISAR_SPLIT_REND_PRED_MAX_VAL - ISAR_SPLIT_REND_PRED_MIN_VAL ) / ( ISAR_SPLIT_REND_PRED_31QUANT_PNTS - 1 ) )
#define ISAR_SPLIT_REND_PRED31_1BYQ_STEP ( ( ISAR_SPLIT_REND_PRED_31QUANT_PNTS - 1 ) / ( ISAR_SPLIT_REND_PRED_MAX_VAL - ISAR_SPLIT_REND_PRED_MIN_VAL ) )
#define ISAR_SPLIT_REND_PRED63_Q_STEP ( ( ISAR_SPLIT_REND_PRED_MAX_VAL - ISAR_SPLIT_REND_PRED_MIN_VAL ) / ( ISAR_SPLIT_REND_PRED_63QUANT_PNTS - 1 ) )
#define ISAR_SPLIT_REND_PRED63_1BYQ_STEP ( ( ISAR_SPLIT_REND_PRED_63QUANT_PNTS - 1 ) / ( ISAR_SPLIT_REND_PRED_MAX_VAL - ISAR_SPLIT_REND_PRED_MIN_VAL ) )
#define ISAR_SPLIT_REND_D_Q_STEP ( ( ISAR_SPLIT_REND_D_MAX_VAL - ISAR_SPLIT_REND_D_MIN_VAL ) / ( ISAR_SPLIT_REND_D_QUANT_PNTS - 1 ) )
#define ISAR_SPLIT_REND_D_1BYQ_STEP ( ( ISAR_SPLIT_REND_D_QUANT_PNTS - 1 ) / ( ISAR_SPLIT_REND_D_MAX_VAL - ISAR_SPLIT_REND_D_MIN_VAL ) )
#define ISAR_SPLIT_REND_PITCH_G_Q_STEP ( ( ISAR_SPLIT_REND_PITCH_G_MAX_VAL - ISAR_SPLIT_REND_PITCH_G_MIN_VAL ) / ( ISAR_SPLIT_REND_PITCH_G_QUANT_PNTS - 1 ) )
#define ISAR_SPLIT_REND_PITCH_G_1BYQ_STEP ( ( ISAR_SPLIT_REND_PITCH_G_QUANT_PNTS - 1 ) / ( ISAR_SPLIT_REND_PITCH_G_MAX_VAL - ISAR_SPLIT_REND_PITCH_G_MIN_VAL ) )
#define ISAR_SPLIT_REND_HEAD_POSE_BITS 9
#define ISAR_SPLIT_REND_DOF_BITS 2
#define ISAR_SPLIT_REND_HQ_MODE_BITS 1
#define ISAR_SPLIT_REND_ROT_AXIS_BITS 3
#define ISAR_SPLIT_REND_RO_FLAG_BITS 1
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
#define IVAS_LC3PLUS_MAX_NUM_DECODERS 2
#endif
/*----------------------------------------------------------------------------------*
* Split rendering bitrate constants
*----------------------------------------------------------------------------------*/
#define SPLIT_REND_256k 256000
#define SPLIT_REND_320k 320000
#define SPLIT_REND_384k 384000
#define SPLIT_REND_512k 512000
#define SPLIT_REND_768k 768000
#endif /*SPLIT_REND_WITH_HEAD_ROT */
#endif /*ISAR_CNST_H */
/* clang-format on */
/******************************************************************************************************
(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 "options.h"
#include "isar_lc3plus_common.h"
#include "ivas_error.h"
#include "lc3.h"
#ifdef SPLIT_REND_WITH_HEAD_ROT
/*-----------------------------------------------------------------------------------------*
* Function ISAR_LC3PLUS_LC3plusErrToIvasErr()
*
*
*-----------------------------------------------------------------------------------------*/
ivas_error ISAR_LC3PLUS_LC3plusErrToIvasErr(
const LC3PLUS_Error lc3PlusError )
{
switch ( lc3PlusError )
{
case LC3PLUS_OK:
return IVAS_ERR_OK;
case LC3PLUS_BITRATE_ERROR:
return IVAS_ERR_LC3PLUS_INVALID_BITRATE;
default:
break;
}
return IVAS_ERR_INTERNAL;
}
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
ivas_error IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( const LC3PLUS_RTP_ERR lc3PlusRtpError )
{
switch ( lc3PlusRtpError )
{
case LC3PLUS_RTP_ERR_NO_ERROR:
return IVAS_ERR_OK;
case LC3PLUS_RTP_ERR_NULL_PTR:
return IVAS_ERR_UNEXPECTED_NULL_POINTER;
case LC3PLUS_RTP_ERR_INVALID_PARAMETERS:
return IVAS_ERR_WRONG_PARAMS;
case LC3PLUS_RTP_ERR_NOT_IMPLEMENTED:
return IVAS_ERR_NOT_IMPLEMENTED;
case LC3PLUS_RTP_ERR_UNSUPPORTED_CONFIGURATION:
return IVAS_ERR_INTERNAL;
case LC3PLUS_RTP_ERR_INVALID_BITSTREAM:
return IVAS_ERR_UNEXPECTED_LC3PLUS_BITSTREAM;
case LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE:
return IVAS_ERR_INVALID_BUFFER_SIZE;
case LC3PLUS_RTP_ERR_NOT_ENOUGH_FTDS_ALLOCATED:
return IVAS_ERR_INTERNAL;
case LC3PLUS_RTP_ERR_GENERIC_ERROR:
default:
break;
}
return IVAS_ERR_UNKNOWN;
}
#endif
#endif
...@@ -30,28 +30,43 @@ ...@@ -30,28 +30,43 @@
*******************************************************************************************************/ *******************************************************************************************************/
#ifndef IVAS_LC3PLUS_COM_H #ifndef ISAR_LC3PLUS_COM_H
#define IVAS_LC3PLUS_COM_H #define ISAR_LC3PLUS_COM_H
#include <stdint.h> #include <stdint.h>
#include "options.h"
#include "ivas_error.h" #include "ivas_error.h"
#ifdef SPLIT_REND_WITH_HEAD_ROT
#include "lc3.h" #include "lc3.h"
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
#include "isar_lc3plus_payload.h"
#endif
/*! common configuration parameters between encoder and decoder */ /*! common configuration parameters between encoder and decoder */
typedef struct LC3PLUS_CONFIG typedef struct LC3PLUS_CONFIG
{ {
/*! frame duration in microseconds [10000, 5000, 2500] */ /*! frame duration in microseconds [10000, 5000, 2500] */
uint32_t lc3plus_frame_duration_us; int16_t lc3plus_frame_duration_us;
/*! ivas frame duration in microseconds [20000, 5000] */ /*! isar frame duration in microseconds [20000, 10000, 5000] */
uint32_t ivas_frame_duration_us; int16_t isar_frame_duration_us;
/*! sampling rate*/ /*! sampling rate*/
uint32_t samplerate; int32_t samplerate;
/*! number of channels */ /*! number of channels */
uint16_t channels; int16_t channels;
#if defined ISAR_BITSTREAM_UPDATE_LC3PLUS || defined ISAR_BITSTREAM_UPDATE_LC3PLUS
/*! high resolution mode enabled (1) or disabled (0)*/
int16_t high_res_mode_enabled;
#endif
} LC3PLUS_CONFIG; } LC3PLUS_CONFIG;
/*! utility function to convert LC3PLUS_Errors to the suitable ivas_error */ /*! utility function to convert LC3PLUS_Errors to the suitable ivas_error */
ivas_error IVAS_LC3PLUS_LC3plusErrToIvasErr( const LC3PLUS_Error lc3PlusError ); ivas_error ISAR_LC3PLUS_LC3plusErrToIvasErr( const LC3PLUS_Error lc3PlusError );
#endif /* IVAS_LC3PLUS_COM_H */ #ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
/*! utility function to convert LC3PLUS_Errors to the suitable ivas_error */
ivas_error IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( const LC3PLUS_RTP_ERR lc3PlusRtpError );
#endif
#endif /* SPLIT_REND_WITH_HEAD_ROT */
#endif /* ISAR_LC3PLUS_COM_H */
...@@ -34,41 +34,80 @@ ...@@ -34,41 +34,80 @@
#include "options.h" #include "options.h"
#include "prot.h" #include "prot.h"
#include "ivas_prot.h" #include "ivas_prot.h"
#include "ivas_lc3plus_dec.h" #include "isar_lc3plus_dec.h"
#include "ivas_lc3plus_common.h" #include "isar_lc3plus_common.h"
#include "lc3.h" #include "lc3.h"
#include "ivas_error_utils.h" #include "ivas_error_utils.h"
#include "wmc_auto.h" #include "wmc_auto.h"
#ifdef SPLIT_REND_WITH_HEAD_ROT #ifdef SPLIT_REND_WITH_HEAD_ROT
#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* IVAS_LC3PLUS_DEC_Open() * isar_LC3PLUS_AllocateSubframeDecodingMatrix()
* *
* *
*------------------------------------------------------------------------*/ *------------------------------------------------------------------------*/
ivas_error IVAS_LC3PLUS_DEC_Open( static void isar_LC3PLUS_DEC_FreeSubframeDecodingMatrix(
int16_t **subframeChannelMatrix )
{
for ( int16_t i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
{
free( subframeChannelMatrix[i] );
}
free( subframeChannelMatrix );
return;
}
#endif
/*-------------------------------------------------------------------------
* ISAR_LC3PLUS_DEC_Open()
*
*
*------------------------------------------------------------------------*/
ivas_error ISAR_LC3PLUS_DEC_Open(
const LC3PLUS_CONFIG config, /* i : LC3plus decoder configuration */ const LC3PLUS_CONFIG config, /* i : LC3plus decoder configuration */
IVAS_LC3PLUS_DEC_HANDLE *handle /* o : decoder handle */ ISAR_LC3PLUS_DEC_HANDLE *handle /* o : decoder handle */
) )
{ {
LC3PLUS_Error err; LC3PLUS_Error err;
int32_t decoder_size; int32_t decoder_size;
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
int16_t i;
if ( 0 == config.lc3plus_frame_duration_us )
{
return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Invalid lc3plus_frame_duration_us (0)\n" );
}
#else
int16_t lc3plusFrameIdx; int16_t lc3plusFrameIdx;
int16_t numLC3plusFramesPerIvasFrame; int16_t numLC3plusFramesPerIvasFrame;
int16_t i; int16_t i;
#endif
if ( ( *handle = malloc( sizeof( struct IVAS_LC3PLUS_DEC_HANDLE ) ) ) == NULL ) if ( ( *handle = malloc( sizeof( struct ISAR_LC3PLUS_DEC_HANDLE ) ) ) == NULL )
{ {
return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" ); return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" );
} }
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
if ( config.channels > IVAS_LC3PLUS_MAX_NUM_DECODERS )
{
return IVAS_ERROR( IVAS_ERR_INIT_ERROR, "Maximum number of channels exceeds IVAS_LC3PLUS_MAX_NUM_DECODERS\n" );
}
#else
if ( 0 == config.lc3plus_frame_duration_us ) if ( 0 == config.lc3plus_frame_duration_us )
{ {
return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Invalid lc3plus_frame_duration_us (0)\n" ); return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Invalid lc3plus_frame_duration_us (0)\n" );
} }
numLC3plusFramesPerIvasFrame = (int16_t) ( config.ivas_frame_duration_us / config.lc3plus_frame_duration_us ); numLC3plusFramesPerIvasFrame = (int16_t) ( config.isar_frame_duration_us / config.lc3plus_frame_duration_us );
#endif
( *handle )->num_decs = 0; ( *handle )->num_decs = 0;
...@@ -77,15 +116,15 @@ ivas_error IVAS_LC3PLUS_DEC_Open( ...@@ -77,15 +116,15 @@ ivas_error IVAS_LC3PLUS_DEC_Open(
( *handle )->selective_decoding_states = NULL; ( *handle )->selective_decoding_states = NULL;
( *handle )->bitstream_caches = NULL; ( *handle )->bitstream_caches = NULL;
if ( ( ( *handle )->handles = malloc( config.channels * sizeof( IVAS_LC3PLUS_DEC_HANDLE ) ) ) == NULL ) if ( ( ( *handle )->handles = malloc( config.channels * sizeof( ISAR_LC3PLUS_DEC_HANDLE ) ) ) == NULL )
{ {
IVAS_LC3PLUS_DEC_Close( handle ); ISAR_LC3PLUS_DEC_Close( handle );
return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" ); return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" );
} }
if ( ( ( *handle )->selective_decoding_states = malloc( config.channels * sizeof( IVAS_LC3PLUS_DEC_SELECTIVE_DECODING_STATE * ) ) ) == NULL ) if ( ( ( *handle )->selective_decoding_states = malloc( config.channels * sizeof( ISAR_LC3PLUS_DEC_SELECTIVE_DECODING_STATE * ) ) ) == NULL )
{ {
IVAS_LC3PLUS_DEC_Close( handle ); ISAR_LC3PLUS_DEC_Close( handle );
return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" ); return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" );
} }
...@@ -95,9 +134,9 @@ ivas_error IVAS_LC3PLUS_DEC_Open( ...@@ -95,9 +134,9 @@ ivas_error IVAS_LC3PLUS_DEC_Open(
( *handle )->selective_decoding_states[i] = NULL; ( *handle )->selective_decoding_states[i] = NULL;
} }
if ( ( ( *handle )->bitstream_caches = malloc( config.channels * sizeof( IVAS_LC3PLUS_DEC_BITSTREAM_CACHE * ) ) ) == NULL ) if ( ( ( *handle )->bitstream_caches = malloc( config.channels * sizeof( ISAR_LC3PLUS_DEC_BITSTREAM_CACHE * ) ) ) == NULL )
{ {
IVAS_LC3PLUS_DEC_Close( handle ); ISAR_LC3PLUS_DEC_Close( handle );
return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" ); return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" );
} }
for ( i = 0; i < config.channels; ++i ) for ( i = 0; i < config.channels; ++i )
...@@ -117,89 +156,103 @@ ivas_error IVAS_LC3PLUS_DEC_Open( ...@@ -117,89 +156,103 @@ ivas_error IVAS_LC3PLUS_DEC_Open(
decoder_size = lc3plus_dec_get_size( config.samplerate, 1 ); decoder_size = lc3plus_dec_get_size( config.samplerate, 1 );
if ( 0 == decoder_size ) if ( 0 == decoder_size )
{ {
IVAS_LC3PLUS_DEC_Close( handle ); ISAR_LC3PLUS_DEC_Close( handle );
return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_dec_get_size failed\n" ); return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_dec_get_size failed\n" );
} }
if ( ( ( *handle )->handles[iCh] = malloc( decoder_size ) ) == NULL ) if ( ( ( *handle )->handles[iCh] = malloc( decoder_size ) ) == NULL )
{ {
IVAS_LC3PLUS_DEC_Close( handle ); ISAR_LC3PLUS_DEC_Close( handle );
return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus decoder\n" ); return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus decoder\n" );
} }
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
err = lc3plus_dec_init( ( *handle )->handles[iCh], config.samplerate, 1, LC3PLUS_PLC_ADVANCED, config.high_res_mode_enabled );
#else
err = lc3plus_dec_init( ( *handle )->handles[iCh], config.samplerate, 1, LC3PLUS_PLC_ADVANCED, 0 ); err = lc3plus_dec_init( ( *handle )->handles[iCh], config.samplerate, 1, LC3PLUS_PLC_ADVANCED, 0 );
#endif
if ( LC3PLUS_OK != err ) if ( LC3PLUS_OK != err )
{ {
IVAS_LC3PLUS_DEC_Close( handle ); ISAR_LC3PLUS_DEC_Close( handle );
return IVAS_ERROR( IVAS_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_dec_init failed\n" ); return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_dec_init failed\n" );
} }
err = lc3plus_dec_set_frame_dms( ( *handle )->handles[iCh], config.lc3plus_frame_duration_us / 100 ); err = lc3plus_dec_set_frame_dms( ( *handle )->handles[iCh], config.lc3plus_frame_duration_us / 100 );
if ( LC3PLUS_OK != err ) if ( LC3PLUS_OK != err )
{ {
IVAS_LC3PLUS_DEC_Close( handle ); ISAR_LC3PLUS_DEC_Close( handle );
return IVAS_ERROR( IVAS_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_dec_set_frame_dms failed\n" ); return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_dec_set_frame_dms failed\n" );
} }
/* allocate and configure per LC3plus decoder skip state */ /* allocate and configure per LC3plus decoder skip state */
if ( ( ( *handle )->selective_decoding_states[iCh] = malloc( sizeof( IVAS_LC3PLUS_DEC_SELECTIVE_DECODING_STATE ) ) ) == NULL ) if ( ( ( *handle )->selective_decoding_states[iCh] = malloc( sizeof( ISAR_LC3PLUS_DEC_SELECTIVE_DECODING_STATE ) ) ) == NULL )
{ {
IVAS_LC3PLUS_DEC_Close( handle ); ISAR_LC3PLUS_DEC_Close( handle );
return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus decoder\n" ); return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus decoder\n" );
} }
#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
if ( ( ( *handle )->selective_decoding_states[iCh]->frame_actions = malloc( numLC3plusFramesPerIvasFrame * sizeof( SelectiveDecAction ) ) ) == NULL ) if ( ( ( *handle )->selective_decoding_states[iCh]->frame_actions = malloc( numLC3plusFramesPerIvasFrame * sizeof( SelectiveDecAction ) ) ) == NULL )
{ {
IVAS_LC3PLUS_DEC_Close( handle ); ISAR_LC3PLUS_DEC_Close( handle );
return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus decoder\n" ); return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus decoder\n" );
} }
#endif
( *handle )->selective_decoding_states[iCh]->has_skipped_a_frame = 0; ( *handle )->selective_decoding_states[iCh]->has_skipped_a_frame = 0;
( *handle )->selective_decoding_states[iCh]->shall_decode_cached_frame = 0; ( *handle )->selective_decoding_states[iCh]->shall_decode_cached_frame = 0;
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
( *handle )->selective_decoding_states[iCh]->frame_action = DEC_ACTION_DECODE_AND_USE;
#else
for ( lc3plusFrameIdx = 0; lc3plusFrameIdx < numLC3plusFramesPerIvasFrame; lc3plusFrameIdx++ ) for ( lc3plusFrameIdx = 0; lc3plusFrameIdx < numLC3plusFramesPerIvasFrame; lc3plusFrameIdx++ )
{ {
( *handle )->selective_decoding_states[iCh]->frame_actions[lc3plusFrameIdx] = DEC_ACTION_DECODE_AND_USE; ( *handle )->selective_decoding_states[iCh]->frame_actions[lc3plusFrameIdx] = DEC_ACTION_DECODE_AND_USE;
} }
#endif
/* allocate and configure per LC3plus decoder bitstream cache */ /* allocate and configure per LC3plus decoder bitstream cache */
if ( ( ( *handle )->bitstream_caches[iCh] = malloc( sizeof( IVAS_LC3PLUS_DEC_BITSTREAM_CACHE ) ) ) == NULL ) if ( ( ( *handle )->bitstream_caches[iCh] = malloc( sizeof( ISAR_LC3PLUS_DEC_BITSTREAM_CACHE ) ) ) == NULL )
{ {
IVAS_LC3PLUS_DEC_Close( handle ); ISAR_LC3PLUS_DEC_Close( handle );
return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus decoder\n" ); return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus decoder\n" );
} }
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
( *handle )->bitstream_caches[iCh]->bitstream_cache_capacity = 400 /*LC3plus max non-HR octet count*/;
#else
( *handle )->bitstream_caches[iCh]->bitstream_cache_capacity = 400 /*LC3plus max non-HR octet count*/ * numLC3plusFramesPerIvasFrame; ( *handle )->bitstream_caches[iCh]->bitstream_cache_capacity = 400 /*LC3plus max non-HR octet count*/ * numLC3plusFramesPerIvasFrame;
#endif
if ( ( ( *handle )->bitstream_caches[iCh]->bitstream_cache = malloc( ( *handle )->bitstream_caches[iCh]->bitstream_cache_capacity ) ) == NULL ) if ( ( ( *handle )->bitstream_caches[iCh]->bitstream_cache = malloc( ( *handle )->bitstream_caches[iCh]->bitstream_cache_capacity ) ) == NULL )
{ {
IVAS_LC3PLUS_DEC_Close( handle ); ISAR_LC3PLUS_DEC_Close( handle );
return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus decoder\n" ); return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus decoder\n" );
} }
( *handle )->bitstream_caches[iCh]->bitstream_cache_size = 0; ( *handle )->bitstream_caches[iCh]->bitstream_cache_size = 0;
} }
( *handle )->config = config; ( *handle )->config = config;
if ( config.ivas_frame_duration_us < config.lc3plus_frame_duration_us || config.ivas_frame_duration_us % config.lc3plus_frame_duration_us != 0 ) if ( config.isar_frame_duration_us < config.lc3plus_frame_duration_us || config.isar_frame_duration_us % config.lc3plus_frame_duration_us != 0 )
{ {
IVAS_LC3PLUS_DEC_Close( handle ); ISAR_LC3PLUS_DEC_Close( handle );
return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "Current pcm_conversion_buffer sizing requires that lc3plus uses a shorter or equal frame duration than ivas\n" ); return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "Current pcm_conversion_buffer sizing requires that lc3plus uses a shorter or equal frame duration than ivas\n" );
} }
if ( ( ( *handle )->pcm_conversion_buffer = malloc( sizeof( int16_t ) * config.samplerate * config.lc3plus_frame_duration_us / 1000000 ) ) == NULL ) if ( ( ( *handle )->pcm_conversion_buffer = malloc( sizeof( int16_t ) * config.samplerate * config.lc3plus_frame_duration_us / 1000000 ) ) == NULL )
{ {
IVAS_LC3PLUS_DEC_Close( handle ); ISAR_LC3PLUS_DEC_Close( handle );
return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus decoder wrapper pcm_conversion_buffer\n" ); return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus decoder wrapper pcm_conversion_buffer\n" );
} }
return IVAS_ERR_OK; return IVAS_ERR_OK;
} }
#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* IVAS_LC3PLUS_DEC_AllocateSubframeDecodingMatrix() * ISAR_LC3PLUS_DEC_AllocateSubframeDecodingMatrix()
* *
* *
*------------------------------------------------------------------------*/ *------------------------------------------------------------------------*/
ivas_error IVAS_LC3PLUS_DEC_AllocateSubframeDecodingMatrix( ivas_error ISAR_LC3PLUS_DEC_AllocateSubframeDecodingMatrix(
int16_t ***subframeChannelMatrix, int16_t ***subframeChannelMatrix,
const uint32_t num_decs ) const uint32_t num_decs )
{ {
...@@ -219,7 +272,7 @@ ivas_error IVAS_LC3PLUS_DEC_AllocateSubframeDecodingMatrix( ...@@ -219,7 +272,7 @@ ivas_error IVAS_LC3PLUS_DEC_AllocateSubframeDecodingMatrix(
{ {
if ( ( ( *subframeChannelMatrix )[i] = malloc( num_decs * sizeof( int16_t ) ) ) == NULL ) if ( ( ( *subframeChannelMatrix )[i] = malloc( num_decs * sizeof( int16_t ) ) ) == NULL )
{ {
IVAS_LC3PLUS_DEC_FreeSubframeDecodingMatrix( *subframeChannelMatrix ); isar_LC3PLUS_DEC_FreeSubframeDecodingMatrix( *subframeChannelMatrix );
return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "subframeChannelMatrix allocation failed\n" ); return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "subframeChannelMatrix allocation failed\n" );
} }
} }
...@@ -229,44 +282,24 @@ ivas_error IVAS_LC3PLUS_DEC_AllocateSubframeDecodingMatrix( ...@@ -229,44 +282,24 @@ ivas_error IVAS_LC3PLUS_DEC_AllocateSubframeDecodingMatrix(
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* IVAS_LC3PLUS_DEC_AllocateSubframeDecodingMatrix() * ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix()
* *
* *
*------------------------------------------------------------------------*/ *------------------------------------------------------------------------*/
void IVAS_LC3PLUS_DEC_FreeSubframeDecodingMatrix( ivas_error ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix(
int16_t **subframeChannelMatrix ) ISAR_LC3PLUS_DEC_HANDLE handle, /* i : LC3plus decoder handle */
{
for ( int16_t i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ )
{
free( subframeChannelMatrix[i] );
}
free( subframeChannelMatrix );
return;
}
/*-------------------------------------------------------------------------
* IVAS_LC3PLUS_DEC_SetSelectiveDecodingMatrix()
*
*
*------------------------------------------------------------------------*/
ivas_error IVAS_LC3PLUS_DEC_SetSelectiveDecodingMatrix(
IVAS_LC3PLUS_DEC_HANDLE handle, /* i : LC3plus decoder handle */
int16_t *subframeChannelMatrix[MAX_PARAM_SPATIAL_SUBFRAMES] ) int16_t *subframeChannelMatrix[MAX_PARAM_SPATIAL_SUBFRAMES] )
{ {
int16_t numIvasSubFramesPerLC3frame; int16_t numIvasSubFramesPerLC3frame;
uint32_t decIdx; uint32_t decIdx;
int16_t ivasSubframeIdx; int16_t ivasSubframeIdx;
int16_t effectiveIvasSubframeDuration; int16_t effectiveIsarSubframeDuration;
int16_t actual_num_spatial_subframes; int16_t actual_num_spatial_subframes;
if ( NULL == handle ) if ( NULL == handle )
{ {
return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "IVAS_LC3PLUS_DEC_HANDLE is NULL\n" ); return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "ISAR_LC3PLUS_DEC_HANDLE is NULL\n" );
} }
if ( NULL == subframeChannelMatrix ) if ( NULL == subframeChannelMatrix )
...@@ -274,14 +307,14 @@ ivas_error IVAS_LC3PLUS_DEC_SetSelectiveDecodingMatrix( ...@@ -274,14 +307,14 @@ ivas_error IVAS_LC3PLUS_DEC_SetSelectiveDecodingMatrix(
return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "subframeChannelMatrix is NULL\n" ); return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "subframeChannelMatrix is NULL\n" );
} }
if ( handle->config.lc3plus_frame_duration_us == 0 || handle->config.ivas_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 ) if ( handle->config.lc3plus_frame_duration_us == 0 || handle->config.isar_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 )
{ {
return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "invalid ivas_frame_duration_us/lc3plus_frame_duration_us values\n" ); return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "invalid isar_frame_duration_us/lc3plus_frame_duration_us values\n" );
} }
effectiveIvasSubframeDuration = (int16_t) ( handle->config.ivas_frame_duration_us == 20000 ? handle->config.ivas_frame_duration_us / MAX_PARAM_SPATIAL_SUBFRAMES : handle->config.ivas_frame_duration_us ); effectiveIsarSubframeDuration = (int16_t) ( handle->config.isar_frame_duration_us == 20000 ? handle->config.isar_frame_duration_us / MAX_PARAM_SPATIAL_SUBFRAMES : handle->config.isar_frame_duration_us );
numIvasSubFramesPerLC3frame = (int16_t) handle->config.lc3plus_frame_duration_us / effectiveIvasSubframeDuration; numIvasSubFramesPerLC3frame = (int16_t) handle->config.lc3plus_frame_duration_us / effectiveIsarSubframeDuration;
actual_num_spatial_subframes = (int16_t) handle->config.ivas_frame_duration_us / effectiveIvasSubframeDuration; actual_num_spatial_subframes = (int16_t) handle->config.isar_frame_duration_us / effectiveIsarSubframeDuration;
/* 0.5(0) = 10ms lc3plus, 5ms subframe */ /* 0.5(0) = 10ms lc3plus, 5ms subframe */
if ( numIvasSubFramesPerLC3frame != 1 ) if ( numIvasSubFramesPerLC3frame != 1 )
{ {
...@@ -360,16 +393,17 @@ ivas_error IVAS_LC3PLUS_DEC_SetSelectiveDecodingMatrix( ...@@ -360,16 +393,17 @@ ivas_error IVAS_LC3PLUS_DEC_SetSelectiveDecodingMatrix(
return IVAS_ERR_OK; return IVAS_ERR_OK;
} }
#endif
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* IVAS_LC3PLUS_DEC_GetDelay() * ISAR_LC3PLUS_DEC_GetDelay()
* *
* *
*------------------------------------------------------------------------*/ *------------------------------------------------------------------------*/
ivas_error IVAS_LC3PLUS_DEC_GetDelay( ivas_error ISAR_LC3PLUS_DEC_GetDelay(
IVAS_LC3PLUS_DEC_HANDLE handle, /* i : LC3plus decoder handle */ ISAR_LC3PLUS_DEC_HANDLE handle, /* i : LC3plus decoder handle */
int32_t *delayInSamples /* o : decoder delay in number of samples per channel */ int32_t *delayInSamples /* o : decoder delay in number of samples per channel */
) )
{ {
...@@ -377,7 +411,7 @@ ivas_error IVAS_LC3PLUS_DEC_GetDelay( ...@@ -377,7 +411,7 @@ ivas_error IVAS_LC3PLUS_DEC_GetDelay(
if ( NULL == handle ) if ( NULL == handle )
{ {
return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "IVAS_LC3PLUS_DEC_HANDLE is NULL\n" ); return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "ISAR_LC3PLUS_DEC_HANDLE is NULL\n" );
} }
if ( NULL == delayInSamples ) if ( NULL == delayInSamples )
{ {
...@@ -407,13 +441,13 @@ ivas_error IVAS_LC3PLUS_DEC_GetDelay( ...@@ -407,13 +441,13 @@ ivas_error IVAS_LC3PLUS_DEC_GetDelay(
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* IVAS_LC3PLUS_DEC_Close() * ISAR_LC3PLUS_DEC_Close()
* *
* *
*------------------------------------------------------------------------*/ *------------------------------------------------------------------------*/
void IVAS_LC3PLUS_DEC_Close( void ISAR_LC3PLUS_DEC_Close(
IVAS_LC3PLUS_DEC_HANDLE *handle /* i/o: Pointer to LC3plus decoder handle */ ISAR_LC3PLUS_DEC_HANDLE *handle /* i/o: Pointer to LC3plus decoder handle */
) )
{ {
if ( NULL == handle || NULL == *handle ) if ( NULL == handle || NULL == *handle )
...@@ -430,7 +464,9 @@ void IVAS_LC3PLUS_DEC_Close( ...@@ -430,7 +464,9 @@ void IVAS_LC3PLUS_DEC_Close(
if ( NULL != ( *handle )->selective_decoding_states && NULL != ( *handle )->selective_decoding_states[iDec] ) if ( NULL != ( *handle )->selective_decoding_states && NULL != ( *handle )->selective_decoding_states[iDec] )
{ {
#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
free( ( *handle )->selective_decoding_states[iDec]->frame_actions ); free( ( *handle )->selective_decoding_states[iDec]->frame_actions );
#endif
free( ( *handle )->selective_decoding_states[iDec] ); free( ( *handle )->selective_decoding_states[iDec] );
} }
...@@ -487,7 +523,7 @@ static ivas_error decode_or_conceal_one_lc3plus_frame( ...@@ -487,7 +523,7 @@ static ivas_error decode_or_conceal_one_lc3plus_frame(
if ( err != LC3PLUS_OK ) if ( err != LC3PLUS_OK )
{ {
return IVAS_ERROR( IVAS_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_dec16 failed\n" ); return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_dec16 failed\n" );
} }
return IVAS_ERR_OK; return IVAS_ERR_OK;
...@@ -495,13 +531,13 @@ static ivas_error decode_or_conceal_one_lc3plus_frame( ...@@ -495,13 +531,13 @@ static ivas_error decode_or_conceal_one_lc3plus_frame(
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* IVAS_LC3PLUS_DEC_Decode_or_Conceal_internal() * isar_LC3PLUS_DEC_Decode_or_Conceal_internal()
* *
* *
*------------------------------------------------------------------------*/ *------------------------------------------------------------------------*/
static ivas_error IVAS_LC3PLUS_DEC_Decode_or_Conceal_internal( static ivas_error isar_LC3PLUS_DEC_Decode_or_Conceal_internal(
IVAS_LC3PLUS_DEC_HANDLE handle, /* i : LC3plus decoder configuration */ ISAR_LC3PLUS_DEC_HANDLE handle, /* i : LC3plus decoder configuration */
uint8_t *bitstream_in, /* i : pointer to input bitstream */ uint8_t *bitstream_in, /* i : pointer to input bitstream */
int32_t bitstream_in_size, /* i : size of bitstream_in */ int32_t bitstream_in_size, /* i : size of bitstream_in */
const int16_t badFrameIndicator, /* i : bad frame indicator. If set to 1, triggers concealment */ const int16_t badFrameIndicator, /* i : bad frame indicator. If set to 1, triggers concealment */
...@@ -509,13 +545,20 @@ static ivas_error IVAS_LC3PLUS_DEC_Decode_or_Conceal_internal( ...@@ -509,13 +545,20 @@ static ivas_error IVAS_LC3PLUS_DEC_Decode_or_Conceal_internal(
) )
{ {
uint32_t iDec; uint32_t iDec;
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
int32_t config_num_media_times;
int32_t iMediaTime;
int32_t iFtd;
LC3PLUS_RTP_PAYLOAD payload;
#else
int32_t iLc3plusFrame; int32_t iLc3plusFrame;
int32_t lc3framesPerIvasFrame; int32_t lc3framesPerIvasFrame;
int32_t bitstreamOffsetPerCoder;
uint8_t *bitstream_in_iter = bitstream_in;
#endif
int32_t ivasSampleIndex; int32_t ivasSampleIndex;
int16_t numSamplesPerLC3plusChannel; int16_t numSamplesPerLC3plusChannel;
int32_t bitstreamOffsetPerCoder;
ivas_error err; ivas_error err;
uint8_t *bitstream_in_iter = bitstream_in;
if ( NULL == handle ) if ( NULL == handle )
{ {
...@@ -538,19 +581,59 @@ static ivas_error IVAS_LC3PLUS_DEC_Decode_or_Conceal_internal( ...@@ -538,19 +581,59 @@ static ivas_error IVAS_LC3PLUS_DEC_Decode_or_Conceal_internal(
return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "bitstream_in_size must be positive\n" ); return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "bitstream_in_size must be positive\n" );
} }
if ( handle->config.ivas_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 ) if ( handle->config.isar_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 )
{
return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "isar_frame_duration_us must be equal or multiple of lc3plus_frame_duration_us \n" );
}
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
config_num_media_times = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us;
if ( !badFrameIndicator )
{
if ( LC3PLUS_RTP_payload_deserialize( &payload, bitstream_in, bitstream_in_size ) != LC3PLUS_RTP_ERR_NO_ERROR )
{
return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_payload_deserialize failed\n" );
}
if ( payload.sampling_rate_hz != handle->config.samplerate )
{
return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "LC3plus config change (samplerate) in bitstream is not supported\n" );
}
if ( payload.num_channels != handle->config.channels )
{
return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "LC3plus config change (number of channels) in bitstream is not supported\n" );
}
if ( payload.frame_duration_us != handle->config.lc3plus_frame_duration_us )
{
return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "LC3plus config change (frame duration) in bitstream is not supported\n" );
}
if ( payload.high_resolution_enabled != handle->config.high_res_mode_enabled )
{ {
return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "ivas_frame_duration_us must be equal or multiple of lc3plus_frame_duration_us \n" ); return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "LC3plus config change (high resolution mode) in bitstream is not supported\n" );
}
if ( payload.num_media_times != config_num_media_times )
{
return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "LC3plus config change (number of media times per frame data block) in bitstream is not supported\n" );
}
} }
#endif
lc3framesPerIvasFrame = handle->config.ivas_frame_duration_us / handle->config.lc3plus_frame_duration_us; #ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
numSamplesPerLC3plusChannel = (int16_t) ( handle->config.samplerate / ( 1000000 / handle->config.isar_frame_duration_us ) / config_num_media_times );
for ( iDec = 0; iDec < handle->num_decs; iDec++ )
{
for ( iMediaTime = 0; iMediaTime < config_num_media_times; iMediaTime++ )
{
iFtd = iDec + iMediaTime * handle->num_decs;
#else
lc3framesPerIvasFrame = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us;
numSamplesPerLC3plusChannel = (int16_t) ( handle->config.samplerate / ( 1000000 / handle->config.ivas_frame_duration_us ) / lc3framesPerIvasFrame ); numSamplesPerLC3plusChannel = (int16_t) ( handle->config.samplerate / ( 1000000 / handle->config.isar_frame_duration_us ) / lc3framesPerIvasFrame );
bitstreamOffsetPerCoder = bitstream_in_size / handle->num_decs / lc3framesPerIvasFrame; bitstreamOffsetPerCoder = bitstream_in_size / handle->num_decs / lc3framesPerIvasFrame;
for ( iDec = 0; iDec < handle->num_decs; iDec++ ) for ( iDec = 0; iDec < handle->num_decs; iDec++ )
{ {
for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ ) for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
{ {
#endif
if ( handle->selective_decoding_states[iDec]->shall_decode_cached_frame ) if ( handle->selective_decoding_states[iDec]->shall_decode_cached_frame )
{ {
if ( 0 == handle->bitstream_caches[iDec]->bitstream_cache_size ) if ( 0 == handle->bitstream_caches[iDec]->bitstream_cache_size )
...@@ -572,8 +655,14 @@ static ivas_error IVAS_LC3PLUS_DEC_Decode_or_Conceal_internal( ...@@ -572,8 +655,14 @@ static ivas_error IVAS_LC3PLUS_DEC_Decode_or_Conceal_internal(
{ {
handle->bitstream_caches[iDec]->bitstream_cache_size = 0; handle->bitstream_caches[iDec]->bitstream_cache_size = 0;
} }
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
switch ( handle->selective_decoding_states[iDec]->frame_action )
#else
switch ( handle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] ) switch ( handle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] )
#endif
{ {
#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
case DEC_ACTION_DECODE_AND_DROP: case DEC_ACTION_DECODE_AND_DROP:
{ {
err = decode_or_conceal_one_lc3plus_frame( handle->handles[iDec], bitstream_in_iter, bitstreamOffsetPerCoder, &handle->pcm_conversion_buffer, badFrameIndicator ); err = decode_or_conceal_one_lc3plus_frame( handle->handles[iDec], bitstream_in_iter, bitstreamOffsetPerCoder, &handle->pcm_conversion_buffer, badFrameIndicator );
...@@ -584,8 +673,37 @@ static ivas_error IVAS_LC3PLUS_DEC_Decode_or_Conceal_internal( ...@@ -584,8 +673,37 @@ static ivas_error IVAS_LC3PLUS_DEC_Decode_or_Conceal_internal(
handle->selective_decoding_states[iDec]->has_skipped_a_frame = 0; handle->selective_decoding_states[iDec]->has_skipped_a_frame = 0;
break; break;
} }
#endif
case DEC_ACTION_DECODE_AND_USE: case DEC_ACTION_DECODE_AND_USE:
{ {
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
if ( badFrameIndicator )
{
err = decode_or_conceal_one_lc3plus_frame( handle->handles[iDec], bitstream_in, bitstream_in_size, &handle->pcm_conversion_buffer, badFrameIndicator );
}
else if ( payload.ftds[iFtd].frame_data_length == LC3PLUS_RTP_FDL_SPEECH_BAD )
{
return IVAS_ERR_NOT_IMPLEMENTED;
/* Untested therefore disabled. Would probably only need to call concealment,
* but the LC3plus API requires a non-NULL ptr for this which is not available here */
}
else
{
err = decode_or_conceal_one_lc3plus_frame( handle->handles[iDec], payload.ftds[iFtd].frame_data, payload.ftds[iFtd].frame_data_length, &handle->pcm_conversion_buffer, badFrameIndicator );
}
if ( err != IVAS_ERR_OK )
{
return IVAS_ERROR( err, "lc3plus decoding failed\n" );
}
for ( int16_t iSampleInt16 = 0; iSampleInt16 < numSamplesPerLC3plusChannel; iSampleInt16++ )
{
ivasSampleIndex = iSampleInt16 + iMediaTime * numSamplesPerLC3plusChannel;
pcm_out[iDec][ivasSampleIndex] = (float) handle->pcm_conversion_buffer[iSampleInt16];
}
handle->selective_decoding_states[iDec]->has_skipped_a_frame = 0;
break;
#else
err = decode_or_conceal_one_lc3plus_frame( handle->handles[iDec], bitstream_in_iter, bitstreamOffsetPerCoder, &handle->pcm_conversion_buffer, badFrameIndicator ); err = decode_or_conceal_one_lc3plus_frame( handle->handles[iDec], bitstream_in_iter, bitstreamOffsetPerCoder, &handle->pcm_conversion_buffer, badFrameIndicator );
if ( err != IVAS_ERR_OK ) if ( err != IVAS_ERR_OK )
{ {
...@@ -599,15 +717,30 @@ static ivas_error IVAS_LC3PLUS_DEC_Decode_or_Conceal_internal( ...@@ -599,15 +717,30 @@ static ivas_error IVAS_LC3PLUS_DEC_Decode_or_Conceal_internal(
} }
handle->selective_decoding_states[iDec]->has_skipped_a_frame = 0; handle->selective_decoding_states[iDec]->has_skipped_a_frame = 0;
break; break;
#endif
} }
#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
case DEC_ACTION_SKIP: case DEC_ACTION_SKIP:
{ {
/* log that this instance has skipped a frame and must decode twice once reactivated */ /* log that this instance has skipped a frame and must decode twice once reactivated */
handle->selective_decoding_states[iDec]->has_skipped_a_frame = 1; handle->selective_decoding_states[iDec]->has_skipped_a_frame = 1;
break; break;
} }
#endif
case DEC_ACTION_CACHE: case DEC_ACTION_CACHE:
{ {
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
if ( handle->bitstream_caches[iDec]->bitstream_cache_capacity < (int32_t) payload.ftds[iFtd].frame_data_length )
{
return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "bitstream_cache_capacity is too low for LC3plus frame size\n" );
}
/* store bit rate of cached frame */
mvc2c( payload.ftds[iFtd].frame_data, handle->bitstream_caches[iDec]->bitstream_cache, (int16_t) payload.ftds[iFtd].frame_data_length );
handle->bitstream_caches[iDec]->bitstream_cache_size = payload.ftds[iFtd].frame_data_length;
/* log that this instance has skipped a frame and must decode twice once reactivated */
handle->selective_decoding_states[iDec]->has_skipped_a_frame = 1;
break;
#else
if ( handle->bitstream_caches[iDec]->bitstream_cache_capacity < bitstreamOffsetPerCoder ) if ( handle->bitstream_caches[iDec]->bitstream_cache_capacity < bitstreamOffsetPerCoder )
{ {
return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "bitstream_cache_capacity is too low for LC3plus frame size\n" ); return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "bitstream_cache_capacity is too low for LC3plus frame size\n" );
...@@ -618,11 +751,18 @@ static ivas_error IVAS_LC3PLUS_DEC_Decode_or_Conceal_internal( ...@@ -618,11 +751,18 @@ static ivas_error IVAS_LC3PLUS_DEC_Decode_or_Conceal_internal(
/* log that this instance has skipped a frame and must decode twice once reactivated */ /* log that this instance has skipped a frame and must decode twice once reactivated */
handle->selective_decoding_states[iDec]->has_skipped_a_frame = 1; handle->selective_decoding_states[iDec]->has_skipped_a_frame = 1;
break; break;
#endif
} }
case DEC_ACTION_NUM_ENUMS: case DEC_ACTION_NUM_ENUMS:
default: default:
return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "invalid LC3plus decoder state\n" ); return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "invalid LC3plus decoder state\n" );
} }
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
} /* for each media time */
/* reset skipping state, must be set by the user before each decode call*/
handle->selective_decoding_states[iDec]->frame_action = DEC_ACTION_DECODE_AND_USE;
} /* for each dec/channel */
#else
bitstream_in_iter += bitstreamOffsetPerCoder; bitstream_in_iter += bitstreamOffsetPerCoder;
} }
...@@ -634,18 +774,19 @@ static ivas_error IVAS_LC3PLUS_DEC_Decode_or_Conceal_internal( ...@@ -634,18 +774,19 @@ static ivas_error IVAS_LC3PLUS_DEC_Decode_or_Conceal_internal(
} }
} }
#endif
return IVAS_ERR_OK; return IVAS_ERR_OK;
} }
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* IVAS_LC3PLUS_DEC_Decode() * ISAR_LC3PLUS_DEC_Decode()
* *
* *
*------------------------------------------------------------------------*/ *------------------------------------------------------------------------*/
ivas_error IVAS_LC3PLUS_DEC_Decode( ivas_error ISAR_LC3PLUS_DEC_Decode(
IVAS_LC3PLUS_DEC_HANDLE handle, /* i : LC3plus decoder configuration */ ISAR_LC3PLUS_DEC_HANDLE handle, /* i : LC3plus decoder configuration */
uint8_t *bitstream_in, /* i : pointer to input bitstream */ uint8_t *bitstream_in, /* i : pointer to input bitstream */
const int32_t bitstream_in_size, /* i : size of bitstream_in */ const int32_t bitstream_in_size, /* i : size of bitstream_in */
float **pcm_out /* o : decoded samples */ float **pcm_out /* o : decoded samples */
...@@ -667,18 +808,18 @@ ivas_error IVAS_LC3PLUS_DEC_Decode( ...@@ -667,18 +808,18 @@ ivas_error IVAS_LC3PLUS_DEC_Decode(
} }
badFrameIndicator = 0; badFrameIndicator = 0;
return IVAS_LC3PLUS_DEC_Decode_or_Conceal_internal( handle, bitstream_in, bitstream_in_size, badFrameIndicator, pcm_out ); return isar_LC3PLUS_DEC_Decode_or_Conceal_internal( handle, bitstream_in, bitstream_in_size, badFrameIndicator, pcm_out );
} }
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* IVAS_LC3PLUS_DEC_Conceal() * ISAR_LC3PLUS_DEC_Conceal()
* *
* *
*------------------------------------------------------------------------*/ *------------------------------------------------------------------------*/
ivas_error IVAS_LC3PLUS_DEC_Conceal( ivas_error ISAR_LC3PLUS_DEC_Conceal(
IVAS_LC3PLUS_DEC_HANDLE handle, /* i : LC3plus decoder handle */ ISAR_LC3PLUS_DEC_HANDLE handle, /* i : LC3plus decoder handle */
float **pcm_out /* o : concealed samples */ float **pcm_out /* o : concealed samples */
) )
{ {
...@@ -698,6 +839,6 @@ ivas_error IVAS_LC3PLUS_DEC_Conceal( ...@@ -698,6 +839,6 @@ ivas_error IVAS_LC3PLUS_DEC_Conceal(
/* LC3plus API requires a non-NULL bitstream pointer, even when triggering concealment */ /* LC3plus API requires a non-NULL bitstream pointer, even when triggering concealment */
badFrameIndicator = 1; badFrameIndicator = 1;
return IVAS_LC3PLUS_DEC_Decode_or_Conceal_internal( handle, bitstream_in, 0, badFrameIndicator, pcm_out ); return isar_LC3PLUS_DEC_Decode_or_Conceal_internal( handle, bitstream_in, 0, badFrameIndicator, pcm_out );
} }
#endif /* SPLIT_REND_WITH_HEAD_ROT */ #endif /* SPLIT_REND_WITH_HEAD_ROT */
...@@ -30,90 +30,106 @@ ...@@ -30,90 +30,106 @@
*******************************************************************************************************/ *******************************************************************************************************/
#ifndef IVAS_LC3PLUS_DEC_H #ifndef ISAR_LC3PLUS_DEC_H
#define IVAS_LC3PLUS_DEC_H #define ISAR_LC3PLUS_DEC_H
#include <stdint.h> #include <stdint.h>
#include "options.h" #include "options.h"
#ifdef SPLIT_REND_WITH_HEAD_ROT
#include "lc3.h" #include "lc3.h"
#include "ivas_error.h" #include "ivas_error.h"
#include "ivas_lc3plus_common.h"
#include "ivas_cnst.h" #include "ivas_cnst.h"
#include "isar_lc3plus_common.h"
typedef enum typedef enum
{ {
#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
DEC_ACTION_DECODE_AND_DROP = 0, DEC_ACTION_DECODE_AND_DROP = 0,
#endif
DEC_ACTION_DECODE_AND_USE, DEC_ACTION_DECODE_AND_USE,
#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
DEC_ACTION_SKIP, DEC_ACTION_SKIP,
#endif
DEC_ACTION_CACHE, DEC_ACTION_CACHE,
DEC_ACTION_NUM_ENUMS DEC_ACTION_NUM_ENUMS
} SelectiveDecAction; } SelectiveDecAction;
typedef struct IVAS_LC3PLUS_DEC_SELECTIVE_DECODING_STATE typedef struct ISAR_LC3PLUS_DEC_SELECTIVE_DECODING_STATE
{ {
/*! indicates that the decoder has skipped one or more frames. This means it must decode two frames to flush algorithmic delay when re-activated */ /*! indicates that the decoder has skipped one or more frames. This means it must decode two frames to flush algorithmic delay when re-activated */
int16_t has_skipped_a_frame; int16_t has_skipped_a_frame;
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
/*! action to execute for the next frame */
SelectiveDecAction frame_action;
#else
/*! if set to 1, decoder will skip decoding for the next frame */ /*! if set to 1, decoder will skip decoding for the next frame */
SelectiveDecAction *frame_actions; SelectiveDecAction *frame_actions;
#endif
/*! if set to 1, decoder will decode the cache before decoding any of current frames */ /*! if set to 1, decoder will decode the cache before decoding any of current frames */
int16_t shall_decode_cached_frame; int16_t shall_decode_cached_frame;
} IVAS_LC3PLUS_DEC_SELECTIVE_DECODING_STATE; } ISAR_LC3PLUS_DEC_SELECTIVE_DECODING_STATE;
typedef struct IVAS_LC3PLUS_DEC_BITSTREAM_CACHE typedef struct ISAR_LC3PLUS_DEC_BITSTREAM_CACHE
{ {
uint8_t *bitstream_cache; uint8_t *bitstream_cache;
int32_t bitstream_cache_capacity; int32_t bitstream_cache_capacity;
int32_t bitstream_cache_size; int32_t bitstream_cache_size;
} IVAS_LC3PLUS_DEC_BITSTREAM_CACHE; } ISAR_LC3PLUS_DEC_BITSTREAM_CACHE;
/* decoder wrapper */ /* decoder wrapper */
typedef struct IVAS_LC3PLUS_DEC_HANDLE typedef struct ISAR_LC3PLUS_DEC_HANDLE
{ {
LC3PLUS_Dec **handles; LC3PLUS_Dec **handles;
IVAS_LC3PLUS_DEC_SELECTIVE_DECODING_STATE **selective_decoding_states; ISAR_LC3PLUS_DEC_SELECTIVE_DECODING_STATE **selective_decoding_states;
IVAS_LC3PLUS_DEC_BITSTREAM_CACHE **bitstream_caches; ISAR_LC3PLUS_DEC_BITSTREAM_CACHE **bitstream_caches;
uint32_t num_decs; uint32_t num_decs;
int16_t *pcm_conversion_buffer; int16_t *pcm_conversion_buffer;
LC3PLUS_CONFIG config; LC3PLUS_CONFIG config;
} * IVAS_LC3PLUS_DEC_HANDLE; } * ISAR_LC3PLUS_DEC_HANDLE;
ivas_error IVAS_LC3PLUS_DEC_Open( ivas_error ISAR_LC3PLUS_DEC_Open(
const LC3PLUS_CONFIG config, /* i : decoder configuration */ const LC3PLUS_CONFIG config, /* i : decoder configuration */
IVAS_LC3PLUS_DEC_HANDLE *handle /* o : decoder handle */ ISAR_LC3PLUS_DEC_HANDLE *handle /* o : decoder handle */
); );
ivas_error IVAS_LC3PLUS_DEC_GetDelay( ivas_error ISAR_LC3PLUS_DEC_GetDelay(
IVAS_LC3PLUS_DEC_HANDLE handle, /* i : decoder handle */ ISAR_LC3PLUS_DEC_HANDLE handle, /* i : decoder handle */
int32_t *delayInSamples /* o : algorithmic delay of encoding and decoding in number of samples per channel */ int32_t *delayInSamples /* o : algorithmic delay of encoding and decoding in number of samples per channel */
); );
void IVAS_LC3PLUS_DEC_Close( void ISAR_LC3PLUS_DEC_Close(
IVAS_LC3PLUS_DEC_HANDLE *handle /* i/o: pointer to decoder handle */ ISAR_LC3PLUS_DEC_HANDLE *handle /* i/o: pointer to decoder handle */
); );
#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
/*! Sets a matrix[MAX_PARAM_SPATIAL_SUBFRAMES][numLC3plusDecoders] where all require subframes must be flagged with 1, frames that are not required with 0 */ /*! Sets a matrix[MAX_PARAM_SPATIAL_SUBFRAMES][numLC3plusDecoders] where all require subframes must be flagged with 1, frames that are not required with 0 */
ivas_error IVAS_LC3PLUS_DEC_SetSelectiveDecodingMatrix( ivas_error ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix(
IVAS_LC3PLUS_DEC_HANDLE handle, /* i : decoder handle */ ISAR_LC3PLUS_DEC_HANDLE handle, /* i : decoder handle */
int16_t *subframeChannelMatrix[MAX_PARAM_SPATIAL_SUBFRAMES] /* i : */ int16_t *subframeChannelMatrix[MAX_PARAM_SPATIAL_SUBFRAMES] /* i : */
); );
#endif
ivas_error IVAS_LC3PLUS_DEC_Decode( ivas_error ISAR_LC3PLUS_DEC_Decode(
IVAS_LC3PLUS_DEC_HANDLE handle, /* i : decoder handle */ ISAR_LC3PLUS_DEC_HANDLE handle, /* i : decoder handle */
uint8_t *bitstream_in, /* i : pointer to input bitstream */ uint8_t *bitstream_in, /* i : pointer to input bitstream */
const int32_t bitstream_in_size, /* i : size of bitstream_in */ const int32_t bitstream_in_size, /* i : size of bitstream_in */
float **pcm_out /* o : decoded samples */ float **pcm_out /* o : decoded samples */
); );
ivas_error IVAS_LC3PLUS_DEC_Conceal( ivas_error ISAR_LC3PLUS_DEC_Conceal(
IVAS_LC3PLUS_DEC_HANDLE handle, /* i : decoder handle */ ISAR_LC3PLUS_DEC_HANDLE handle, /* i : decoder handle */
float **pcm_out /* o : concealed samples */ float **pcm_out /* o : concealed samples */
); );
ivas_error IVAS_LC3PLUS_DEC_AllocateSubframeDecodingMatrix( #ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
ivas_error ISAR_LC3PLUS_DEC_AllocateSubframeDecodingMatrix(
int16_t ***subframeChannelMatrix, int16_t ***subframeChannelMatrix,
const uint32_t num_decs ); const uint32_t num_decs );
void IVAS_LC3PLUS_DEC_FreeSubframeDecodingMatrix( int16_t **subframeChannelMatrix ); void ISAR_LC3PLUS_DEC_FreeSubframeDecodingMatrix( int16_t **subframeChannelMatrix );
#endif
#endif /* IVAS_LC3PLUS_DEC_H */ #endif /* SPLIT_REND_WITH_HEAD_ROT */
#endif /* ISAR_LC3PLUS_DEC_H */
...@@ -30,27 +30,83 @@ ...@@ -30,27 +30,83 @@
*******************************************************************************************************/ *******************************************************************************************************/
#include "ivas_lc3plus_enc.h" #include "isar_lc3plus_enc.h"
#include "ivas_lc3plus_common.h" #include "isar_lc3plus_common.h"
#include "lc3.h" #include "lc3.h"
#include "ivas_error_utils.h" #include "ivas_error_utils.h"
#include "prot.h" #include "prot.h"
#include "wmc_auto.h" #include "wmc_auto.h"
#include "options.h"
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
static const LC3PLUS_RTP_FDL s_fdl_request = LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA;
#endif
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
static int32_t limit_per_channel_bitrate( LC3PLUS_CONFIG config,
int32_t per_channel_bitrate )
{
if ( config.high_res_mode_enabled )
{
switch ( config.lc3plus_frame_duration_us )
{
case 10000:
return min( per_channel_bitrate, 500000 );
case 5000:
return min( per_channel_bitrate, 600000 );
case 2500:
return min( per_channel_bitrate, 672000 );
default:
assert( false && "unreachable" );
}
}
switch ( config.samplerate )
{
case 48000:
case 32000:
return min( per_channel_bitrate, 320000 );
case 24000:
return min( per_channel_bitrate, 314400 );
case 16000:
return min( per_channel_bitrate, 221600 );
case 8000:
return min( per_channel_bitrate, 114400 );
default:
assert( false && "unreachable" );
}
assert( false && "unreachable" );
return -1;
}
#endif
#ifdef SPLIT_REND_WITH_HEAD_ROT #ifdef SPLIT_REND_WITH_HEAD_ROT
/*-------------------------------------------------------------------* /*-------------------------------------------------------------------*
* Function IVAS_LC3PLUS_ENC_Open() * Function ISAR_LC3PLUS_ENC_Open()
* *
* *
*-------------------------------------------------------------------*/ *-------------------------------------------------------------------*/
ivas_error IVAS_LC3PLUS_ENC_Open( ivas_error ISAR_LC3PLUS_ENC_Open(
const LC3PLUS_CONFIG config, /* i : LC3plus encoder configuration */ const LC3PLUS_CONFIG config, /* i : LC3plus encoder configuration */
const uint32_t bitsPerSecond, /* i : bit rate */ const uint32_t bitsPerSecond, /* i : bit rate */
IVAS_LC3PLUS_ENC_HANDLE *handle /* o : encoder handle */ ISAR_LC3PLUS_ENC_HANDLE *handle /* o : encoder handle */
) )
{ {
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
int32_t num_lc3plus_media_times_per_ivas_frame;
#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
int32_t lc3plus_num_bytes_per_frame;
#endif
bool is_last_media_time, is_last_channel;
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
ivas_error ivas_err;
#endif
#endif
#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
int32_t bitsPerSecondPerChannel; int32_t bitsPerSecondPerChannel;
#endif
int32_t encoder_size; int32_t encoder_size;
LC3PLUS_Error err; LC3PLUS_Error err;
int32_t lfeChans[1]; int32_t lfeChans[1];
...@@ -62,24 +118,39 @@ ivas_error IVAS_LC3PLUS_ENC_Open( ...@@ -62,24 +118,39 @@ ivas_error IVAS_LC3PLUS_ENC_Open(
{ {
return IVAS_ERROR( IVAS_ERR_INTERNAL, "Invalid number of channels\n" ); return IVAS_ERROR( IVAS_ERR_INTERNAL, "Invalid number of channels\n" );
} }
#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
bitsPerSecondPerChannel = bitsPerSecond / config.channels; bitsPerSecondPerChannel = bitsPerSecond / config.channels;
#endif
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
if ( config.lc3plus_frame_duration_us != 2500 && config.lc3plus_frame_duration_us != 5000 && config.lc3plus_frame_duration_us != 10000 )
{
return IVAS_ERROR( IVAS_ERR_INTERNAL, "Invalid lc3plus_frame_duration_us\n" );
}
if ( config.isar_frame_duration_us != 20000 && config.isar_frame_duration_us != 10000 && config.isar_frame_duration_us != 5000 )
{
return IVAS_ERROR( IVAS_ERR_INTERNAL, "Invalid isar_frame_duration_us\n" );
}
#endif
encoder_size = lc3plus_enc_get_size( config.samplerate, 1 ); encoder_size = lc3plus_enc_get_size( config.samplerate, 1 );
if ( 0 == encoder_size ) if ( 0 == encoder_size )
{ {
return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_enc_get_size failed\n" ); return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_enc_get_size failed\n" );
} }
if ( ( *handle = malloc( sizeof( struct IVAS_LC3PLUS_ENC_HANDLE ) ) ) == NULL ) if ( ( *handle = malloc( sizeof( struct ISAR_LC3PLUS_ENC_HANDLE ) ) ) == NULL )
{ {
return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" ); return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" );
} }
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
( *handle )->config = config;
( *handle )->frame_type_descriptors = NULL;
#endif
( *handle )->pcm_conversion_buffer = NULL; ( *handle )->pcm_conversion_buffer = NULL;
( *handle )->num_encs = 0; ( *handle )->num_encs = 0;
if ( ( ( *handle )->handles = malloc( config.channels * sizeof( IVAS_LC3PLUS_ENC_HANDLE ) ) ) == NULL ) if ( ( ( *handle )->handles = malloc( config.channels * sizeof( ISAR_LC3PLUS_ENC_HANDLE ) ) ) == NULL )
{ {
IVAS_LC3PLUS_ENC_Close( handle ); ISAR_LC3PLUS_ENC_Close( handle );
return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" ); return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" );
} }
...@@ -88,63 +159,243 @@ ivas_error IVAS_LC3PLUS_ENC_Open( ...@@ -88,63 +159,243 @@ ivas_error IVAS_LC3PLUS_ENC_Open(
( *handle )->handles[i] = NULL; ( *handle )->handles[i] = NULL;
} }
( *handle )->num_encs = config.channels; ( *handle )->num_encs = config.channels;
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
num_lc3plus_media_times_per_ivas_frame = config.isar_frame_duration_us / config.lc3plus_frame_duration_us;
( *handle )->fdl_request = s_fdl_request;
( *handle )->num_ftds = config.channels * num_lc3plus_media_times_per_ivas_frame;
( *handle )->frame_type_descriptors = malloc( ( *handle )->num_ftds * sizeof( LC3PLUS_RTP_FTD ) );
if ( NULL == ( *handle )->frame_type_descriptors )
{
ISAR_LC3PLUS_ENC_Close( handle );
return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus frame_type_descriptors\n" );
}
#endif
for ( int32_t iCh = 0; iCh < config.channels; iCh++ ) for ( int32_t iCh = 0; iCh < config.channels; iCh++ )
{ {
if ( ( ( *handle )->handles[iCh] = malloc( encoder_size ) ) == NULL ) if ( ( ( *handle )->handles[iCh] = malloc( encoder_size ) ) == NULL )
{ {
IVAS_LC3PLUS_ENC_Close( handle ); ISAR_LC3PLUS_ENC_Close( handle );
return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus encoder\n" ); return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus encoder\n" );
} }
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
err = lc3plus_enc_init( ( *handle )->handles[iCh], config.samplerate, 1, config.high_res_mode_enabled, lfeChans );
#else
err = lc3plus_enc_init( ( *handle )->handles[iCh], config.samplerate, 1, 0, lfeChans ); err = lc3plus_enc_init( ( *handle )->handles[iCh], config.samplerate, 1, 0, lfeChans );
#endif
if ( err != LC3PLUS_OK ) if ( err != LC3PLUS_OK )
{ {
IVAS_LC3PLUS_ENC_Close( handle ); ISAR_LC3PLUS_ENC_Close( handle );
return IVAS_ERROR( IVAS_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc_init failed\n" ); return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc_init failed\n" );
} }
err = lc3plus_enc_set_frame_dms( ( *handle )->handles[iCh], config.lc3plus_frame_duration_us / 100 ); err = lc3plus_enc_set_frame_dms( ( *handle )->handles[iCh], config.lc3plus_frame_duration_us / 100 );
if ( err != LC3PLUS_OK ) if ( err != LC3PLUS_OK )
{ {
IVAS_LC3PLUS_ENC_Close( handle ); ISAR_LC3PLUS_ENC_Close( handle );
return IVAS_ERROR( IVAS_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc_set_frame_dms failed\n" ); return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc_set_frame_dms failed\n" );
} }
#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
err = lc3plus_enc_set_bitrate( ( *handle )->handles[iCh], bitsPerSecondPerChannel ); err = lc3plus_enc_set_bitrate( ( *handle )->handles[iCh], bitsPerSecondPerChannel );
if ( err != LC3PLUS_OK ) if ( err != LC3PLUS_OK )
{ {
IVAS_LC3PLUS_ENC_Close( handle ); ISAR_LC3PLUS_ENC_Close( handle );
return IVAS_ERROR( IVAS_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc_set_bitrate failed\n" ); return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc_set_bitrate failed\n" );
} }
#endif
} }
if ( config.ivas_frame_duration_us < config.lc3plus_frame_duration_us || config.ivas_frame_duration_us % config.lc3plus_frame_duration_us != 0 ) if ( config.isar_frame_duration_us < config.lc3plus_frame_duration_us || config.isar_frame_duration_us % config.lc3plus_frame_duration_us != 0 )
{ {
IVAS_LC3PLUS_ENC_Close( handle ); ISAR_LC3PLUS_ENC_Close( handle );
return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "Current pcm_conversion_buffer sizing requires that lc3plus uses a shorter or equal frame duration than ivas\n" ); return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "Current pcm_conversion_buffer sizing requires that lc3plus uses a shorter or equal frame duration than ivas\n" );
} }
#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
( *handle )->config = config; ( *handle )->config = config;
#endif
( *handle )->pcm_conversion_buffer = malloc( sizeof( int16_t ) * config.samplerate * config.lc3plus_frame_duration_us / 1000000 ); ( *handle )->pcm_conversion_buffer = malloc( sizeof( int16_t ) * config.samplerate * config.lc3plus_frame_duration_us / 1000000 );
if ( NULL == ( *handle )->pcm_conversion_buffer ) if ( NULL == ( *handle )->pcm_conversion_buffer )
{ {
IVAS_LC3PLUS_ENC_Close( handle ); ISAR_LC3PLUS_ENC_Close( handle );
return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus encoder wrapper pcm_conversion_buffer\n" ); return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus encoder wrapper pcm_conversion_buffer\n" );
} }
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
/* update FDI fields */
for ( int32_t iMediaTime = 0; iMediaTime < num_lc3plus_media_times_per_ivas_frame; ++iMediaTime )
{
for ( uint32_t iEnc = 0; iEnc < ( *handle )->num_encs; ++iEnc )
{
int32_t ftd_index = iEnc + iMediaTime * ( *handle )->num_encs;
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
( *handle )->frame_type_descriptors[ftd_index].frame_data_length = 0; /* will be set to the correct value in IVAS_LC3PLUS_ENC_SetBitrate */
#else
lc3plus_num_bytes_per_frame = lc3plus_enc_get_num_bytes( ( *handle )->handles[iEnc] );
if ( lc3plus_num_bytes_per_frame <= 0 )
{
ISAR_LC3PLUS_ENC_Close( handle );
return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_enc_get_num_bytes reported invalid result failed\n" );
}
( *handle )->frame_type_descriptors[ftd_index].frame_data_length = lc3plus_num_bytes_per_frame;
#endif
if ( 0 != LC3PLUS_RTP_ftd_bwr_from_samplerate( &( *handle )->frame_type_descriptors[ftd_index].bwr, config.samplerate, config.high_res_mode_enabled ) )
{
ISAR_LC3PLUS_ENC_Close( handle );
return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_ftd_bwr_from_samplerate failed\n" );
}
if ( 0 != LC3PLUS_RTP_ftd_fdi_from_frame_duration_us( &( *handle )->frame_type_descriptors[ftd_index].fdi, config.lc3plus_frame_duration_us ) )
{
ISAR_LC3PLUS_ENC_Close( handle );
return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_ftd_fdi_from_frame_duration_us failed\n" );
}
( *handle )->frame_type_descriptors[ftd_index].h = LC3PLUS_RTP_FTD_H_PRIMARY;
( *handle )->frame_type_descriptors[ftd_index].frame_data = NULL;
/* The FTDs in the ToC are included in the following order:
* 1) First the FTD for the first channel of the first FDB (oldest frame)
* 2) Then the FTDs for the remaining channels for the first FDB in increasing CC order
* 3) Then the FTD for the first channel of the second FDB
* 4) Then the FTDs for the remaining channels for the second FDB
* 5) Etc. to the last FDB */
is_last_media_time = num_lc3plus_media_times_per_ivas_frame - 1 == iMediaTime;
is_last_channel = ( *handle )->num_encs - 1 == iEnc;
if ( is_last_media_time && is_last_channel )
{
( *handle )->frame_type_descriptors[ftd_index].fc = LC3PLUS_RTP_FTD_FC_LAST_OVERALL;
}
else if ( !is_last_media_time && is_last_channel )
{
( *handle )->frame_type_descriptors[ftd_index].fc = LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME;
}
else
{
( *handle )->frame_type_descriptors[ftd_index].fc = LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL;
}
}
}
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
ivas_err = IVAS_LC3PLUS_ENC_SetBitrate( *handle, bitsPerSecond );
if ( ivas_err != IVAS_ERR_OK )
{
ISAR_LC3PLUS_ENC_Close( handle );
return ivas_err;
}
#endif
#endif
return IVAS_ERR_OK;
}
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
/*-------------------------------------------------------------------*
* Function IVAS_LC3PLUS_ENC_SetBitrate()
*
*
*-------------------------------------------------------------------*/
ivas_error IVAS_LC3PLUS_ENC_SetBitrate(
ISAR_LC3PLUS_ENC_HANDLE handle, /* o : LC3plus encoder handle */
const uint32_t bitsPerSecond /* i : new target bit rate */
)
{
int32_t numLc3plusMediaTimesPerIvasFrame;
int32_t lc3plus_num_bytes_per_frame;
int32_t availableOctetsPerIsarFrame;
int32_t actualOctetsPerFrame;
LC3PLUS_Error err;
int32_t iFtd;
int32_t fdrLength;
int32_t lc3plusPacketRate;
int32_t numSubframes;
int32_t minPayloadOverhead;
int32_t targetLc3PlusBitratePerChannel;
int32_t targetLc3PlusOctetCount;
int32_t lc3plusFdlLength;
if ( NULL == handle )
{
return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3PLUS_Enc_Wrap_Handle is NULL\n" );
}
availableOctetsPerIsarFrame = bitsPerSecond / ( 1000000 / handle->config.isar_frame_duration_us ) / 8;
lc3plusPacketRate = 1000 * 1000 / handle->config.lc3plus_frame_duration_us;
numLc3plusMediaTimesPerIvasFrame = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us;
numSubframes = numLc3plusMediaTimesPerIvasFrame * handle->config.channels;
/* subtract minimum required payload bytes & calculate a first per-channel target bit rate */
if ( LC3PLUS_RTP_frame_data_length_get_size( &fdrLength, s_fdl_request ) != LC3PLUS_RTP_ERR_NO_ERROR )
{
return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_frame_data_length_get_size failed\n" );
}
minPayloadOverhead = fdrLength + ( numSubframes * LC3PLUS_RTP_FTD_MIN_SIZE );
targetLc3PlusBitratePerChannel = ( availableOctetsPerIsarFrame - minPayloadOverhead ) / handle->config.channels * 8 * lc3plusPacketRate / numLc3plusMediaTimesPerIvasFrame;
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
if ( targetLc3PlusBitratePerChannel <= 0 )
{
return IVAS_ERROR( IVAS_ERR_LC3PLUS_INVALID_BITRATE, "available LC3plus bitrate <= 0\n" );
}
#endif
targetLc3PlusBitratePerChannel = limit_per_channel_bitrate( handle->config, targetLc3PlusBitratePerChannel );
targetLc3PlusOctetCount = targetLc3PlusBitratePerChannel / 8 / lc3plusPacketRate;
/* check resulting octet count. If it requires larger than 1-byte length fields, decrease the bitrate by enough to make room for the additional length field */
if ( LC3PLUS_RTP_frame_data_length_get_size( &lc3plusFdlLength, targetLc3PlusOctetCount ) != LC3PLUS_RTP_ERR_NO_ERROR )
{
return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_frame_data_length_get_size failed\n" );
}
if ( lc3plusFdlLength != LC3PLUS_RTP_FDL_MIN_LENGTH )
{
/* reduce bitrate to allow for the required fdl field */
targetLc3PlusBitratePerChannel = ( targetLc3PlusOctetCount - ( lc3plusFdlLength - LC3PLUS_RTP_FDL_MIN_LENGTH ) ) / handle->config.channels * 8 * lc3plusPacketRate;
}
for ( int32_t iCh = 0; iCh < handle->config.channels; iCh++ )
{
err = lc3plus_enc_set_bitrate( handle->handles[iCh], targetLc3PlusBitratePerChannel );
if ( err != LC3PLUS_OK )
{
return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc_set_bitrate failed\n" );
}
}
// update FTD settings after bitrate change
for ( int32_t iMediaTime = 0; iMediaTime < numLc3plusMediaTimesPerIvasFrame; ++iMediaTime )
{
for ( uint32_t iEnc = 0; iEnc < handle->num_encs; ++iEnc )
{
iFtd = iEnc + iMediaTime * handle->num_encs;
lc3plus_num_bytes_per_frame = lc3plus_enc_get_num_bytes( handle->handles[iEnc] );
if ( lc3plus_num_bytes_per_frame <= 0 )
{
return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_enc_get_num_bytes reported invalid result failed\n" );
}
handle->frame_type_descriptors[iFtd].frame_data_length = lc3plus_num_bytes_per_frame;
}
}
// TODO: remove sanity checks?
if ( ISAR_LC3PLUS_ENC_GetOutputBitstreamSize( handle, &actualOctetsPerFrame ) != IVAS_ERR_OK )
{
return IVAS_ERROR( IVAS_ERR_INTERNAL, "ISAR_LC3PLUS_ENC_GetOutputBitstreamSize failed\n" );
}
if ( actualOctetsPerFrame > availableOctetsPerIsarFrame )
{
return IVAS_ERROR( IVAS_ERR_INTERNAL, "Bitrate reduction logic failed\n" );
}
return IVAS_ERR_OK; return IVAS_ERR_OK;
} }
#endif
/*-------------------------------------------------------------------* /*-------------------------------------------------------------------*
* Function IVAS_LC3PLUS_ENC_GetDelay() * Function ISAR_LC3PLUS_ENC_GetDelay()
* *
* *
*-------------------------------------------------------------------*/ *-------------------------------------------------------------------*/
ivas_error IVAS_LC3PLUS_ENC_GetDelay( ivas_error ISAR_LC3PLUS_ENC_GetDelay(
IVAS_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */ ISAR_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */
int32_t *delayInSamples /* o : encoder delay in number of samples per channel */ int32_t *delayInSamples /* o : encoder delay in number of samples per channel */
) )
{ {
...@@ -181,17 +432,25 @@ ivas_error IVAS_LC3PLUS_ENC_GetDelay( ...@@ -181,17 +432,25 @@ ivas_error IVAS_LC3PLUS_ENC_GetDelay(
/*-------------------------------------------------------------------* /*-------------------------------------------------------------------*
* Function IVAS_LC3PLUS_ENC_GetOutputBitstreamSize() * Function ISAR_LC3PLUS_ENC_GetOutputBitstreamSize()
* *
* *
*-------------------------------------------------------------------*/ *-------------------------------------------------------------------*/
ivas_error IVAS_LC3PLUS_ENC_GetOutputBitstreamSize( ivas_error ISAR_LC3PLUS_ENC_GetOutputBitstreamSize(
IVAS_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */ ISAR_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */
int32_t *bsSize /* o : size of each bitstream frame in bytes */ int32_t *bsSize /* o : size of each bitstream frame in bytes */
) )
{ {
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
LC3PLUS_RTP_ERR rtp_err;
int32_t num_lc3plus_media_times_per_ivas_frame;
int32_t iMediaTime;
int32_t ftd_frame_data_length_size, lc3plus_frame_data_length;
int32_t ftd_index;
#else
int32_t bitstreamSizeMultiplier; int32_t bitstreamSizeMultiplier;
#endif
if ( NULL == handle ) if ( NULL == handle )
{ {
return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3PLUS_Enc_Wrap_Handle is NULL\n" ); return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3PLUS_Enc_Wrap_Handle is NULL\n" );
...@@ -201,42 +460,90 @@ ivas_error IVAS_LC3PLUS_ENC_GetOutputBitstreamSize( ...@@ -201,42 +460,90 @@ ivas_error IVAS_LC3PLUS_ENC_GetOutputBitstreamSize(
return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "bsSize is NULL\n" ); return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "bsSize is NULL\n" );
} }
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
if ( 0 == handle->config.lc3plus_frame_duration_us )
{
return IVAS_ERROR( IVAS_ERR_INIT_ERROR, "lc3plus_frame_duration_us is 0\n" );
}
if ( handle->config.isar_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 )
{
return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "isar_frame_duration_us must be equal or multiple of lc3plus_frame_duration_us \n" );
}
num_lc3plus_media_times_per_ivas_frame = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us;
#endif
*bsSize = 0; *bsSize = 0;
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
int32_t fdl_request_length;
rtp_err = LC3PLUS_RTP_frame_data_length_get_size( &fdl_request_length, handle->fdl_request );
if ( rtp_err != LC3PLUS_RTP_ERR_NO_ERROR )
{
return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Invalid LC3plus frame_data_length request\n" );
}
*bsSize += fdl_request_length;
#endif
for ( uint32_t iEnc = 0; iEnc < handle->num_encs; iEnc++ ) for ( uint32_t iEnc = 0; iEnc < handle->num_encs; iEnc++ )
{ {
if ( NULL == handle->handles[iEnc] ) if ( NULL == handle->handles[iEnc] )
{ {
return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3plus encoder handle is NULL\n" ); return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3plus encoder handle is NULL\n" );
} }
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
lc3plus_frame_data_length = lc3plus_enc_get_num_bytes( handle->handles[iEnc] );
for ( iMediaTime = 0; iMediaTime < num_lc3plus_media_times_per_ivas_frame; ++iMediaTime )
{
ftd_index = iEnc + iMediaTime * handle->num_encs;
if ( lc3plus_frame_data_length != (int32_t) handle->frame_type_descriptors[ftd_index].frame_data_length )
{
return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "LC3plus FTD data not synchronised with encoder bitrate\n" );
}
rtp_err = LC3PLUS_RTP_frame_data_length_get_size( &ftd_frame_data_length_size, handle->frame_type_descriptors[ftd_index].frame_data_length );
if ( rtp_err != LC3PLUS_RTP_ERR_NO_ERROR )
{
return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Invalid LC3plus frame_data_length\n" );
}
*bsSize += LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL;
*bsSize += handle->frame_type_descriptors[ftd_index].frame_data_length;
*bsSize += ftd_frame_data_length_size;
}
}
#else
*bsSize += lc3plus_enc_get_num_bytes( handle->handles[iEnc] ); *bsSize += lc3plus_enc_get_num_bytes( handle->handles[iEnc] );
} }
if ( handle->config.ivas_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 ) if ( handle->config.isar_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 )
{ {
return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "ivas_frame_duration_us must be equal or multiple of lc3plus_frame_duration_us \n" ); return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "isar_frame_duration_us must be equal or multiple of lc3plus_frame_duration_us \n" );
} }
bitstreamSizeMultiplier = handle->config.ivas_frame_duration_us / handle->config.lc3plus_frame_duration_us; bitstreamSizeMultiplier = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us;
*bsSize *= bitstreamSizeMultiplier; *bsSize *= bitstreamSizeMultiplier;
#endif
return IVAS_ERR_OK; return IVAS_ERR_OK;
} }
/*-------------------------------------------------------------------* /*-------------------------------------------------------------------*
* Function IVAS_LC3PLUS_ENC_Close() * Function ISAR_LC3PLUS_ENC_Close()
* *
* *
*-------------------------------------------------------------------*/ *-------------------------------------------------------------------*/
void IVAS_LC3PLUS_ENC_Close( void ISAR_LC3PLUS_ENC_Close(
IVAS_LC3PLUS_ENC_HANDLE *handle /* i/o: pointer to LC3plus encoder handle */ ISAR_LC3PLUS_ENC_HANDLE *handle /* i/o: pointer to LC3plus encoder handle */
) )
{ {
if ( NULL == handle || NULL == *handle ) if ( NULL == handle || NULL == *handle )
{ {
return; return;
} }
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
if ( NULL != ( *handle )->frame_type_descriptors )
{
free( ( *handle )->frame_type_descriptors );
}
#endif
for ( uint32_t iEnc = 0; iEnc < ( *handle )->num_encs; iEnc++ ) for ( uint32_t iEnc = 0; iEnc < ( *handle )->num_encs; iEnc++ )
{ {
if ( NULL != ( *handle )->handles[iEnc] ) if ( NULL != ( *handle )->handles[iEnc] )
...@@ -260,25 +567,36 @@ void IVAS_LC3PLUS_ENC_Close( ...@@ -260,25 +567,36 @@ void IVAS_LC3PLUS_ENC_Close(
/*-------------------------------------------------------------------* /*-------------------------------------------------------------------*
* Function IVAS_LC3PLUS_ENC_Encode() * Function ISAR_LC3PLUS_ENC_Encode()
* *
* *
*-------------------------------------------------------------------*/ *-------------------------------------------------------------------*/
ivas_error IVAS_LC3PLUS_ENC_Encode( ivas_error ISAR_LC3PLUS_ENC_Encode(
IVAS_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */ ISAR_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */
float **pcm_in, /* i : pointer input samples */ float **pcm_in, /* i : pointer input samples */
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
void *bitstream_out, /* o : pointer to bitstream frame */
const int32_t bitstream_out_size /* i : size of the bitstream_out buffer in bytes. Must be equal to ISAR_LC3PLUS_ENC_GetOutputBitstreamSize. */
#else
void *bitstream_out /* o : pointer to bitstream frame */ void *bitstream_out /* o : pointer to bitstream frame */
#endif
) )
{ {
uint32_t numSamplesPerLC3plusChannel; #ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
int32_t ftdIndex;
LC3PLUS_RTP_ERR rtpErr;
uint32_t num_media_times;
#else
uint32_t lc3framesPerIvasFrame; uint32_t lc3framesPerIvasFrame;
int32_t ivasSampleIndex;
uint8_t *bitstream_out_iter = bitstream_out; uint8_t *bitstream_out_iter = bitstream_out;
#endif
uint32_t numSamplesPerLC3plusChannel;
int32_t ivasSampleIndex;
int32_t num_bytes = 0; int32_t num_bytes = 0;
LC3PLUS_Error err; LC3PLUS_Error err;
push_wmops( "IVAS_LC3PLUS_ENC_Encode" ); push_wmops( "ISAR_LC3PLUS_ENC_Encode" );
if ( NULL == handle ) if ( NULL == handle )
{ {
...@@ -293,37 +611,71 @@ ivas_error IVAS_LC3PLUS_ENC_Encode( ...@@ -293,37 +611,71 @@ ivas_error IVAS_LC3PLUS_ENC_Encode(
return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "bitstream_out is NULL\n" ); return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "bitstream_out is NULL\n" );
} }
if ( handle->config.ivas_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 ) if ( handle->config.isar_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 )
{
return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "isar_frame_duration_us must be equal or multiple of lc3plus_frame_duration_us \n" );
}
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
num_media_times = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us;
numSamplesPerLC3plusChannel = handle->config.samplerate / ( 1000000 / handle->config.isar_frame_duration_us ) / num_media_times;
size_t actual_size;
rtpErr = LC3PLUS_RTP_payload_serialize( bitstream_out, bitstream_out_size, &actual_size, s_fdl_request, handle->frame_type_descriptors, handle->num_ftds );
if ( rtpErr != LC3PLUS_RTP_ERR_NO_ERROR )
{ {
return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "ivas_frame_duration_us must be equal or multiple of lc3plus_frame_duration_us \n" ); return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( rtpErr ), "LC3PLUS_RTP_payload_serialize failed\n" );
} }
lc3framesPerIvasFrame = handle->config.ivas_frame_duration_us / handle->config.lc3plus_frame_duration_us; #else
lc3framesPerIvasFrame = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us;
numSamplesPerLC3plusChannel = handle->config.samplerate / ( 1000000 / handle->config.ivas_frame_duration_us ) / lc3framesPerIvasFrame; numSamplesPerLC3plusChannel = handle->config.samplerate / ( 1000000 / handle->config.isar_frame_duration_us ) / lc3framesPerIvasFrame;
#endif
for ( uint32_t iEnc = 0; iEnc < handle->num_encs; iEnc++ ) for ( uint32_t iEnc = 0; iEnc < handle->num_encs; iEnc++ )
{ {
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
for ( uint32_t iMediaTime = 0; iMediaTime < num_media_times; iMediaTime++ )
#else
for ( uint32_t iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ ) for ( uint32_t iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ )
#endif
{ {
for ( uint32_t iSampleInt16 = 0; iSampleInt16 < numSamplesPerLC3plusChannel; iSampleInt16++ ) for ( uint32_t iSampleInt16 = 0; iSampleInt16 < numSamplesPerLC3plusChannel; iSampleInt16++ )
{ {
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
ivasSampleIndex = iSampleInt16 + iMediaTime * numSamplesPerLC3plusChannel;
#else
ivasSampleIndex = iSampleInt16 + iLc3plusFrame * numSamplesPerLC3plusChannel; ivasSampleIndex = iSampleInt16 + iLc3plusFrame * numSamplesPerLC3plusChannel;
#endif
handle->pcm_conversion_buffer[iSampleInt16] = (int16_t) max( INT16_MIN, min( pcm_in[iEnc][ivasSampleIndex], INT16_MAX ) ); handle->pcm_conversion_buffer[iSampleInt16] = (int16_t) max( INT16_MIN, min( pcm_in[iEnc][ivasSampleIndex], INT16_MAX ) );
} }
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
ftdIndex = iMediaTime * handle->num_encs + iEnc;
#endif
num_bytes = 0; num_bytes = 0;
push_wmops( "lc3plus_enc16" ); push_wmops( "lc3plus_enc16" );
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
err = lc3plus_enc16( handle->handles[iEnc], &handle->pcm_conversion_buffer, handle->frame_type_descriptors[ftdIndex].frame_data, &num_bytes, NULL );
#else
err = lc3plus_enc16( handle->handles[iEnc], &handle->pcm_conversion_buffer, bitstream_out_iter, &num_bytes, NULL ); err = lc3plus_enc16( handle->handles[iEnc], &handle->pcm_conversion_buffer, bitstream_out_iter, &num_bytes, NULL );
#endif
pop_wmops(); pop_wmops();
if ( err != LC3PLUS_OK ) if ( err != LC3PLUS_OK )
{ {
return IVAS_ERROR( IVAS_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc16 failed\n" ); return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc16 failed\n" );
} }
if ( 0 == num_bytes ) if ( 0 == num_bytes )
{ {
return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_enc16 did not produce output\n" ); return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_enc16 did not produce output\n" );
} }
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
if ( num_bytes != (int32_t) handle->frame_type_descriptors[ftdIndex].frame_data_length )
{
return IVAS_ERROR( IVAS_ERR_INTERNAL, "payload format and lc3plus enc bitrate are not aligned\n" );
}
#else
bitstream_out_iter += num_bytes; bitstream_out_iter += num_bytes;
#endif
} }
} }
......
...@@ -30,47 +30,73 @@ ...@@ -30,47 +30,73 @@
*******************************************************************************************************/ *******************************************************************************************************/
#ifndef IVAS_LC3PLUS_ENC_H #ifndef ISAR_LC3PLUS_ENC_H
#define IVAS_LC3PLUS_ENC_H #define ISAR_LC3PLUS_ENC_H
#include <stdint.h> #include <stdint.h>
#include "lc3.h"
#include "ivas_error.h" #include "ivas_error.h"
#include "ivas_lc3plus_common.h" #ifdef SPLIT_REND_WITH_HEAD_ROT
#include "lc3.h"
#include "isar_lc3plus_common.h"
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
#include "isar_lc3plus_payload.h"
#endif
/* encoder wrapper */ /* encoder wrapper */
typedef struct IVAS_LC3PLUS_ENC_HANDLE typedef struct ISAR_LC3PLUS_ENC_HANDLE
{ {
LC3PLUS_CONFIG config; LC3PLUS_CONFIG config;
LC3PLUS_Enc **handles; LC3PLUS_Enc **handles;
uint32_t num_encs; uint32_t num_encs;
int16_t *pcm_conversion_buffer; int16_t *pcm_conversion_buffer;
} * IVAS_LC3PLUS_ENC_HANDLE; #ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
LC3PLUS_RTP_FTD *frame_type_descriptors;
int32_t num_ftds;
LC3PLUS_RTP_FDL fdl_request;
#endif
} * ISAR_LC3PLUS_ENC_HANDLE;
ivas_error IVAS_LC3PLUS_ENC_Open( ivas_error ISAR_LC3PLUS_ENC_Open(
const LC3PLUS_CONFIG config, /* i : encoder configuration */ const LC3PLUS_CONFIG config, /* i : encoder configuration */
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
const uint32_t initialBitsPerSecond, /* i : initial target bit rate */
#else
const uint32_t bitsPerSecond, /* i : bit rate */ const uint32_t bitsPerSecond, /* i : bit rate */
IVAS_LC3PLUS_ENC_HANDLE *handle /* o : LC3plus encoder handle */ #endif
ISAR_LC3PLUS_ENC_HANDLE *handle /* o : LC3plus encoder handle */
);
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
ivas_error IVAS_LC3PLUS_ENC_SetBitrate(
ISAR_LC3PLUS_ENC_HANDLE handle, /* o : LC3plus encoder handle */
const uint32_t bitsPerSecond /* i : new target bit rate */
); );
#endif
ivas_error IVAS_LC3PLUS_ENC_GetDelay( ivas_error ISAR_LC3PLUS_ENC_GetDelay(
IVAS_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */ ISAR_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */
int32_t *delayInSamples /* o : algorithmic delay of encoding and decoding in number of samples per channel */ int32_t *delayInSamples /* o : algorithmic delay of encoding and decoding in number of samples per channel */
); );
ivas_error IVAS_LC3PLUS_ENC_GetOutputBitstreamSize( ivas_error ISAR_LC3PLUS_ENC_GetOutputBitstreamSize(
IVAS_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */ ISAR_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */
int32_t *bsSize /* o : size of each bitstream frame in bytes */ int32_t *bsSize /* o : size of next bitstream frame in bytes */
); );
void IVAS_LC3PLUS_ENC_Close( void ISAR_LC3PLUS_ENC_Close(
IVAS_LC3PLUS_ENC_HANDLE *handle /* i/o: pointer to LC3plus encoder handle */ ISAR_LC3PLUS_ENC_HANDLE *handle /* i/o: pointer to LC3plus encoder handle */
); );
ivas_error IVAS_LC3PLUS_ENC_Encode( ivas_error ISAR_LC3PLUS_ENC_Encode(
IVAS_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */ ISAR_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */
float **pcm_in, /* i : pointer input samples */ float **pcm_in, /* i : pointer input samples */
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
void *bitstream_out, /* o : pointer to bitstream frame */
const int32_t bitstream_out_size /* i : size of the bitstream_out buffer in bytes. Must be equal to ISAR_LC3PLUS_ENC_GetOutputBitstreamSize. */
#else
void *bitstream_out /* o : pointer to bitstream frame */ void *bitstream_out /* o : pointer to bitstream frame */
#endif
); );
#endif
#endif /* IVAS_LC3PLUS_ENC_H */ #endif /* ISAR_LC3PLUS_ENC_H */
/******************************************************************************************************
(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 <stdbool.h>
#include <assert.h>
#include <string.h>
#include "isar_lc3plus_payload.h"
#include "options.h"
#ifdef SPLIT_REND_WITH_HEAD_ROT
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
static LC3PLUS_RTP_ERR s_frame_duration_ms_from_fdi( int32_t *frame_duration_us, const LC3PLUS_RTP_FTD_FDI fdi )
{
if ( NULL == frame_duration_us )
{
return LC3PLUS_RTP_ERR_NULL_PTR;
}
switch ( fdi )
{
case LC3PLUS_RTP_FTD_FDI_2500_US:
*frame_duration_us = 2500;
break;
case LC3PLUS_RTP_FTD_FDI_5000_US:
*frame_duration_us = 5000;
break;
case LC3PLUS_RTP_FTD_FDI_10000_US:
*frame_duration_us = 10000;
break;
case LC3PLUS_RTP_FTD_FDI_RESERVED:
default:
return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
}
return LC3PLUS_RTP_ERR_NO_ERROR;
}
static LC3PLUS_RTP_ERR s_sampling_rate_hz_from_bwr( int32_t *sample_rate_hz, const LC3PLUS_RTP_FTD_BWR bwr )
{
if ( NULL == sample_rate_hz )
{
return LC3PLUS_RTP_ERR_NULL_PTR;
}
switch ( bwr )
{
case LC3PLUS_RTP_FTD_BWR_NB:
*sample_rate_hz = 8000;
break;
case LC3PLUS_RTP_FTD_BWR_WB:
*sample_rate_hz = 16000;
break;
case LC3PLUS_RTP_FTD_BWR_SSWB:
*sample_rate_hz = 24000;
break;
case LC3PLUS_RTP_FTD_BWR_SWB:
*sample_rate_hz = 32000;
break;
case LC3PLUS_RTP_FTD_BWR_FBCD:
*sample_rate_hz = 44100;
break;
case LC3PLUS_RTP_FTD_BWR_FB:
*sample_rate_hz = 48000;
break;
case LC3PLUS_RTP_FTD_BWR_FBHR:
*sample_rate_hz = 48000;
break;
case LC3PLUS_RTP_FTD_BWR_UBHR:
*sample_rate_hz = 96000;
break;
default:
return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
}
return LC3PLUS_RTP_ERR_NO_ERROR;
}
static LC3PLUS_RTP_ERR s_high_resolution_flag_from_bwr( int16_t *high_resolution_flag, const LC3PLUS_RTP_FTD_BWR bwr )
{
if ( NULL == high_resolution_flag )
{
return LC3PLUS_RTP_ERR_NULL_PTR;
}
switch ( bwr )
{
case LC3PLUS_RTP_FTD_BWR_NB:
*high_resolution_flag = 0;
break;
case LC3PLUS_RTP_FTD_BWR_WB:
*high_resolution_flag = 0;
break;
case LC3PLUS_RTP_FTD_BWR_SSWB:
*high_resolution_flag = 0;
break;
case LC3PLUS_RTP_FTD_BWR_SWB:
*high_resolution_flag = 0;
break;
case LC3PLUS_RTP_FTD_BWR_FBCD:
*high_resolution_flag = 0;
break;
case LC3PLUS_RTP_FTD_BWR_FB:
*high_resolution_flag = 0;
break;
case LC3PLUS_RTP_FTD_BWR_FBHR:
*high_resolution_flag = 1;
break;
case LC3PLUS_RTP_FTD_BWR_UBHR:
*high_resolution_flag = 1;
break;
default:
return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
}
return LC3PLUS_RTP_ERR_NO_ERROR;
}
LC3PLUS_RTP_ERR LC3PLUS_RTP_frame_data_length_get_size( int32_t *length, const LC3PLUS_RTP_FDL frameDataLengthValue )
{
if ( frameDataLengthValue == LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA || frameDataLengthValue == LC3PLUS_RTP_FDL_SPEECH_BAD || frameDataLengthValue == LC3PLUS_RTP_FDL_SPEECH_SID )
{
*length = 1;
}
else if ( frameDataLengthValue >= LC3PLUS_RTP_FDL_LENGTH_1_MIN && frameDataLengthValue <= LC3PLUS_RTP_FDL_LENGTH_1_MAX )
{
*length = 1;
}
else if ( frameDataLengthValue >= LC3PLUS_RTP_FDL_LENGTH_2_MIN && frameDataLengthValue <= LC3PLUS_RTP_FDL_LENGTH_2_MAX )
{
*length = 2;
}
else if ( frameDataLengthValue >= LC3PLUS_RTP_FDL_LENGTH_3_MIN && frameDataLengthValue <= LC3PLUS_RTP_FDL_LENGTH_3_MAX )
{
*length = 3;
}
else
{
return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
}
return LC3PLUS_RTP_ERR_NO_ERROR;
}
static LC3PLUS_RTP_ERR s_frame_data_length_pack( const LC3PLUS_RTP_FDL frameDataLengthValue, uint8_t *dst )
{
int32_t frame_data_length_size;
LC3PLUS_RTP_ERR err;
if ( NULL == dst )
{
return LC3PLUS_RTP_ERR_NULL_PTR;
}
err = LC3PLUS_RTP_frame_data_length_get_size( &frame_data_length_size, frameDataLengthValue );
if ( err != LC3PLUS_RTP_ERR_NO_ERROR )
{
return err;
}
if ( 1 == frame_data_length_size )
{
*dst++ = frameDataLengthValue >> 0 & LC3PLUS_RTP_FDL_EXTENSION_VALUE;
}
else if ( 2 == frame_data_length_size )
{
const int32_t frameDataLengthValueToWrite = frameDataLengthValue - LC3PLUS_RTP_FDL_EXTENSION_VALUE;
*dst++ = LC3PLUS_RTP_FDL_EXTENSION_VALUE;
*dst = frameDataLengthValueToWrite >> 0 & LC3PLUS_RTP_FDL_EXTENSION_VALUE;
}
else if ( 3 == frame_data_length_size )
{
const int32_t frameDataLengthValueToWrite = frameDataLengthValue - ( 2 * LC3PLUS_RTP_FDL_EXTENSION_VALUE );
*dst++ = LC3PLUS_RTP_FDL_EXTENSION_VALUE;
*dst++ = LC3PLUS_RTP_FDL_EXTENSION_VALUE;
*dst = frameDataLengthValueToWrite >> 0 & LC3PLUS_RTP_FDL_EXTENSION_VALUE;
}
return LC3PLUS_RTP_ERR_NO_ERROR;
}
static int32_t s_get_size_from_fdl( const LC3PLUS_RTP_FDL fdl )
{
if ( fdl >= LC3PLUS_RTP_FDL_LENGTH_1_MIN && fdl <= LC3PLUS_RTP_FDL_LENGTH_3_MAX )
{
return fdl;
}
return 0;
}
static bool s_fdl_is_magic_value( const LC3PLUS_RTP_FDL fdl )
{
if ( fdl == LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA || fdl == LC3PLUS_RTP_FDL_SPEECH_SID || fdl == LC3PLUS_RTP_FDL_SPEECH_BAD )
{
return true;
}
return false;
}
static bool s_fdl_value_is_valid_request( const LC3PLUS_RTP_FDL fdl_request )
{
/* LC3PLUS_RTP_FDL_SPEECH_SID && LC3PLUS_RTP_FDL_SPEECH_SID are not valid values for the FDL request */
if ( fdl_request == LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA || ( fdl_request >= LC3PLUS_RTP_FDL_LENGTH_1_MIN && fdl_request <= LC3PLUS_RTP_FDL_LENGTH_3_MAX ) )
{
return true;
}
return false;
}
static LC3PLUS_RTP_ERR s_frame_data_length_parse( LC3PLUS_RTP_FDL *frame_data_length_value, const uint8_t *src, const size_t remaining_capacity )
{
int32_t frame_data_length_size;
LC3PLUS_RTP_ERR err;
if ( NULL == src || NULL == frame_data_length_value || remaining_capacity < 1 )
{
return LC3PLUS_RTP_ERR_NULL_PTR;
}
if ( remaining_capacity > 2 && LC3PLUS_RTP_FDL_EXTENSION_VALUE == *src && LC3PLUS_RTP_FDL_EXTENSION_VALUE == *( src + 1 ) )
{
*frame_data_length_value = *( src + 2 ) + 2 * LC3PLUS_RTP_FDL_EXTENSION_VALUE;
}
else if ( remaining_capacity > 1 && LC3PLUS_RTP_FDL_EXTENSION_VALUE == *src )
{
*frame_data_length_value = *( src + 1 ) + 1 * LC3PLUS_RTP_FDL_EXTENSION_VALUE;
}
else if ( remaining_capacity > 0 )
{
*frame_data_length_value = *src << 0;
}
else
{
return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
}
/* sanity check */
err = LC3PLUS_RTP_frame_data_length_get_size( &frame_data_length_size, *frame_data_length_value );
if ( err != LC3PLUS_RTP_ERR_NO_ERROR )
{
return err;
}
return LC3PLUS_RTP_ERR_NO_ERROR;
}
static LC3PLUS_RTP_ERR s_parse_ftd( const uint8_t *p_read, LC3PLUS_RTP_FTD *receiver_ftd, int32_t *num_bytes_read, const size_t remaining_capacity )
{
int32_t frame_data_block_size;
LC3PLUS_RTP_FDL fdl;
LC3PLUS_RTP_ERR err;
if ( NULL == p_read || NULL == receiver_ftd || NULL == num_bytes_read || remaining_capacity < LC3PLUS_RTP_FTD_MIN_SIZE )
{
return LC3PLUS_RTP_ERR_NULL_PTR;
}
*num_bytes_read = 0;
receiver_ftd->fc = 0;
receiver_ftd->fdi = 0;
receiver_ftd->bwr = 0;
receiver_ftd->h = 0;
receiver_ftd->fc |= *p_read & LC3PLUS_RTP_FTD_FC_MASK;
receiver_ftd->fdi |= ( *p_read & LC3PLUS_RTP_FTD_FDI_MASK );
receiver_ftd->bwr |= ( *p_read & LC3PLUS_RTP_FTD_BWR_MASK );
receiver_ftd->h |= ( *p_read & LC3PLUS_RTP_FTD_H_MASK );
p_read++;
*num_bytes_read = 1;
err = s_frame_data_length_parse( &fdl, p_read, remaining_capacity - *num_bytes_read );
if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
{
return err;
}
frame_data_block_size = s_get_size_from_fdl( fdl );
receiver_ftd->frame_data_length = frame_data_block_size;
int32_t length_field_size;
err = LC3PLUS_RTP_frame_data_length_get_size( &length_field_size, receiver_ftd->frame_data_length );
if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
{
return err;
}
*num_bytes_read += length_field_size;
return LC3PLUS_RTP_ERR_NO_ERROR;
}
LC3PLUS_RTP_ERR LC3PLUS_RTP_payload_serialize(
uint8_t *serialized_buffer,
const size_t serialized_buffer_capacity,
size_t *packed_buffer_actual_size,
const LC3PLUS_RTP_FDL fdl_request,
LC3PLUS_RTP_FTD *sender_ftds,
const size_t sender_ftds_num )
{
LC3PLUS_RTP_ERR err;
uint8_t *p_write = serialized_buffer;
uint32_t i;
int32_t bytes_written = 0;
int32_t lc3plus_frame_size_sum;
uint8_t *p_frame_data;
int32_t fdl_request_length;
if ( NULL == serialized_buffer || NULL == packed_buffer_actual_size || NULL == sender_ftds )
{
return LC3PLUS_RTP_ERR_NULL_PTR;
}
*packed_buffer_actual_size = 0;
err = LC3PLUS_RTP_frame_data_length_get_size( &fdl_request_length, fdl_request );
if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
{
return err;
}
if ( !s_fdl_value_is_valid_request( fdl_request ) )
{
return LC3PLUS_RTP_ERR_INVALID_FDL_REQUEST;
}
if ( (int32_t) serialized_buffer_capacity < bytes_written + fdl_request_length )
{
return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
}
err = s_frame_data_length_pack( fdl_request, p_write );
if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
{
return err;
}
bytes_written += fdl_request_length;
p_write += bytes_written;
for ( i = 0; i < sender_ftds_num; ++i )
{
/* only the last ftd may have the LC3PLUS_RTP_FTD_FC_LAST_OVERALL value */
if ( sender_ftds[i].fc == LC3PLUS_RTP_FTD_FC_LAST_OVERALL && i != ( sender_ftds_num - 1 ) )
{
return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
}
/* the last ftd must have the LC3PLUS_RTP_FTD_FC_LAST_OVERALL value */
if ( sender_ftds[i].fc != LC3PLUS_RTP_FTD_FC_LAST_OVERALL && i == ( sender_ftds_num - 1 ) )
{
return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
}
if ( (int32_t) serialized_buffer_capacity < bytes_written + LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL )
{
return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
}
*p_write = 0x00;
*p_write |= LC3PLUS_RTP_FTD_FC_MASK & (uint8_t) sender_ftds[i].fc;
*p_write |= LC3PLUS_RTP_FTD_FDI_MASK & (uint8_t) sender_ftds[i].fdi;
*p_write |= LC3PLUS_RTP_FTD_BWR_MASK & (uint8_t) sender_ftds[i].bwr;
*p_write |= LC3PLUS_RTP_FTD_H_MASK & (uint8_t) sender_ftds[i].h;
p_write++;
bytes_written += LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL;
int32_t fdl_length;
err = LC3PLUS_RTP_frame_data_length_get_size( &fdl_length, sender_ftds[i].frame_data_length );
if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
{
return err;
}
if ( (int32_t) serialized_buffer_capacity < bytes_written + fdl_length )
{
return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
}
err = s_frame_data_length_pack( sender_ftds[i].frame_data_length, p_write );
if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
{
return err;
}
p_write += fdl_length;
bytes_written += fdl_length;
}
lc3plus_frame_size_sum = 0;
p_frame_data = serialized_buffer + bytes_written;
for ( i = 0; i < sender_ftds_num; ++i )
{
sender_ftds[i].frame_data = p_frame_data;
p_frame_data += sender_ftds[i].frame_data_length;
lc3plus_frame_size_sum += sender_ftds[i].frame_data_length;
}
*packed_buffer_actual_size = bytes_written + lc3plus_frame_size_sum;
assert( *packed_buffer_actual_size <= serialized_buffer_capacity );
return LC3PLUS_RTP_ERR_NO_ERROR;
}
static LC3PLUS_RTP_ERR s_ftds_parse(
LC3PLUS_RTP_FTD *receiver_ftds,
const int32_t receiver_ftds_num_max,
int16_t *receiver_ftds_num,
uint8_t *serialized_buffer,
const size_t serialized_buffer_size )
{
int32_t diff;
uint8_t *p_read;
uint32_t ftds_offset_sum = 0;
int16_t i;
LC3PLUS_RTP_ERR error;
int32_t frame_offset_counter;
int32_t size;
p_read = serialized_buffer;
if ( NULL == receiver_ftds || NULL == receiver_ftds_num || NULL == serialized_buffer )
{
return LC3PLUS_RTP_ERR_NULL_PTR;
}
if ( 0 == serialized_buffer_size )
{
return LC3PLUS_RTP_ERR_EMPTY_TOC;
}
if ( receiver_ftds_num_max <= 0 )
{
return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
}
{
int32_t num_bytes_read_sum = 0;
const int32_t min_num_bytes_per_ftd = 2;
int16_t receiver_ftds_index = 0;
bool another_ftd = true;
int32_t num_bytes_read_per_ftd;
while ( another_ftd )
{
if ( (int32_t) serialized_buffer_size < min_num_bytes_per_ftd )
{
return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
}
if ( num_bytes_read_sum >= (int32_t) serialized_buffer_size - min_num_bytes_per_ftd )
{
return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
}
num_bytes_read_per_ftd = 0;
error = s_parse_ftd( p_read, &receiver_ftds[receiver_ftds_index], &num_bytes_read_per_ftd, serialized_buffer_size - num_bytes_read_sum );
if ( LC3PLUS_RTP_ERR_NO_ERROR != error )
{
return error;
}
p_read += num_bytes_read_per_ftd;
num_bytes_read_sum += num_bytes_read_per_ftd;
if ( receiver_ftds[receiver_ftds_index].fc == LC3PLUS_RTP_FTD_FC_RESERVED )
{
return LC3PLUS_RTP_ERR_INVALID_BITSTREAM;
}
else if ( receiver_ftds[receiver_ftds_index].fc == LC3PLUS_RTP_FTD_FC_LAST_OVERALL )
{
another_ftd = false;
}
if ( another_ftd )
{
if ( receiver_ftds_index >= receiver_ftds_num_max )
{
return LC3PLUS_RTP_ERR_NOT_ENOUGH_FTDS_ALLOCATED;
}
( receiver_ftds_index )++;
}
}
*receiver_ftds_num = receiver_ftds_index + 1;
}
/* set frame-data pointers into serialized_buffer */
for ( i = 0; i < *receiver_ftds_num; ++i )
{
error = LC3PLUS_RTP_frame_data_length_get_size( &size, receiver_ftds[i].frame_data_length );
if ( error != LC3PLUS_RTP_ERR_NO_ERROR )
{
return error;
}
ftds_offset_sum += LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL + size;
}
frame_offset_counter = 0;
for ( i = 0; i < *receiver_ftds_num; ++i )
{
if ( s_fdl_is_magic_value( receiver_ftds[i].frame_data_length ) )
{
receiver_ftds[i].frame_data = NULL;
}
else
{
receiver_ftds[i].frame_data = serialized_buffer + ftds_offset_sum + frame_offset_counter;
frame_offset_counter += receiver_ftds[i].frame_data_length;
}
}
if ( ftds_offset_sum + frame_offset_counter != serialized_buffer_size )
{
/* parsed content & size n bytes of input buffer do not line up */
/* if the buffer capacity is larger and the remaining bytes are zero, we don't treat this as an error since it's due to the IVAS-Split rendering zero padding */
diff = serialized_buffer_size - ( ftds_offset_sum + frame_offset_counter );
if ( diff < 0 )
{
return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
}
/* verify that all bytes are zero */
p_read += frame_offset_counter;
for ( i = 0; i < diff; ++i )
{
if ( *p_read != 0 )
{
/* non-zero byte in padding region */
return LC3PLUS_RTP_ERR_NONZERO_PADDING_BYTES;
}
p_read++;
}
}
return LC3PLUS_RTP_ERR_NO_ERROR;
}
LC3PLUS_RTP_ERR LC3PLUS_RTP_payload_deserialize(
LC3PLUS_RTP_PAYLOAD *payload,
uint8_t *serialized_buffer,
const size_t serialized_buffer_size )
{
int32_t new_frame_duration_us;
int32_t new_sampling_rate_hz;
int16_t new_high_resolution_flag;
int16_t i = 0;
int16_t channel_id = 0;
int16_t media_time_id = 0;
const int16_t invalid_value = -1;
int16_t media_times_per_channel[LC3PLUS_RTP_PAYLOAD_MAX_NUM_CHANNELS];
int16_t channels_per_media_time[LC3PLUS_RTP_PAYLOAD_MAX_NUM_MEDIA_TIMES];
LC3PLUS_RTP_ERR err;
if ( NULL == payload || NULL == serialized_buffer )
{
return LC3PLUS_RTP_ERR_NULL_PTR;
}
if ( 0 == serialized_buffer_size )
{
return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
}
for ( media_time_id = 0; media_time_id < LC3PLUS_RTP_PAYLOAD_MAX_NUM_MEDIA_TIMES; ++media_time_id )
{
channels_per_media_time[media_time_id] = invalid_value;
}
media_time_id = 0;
for ( channel_id = 0; channel_id < LC3PLUS_RTP_PAYLOAD_MAX_NUM_CHANNELS; ++channel_id )
{
media_times_per_channel[channel_id] = invalid_value;
}
channel_id = 0;
err = s_frame_data_length_parse( &payload->fdl_request, serialized_buffer, serialized_buffer_size );
if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
{
return err;
}
int32_t fdl_request_length;
err = LC3PLUS_RTP_frame_data_length_get_size( &fdl_request_length, payload->fdl_request );
if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
{
return err;
}
if ( !s_fdl_value_is_valid_request( payload->fdl_request ) )
{
return LC3PLUS_RTP_ERR_INVALID_FDL_REQUEST;
}
err = s_ftds_parse( payload->ftds, sizeof( payload->ftds ) / sizeof( LC3PLUS_RTP_FTD ), &payload->num_ftds, serialized_buffer + fdl_request_length, serialized_buffer_size - fdl_request_length );
if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
{
return err;
}
if ( 0 == payload->num_ftds )
{
return LC3PLUS_RTP_ERR_GENERIC_ERROR;
}
/* verify shared setting between all FTDs [samplerate, frame_duration, channel count] */
/* initialize on the first FTD, use this as reference */
err = s_frame_duration_ms_from_fdi( &payload->frame_duration_us, payload->ftds[0].fdi );
if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
{
return err;
}
err = s_sampling_rate_hz_from_bwr( &payload->sampling_rate_hz, payload->ftds[0].bwr );
if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
{
return err;
}
err = s_high_resolution_flag_from_bwr( &payload->high_resolution_enabled, payload->ftds[0].bwr );
if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
{
return err;
}
payload->num_channels = 0;
payload->num_media_times = 0;
for ( i = 0; i < payload->num_ftds; ++i )
{
if ( payload->ftds[i].h != LC3PLUS_RTP_FTD_H_PRIMARY )
{
/* not implemented */
return LC3PLUS_RTP_ERR_NOT_IMPLEMENTED;
}
err = s_frame_duration_ms_from_fdi( &new_frame_duration_us, payload->ftds[i].fdi );
if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
{
return err;
}
if ( payload->frame_duration_us != new_frame_duration_us )
{
/* mixed frame durations not supported */
return LC3PLUS_RTP_ERR_UNSUPPORTED_CONFIGURATION;
}
err = s_sampling_rate_hz_from_bwr( &new_sampling_rate_hz, payload->ftds[i].bwr );
if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
{
return err;
}
if ( payload->sampling_rate_hz != new_sampling_rate_hz )
{
/* mixed sampling frequencies not supported */
return LC3PLUS_RTP_ERR_UNSUPPORTED_CONFIGURATION;
}
err = s_high_resolution_flag_from_bwr( &new_high_resolution_flag, payload->ftds[i].bwr );
if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
{
return err;
}
if ( payload->high_resolution_enabled != new_high_resolution_flag )
{
/* mixed high resolution mode not supported */
return LC3PLUS_RTP_ERR_UNSUPPORTED_CONFIGURATION;
}
switch ( payload->ftds[i].fc )
{
case LC3PLUS_RTP_FTD_FC_LAST_OVERALL:
channels_per_media_time[media_time_id]++;
media_times_per_channel[channel_id]++;
channel_id = 0;
media_time_id = 0;
break;
case LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL:
media_times_per_channel[channel_id]++;
channels_per_media_time[media_time_id]++;
channel_id++;
break;
case LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME:
media_times_per_channel[channel_id]++;
channels_per_media_time[media_time_id]++;
channel_id = 0;
media_time_id++;
break;
case LC3PLUS_RTP_FTD_FC_RESERVED:
default:
return LC3PLUS_RTP_ERR_INVALID_BITSTREAM;
}
}
{
int32_t valid_num_media_times_per_channel;
int32_t iCh;
/* check whether all channels exist for each media time */
if ( media_times_per_channel[0] == invalid_value )
{
return LC3PLUS_RTP_ERR_NOT_IMPLEMENTED;
}
valid_num_media_times_per_channel = media_times_per_channel[0];
for ( iCh = 0; iCh < LC3PLUS_RTP_PAYLOAD_MAX_NUM_CHANNELS; ++iCh )
{
if ( media_times_per_channel[iCh] == invalid_value )
{
break;
}
if ( valid_num_media_times_per_channel != media_times_per_channel[iCh] )
{
return LC3PLUS_RTP_ERR_NOT_IMPLEMENTED;
}
}
}
{
/* whether all media times exist for each channel */
int32_t iMediaTime;
int32_t valid_num_channels_per_media_time;
if ( channels_per_media_time[0] == invalid_value )
{
return LC3PLUS_RTP_ERR_NOT_IMPLEMENTED;
}
valid_num_channels_per_media_time = channels_per_media_time[0];
for ( iMediaTime = 0; iMediaTime < LC3PLUS_RTP_PAYLOAD_MAX_NUM_MEDIA_TIMES; ++iMediaTime )
{
if ( channels_per_media_time[iMediaTime] == invalid_value )
{
break;
}
if ( valid_num_channels_per_media_time != channels_per_media_time[iMediaTime] )
{
return LC3PLUS_RTP_ERR_NOT_IMPLEMENTED;
}
}
}
/* convert zero-index to count */
payload->num_channels = channels_per_media_time[0] + 1;
payload->num_media_times = media_times_per_channel[0] + 1;
/* verify that all media times have the same number of channels, partial packets are not supported */
if ( payload->num_ftds != payload->num_channels * payload->num_media_times )
{
return LC3PLUS_RTP_ERR_GENERIC_ERROR;
}
return LC3PLUS_RTP_ERR_NO_ERROR;
}
LC3PLUS_RTP_ERR LC3PLUS_RTP_ftd_bwr_from_samplerate( LC3PLUS_RTP_FTD_BWR *bwr, const int32_t sampling_rate, const int32_t high_res_enabled )
{
if ( NULL == bwr )
{
return LC3PLUS_RTP_ERR_NULL_PTR;
}
switch ( sampling_rate )
{
case 8000:
if ( high_res_enabled )
{
return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
}
*bwr = LC3PLUS_RTP_FTD_BWR_NB;
return LC3PLUS_RTP_ERR_NO_ERROR;
case 16000:
if ( high_res_enabled )
{
return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
}
*bwr = LC3PLUS_RTP_FTD_BWR_WB;
return LC3PLUS_RTP_ERR_NO_ERROR;
case 24000:
if ( high_res_enabled )
{
return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
}
*bwr = LC3PLUS_RTP_FTD_BWR_SSWB;
return LC3PLUS_RTP_ERR_NO_ERROR;
case 32000:
if ( high_res_enabled )
{
return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
}
*bwr = LC3PLUS_RTP_FTD_BWR_SWB;
return LC3PLUS_RTP_ERR_NO_ERROR;
case 44100:
if ( high_res_enabled )
{
return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
}
*bwr = LC3PLUS_RTP_FTD_BWR_FBCD;
return LC3PLUS_RTP_ERR_NO_ERROR;
case 48000:
if ( 0 == high_res_enabled )
{
*bwr = LC3PLUS_RTP_FTD_BWR_FB;
return LC3PLUS_RTP_ERR_NO_ERROR;
}
else
{
*bwr = LC3PLUS_RTP_FTD_BWR_FBHR;
return LC3PLUS_RTP_ERR_NO_ERROR;
}
case 96000:
if ( 0 == high_res_enabled )
{
return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
}
*bwr = LC3PLUS_RTP_FTD_BWR_UBHR;
return LC3PLUS_RTP_ERR_NO_ERROR;
default:
break;
}
return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
}
LC3PLUS_RTP_ERR LC3PLUS_RTP_ftd_fdi_from_frame_duration_us( LC3PLUS_RTP_FTD_FDI *fdi, const int32_t frame_duration_us )
{
if ( NULL == fdi )
{
return LC3PLUS_RTP_ERR_NULL_PTR;
}
switch ( frame_duration_us )
{
case 2500:
*fdi = LC3PLUS_RTP_FTD_FDI_2500_US;
return LC3PLUS_RTP_ERR_NO_ERROR;
case 5000:
*fdi = LC3PLUS_RTP_FTD_FDI_5000_US;
return LC3PLUS_RTP_ERR_NO_ERROR;
case 10000:
*fdi = LC3PLUS_RTP_FTD_FDI_10000_US;
return LC3PLUS_RTP_ERR_NO_ERROR;
default:
break;
}
return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
}
#endif /* ISAR_BITSTREAM_UPDATE_LC3PLUS */
#endif /* SPLIT_REND_WITH_HEAD_ROT */
/******************************************************************************************************
(C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
contributors to this repository. All Rights Reserved.
This software is protected by copyright law and by international treaties.
The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
contributors to this repository retain full ownership rights in their respective contributions in
the software. This notice grants no license of any kind, including but not limited to patent
license, nor is any license granted by implication, estoppel or otherwise.
Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
contributions.
This software is provided "AS IS", without any express or implied warranties. The software is in the
development stage. It is intended exclusively for experts who have experience with such software and
solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
and fitness for a particular purpose are hereby disclaimed and excluded.
Any dispute, controversy or claim arising under or in relation to providing this software shall be
submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
the United Nations Convention on Contracts on the International Sales of Goods.
*******************************************************************************************************/
#ifndef ISAR_LC3PLUS_PAYLOAD_H
#define ISAR_LC3PLUS_PAYLOAD_H
#include <stdint.h>
#include <stddef.h>
#include "lc3.h"
#include "options.h"
#ifdef SPLIT_REND_WITH_HEAD_ROT
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
/* Implementation of the "B.2.6 Table of contents" part of the RTP payload format
* for LC3plus as specified in ETSI TS 103 634. */
typedef enum LC3PLUS_RTP_ERR
{
LC3PLUS_RTP_ERR_NO_ERROR,
LC3PLUS_RTP_ERR_NULL_PTR,
LC3PLUS_RTP_ERR_INVALID_PARAMETERS,
LC3PLUS_RTP_ERR_EMPTY_TOC,
LC3PLUS_RTP_ERR_NOT_IMPLEMENTED,
LC3PLUS_RTP_ERR_UNSUPPORTED_CONFIGURATION,
LC3PLUS_RTP_ERR_INVALID_BITSTREAM,
LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE,
LC3PLUS_RTP_ERR_NOT_ENOUGH_FTDS_ALLOCATED,
LC3PLUS_RTP_ERR_INVALID_FDL_REQUEST,
LC3PLUS_RTP_ERR_NONZERO_PADDING_BYTES,
LC3PLUS_RTP_ERR_GENERIC_ERROR
} LC3PLUS_RTP_ERR;
/*
* The content of the FTD is shown in Figure B.6.
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |FC |FDI| BWR |H| FDL1 | (FDL2) | (FDL3) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/* FC (2 bits):
* Frame and Channel (FC) indicator for subsequent frame data (if available). The meaning of the FC
* indicator is shown in Table B.2. The FC value defines the media time stamp (in integer increments
* of TSI) and the channel counter (CC, starting from 1 for the first channel) for the subsequent
* FTD (if available). */
typedef enum LC3PLUS_RTP_FTD_FC
{
LC3PLUS_RTP_FTD_FC_LAST_OVERALL = 0x00, /* Last FDL in ToC, no FDL follows the current FDL */
LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL = 0x01, /* The next FDL is for the next channel for the same media time */
LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME = 0x02, /* The next FDL is for first channel for next media time, channel counter is reset */
LC3PLUS_RTP_FTD_FC_RESERVED = 0x03, /* Reserved */
} LC3PLUS_RTP_FTD_FC;
#define LC3PLUS_RTP_FTD_FC_MASK 0x03
/* FDI (2 bits):
* Frame Duration Index, with encoding as shown in Table B.3. The FDI shall be static for a given
* payload type during the session. The FDI also dictates the TSI, needed for deriving the media
* time in case of more than one frame in the payload. */
typedef enum LC3PLUS_RTP_FTD_FDI
{
LC3PLUS_RTP_FTD_FDI_2500_US = 0x00,
LC3PLUS_RTP_FTD_FDI_5000_US = 0x04,
LC3PLUS_RTP_FTD_FDI_10000_US = 0x08,
LC3PLUS_RTP_FTD_FDI_RESERVED = 0x0C,
} LC3PLUS_RTP_FTD_FDI;
#define LC3PLUS_RTP_FTD_FDI_MASK 0x0C
LC3PLUS_RTP_ERR LC3PLUS_RTP_ftd_fdi_from_frame_duration_us( LC3PLUS_RTP_FTD_FDI *fdi, const int32_t frame_duration_us );
/* BWR (3 bits):
* Bandwidth and resolution combination used by the codec is jointly encoded into a bandwidth and
* resolution (BWR) index. The BWR index is encoded as shown in Table B.4. The BWR encoding is
* defined in Table B.4. The BWR index shall be static for a given payload type during the session. */
typedef enum LC3PLUS_RTP_FTD_BWR
{
LC3PLUS_RTP_FTD_BWR_NB = 0x00,
LC3PLUS_RTP_FTD_BWR_WB = 0x10,
LC3PLUS_RTP_FTD_BWR_SSWB = 0x20,
LC3PLUS_RTP_FTD_BWR_SWB = 0x30,
LC3PLUS_RTP_FTD_BWR_FBCD = 0x40,
LC3PLUS_RTP_FTD_BWR_FB = 0x50,
LC3PLUS_RTP_FTD_BWR_FBHR = 0x60,
LC3PLUS_RTP_FTD_BWR_UBHR = 0x70,
} LC3PLUS_RTP_FTD_BWR;
#define LC3PLUS_RTP_FTD_BWR_MASK 0x70
LC3PLUS_RTP_ERR LC3PLUS_RTP_ftd_bwr_from_samplerate( LC3PLUS_RTP_FTD_BWR *bwr, const int32_t sampling_rate, const int32_t high_res_enabled );
/* H (1 bit):
* Indicates whether the corresponding frame is a normal frame (primary encoding) or a helper frame
* (secondary encoding). 0 indicates a primary frame, 1 indicates secondary (redundant) frame */
typedef enum LC3PLUS_RTP_FTD_H
{
LC3PLUS_RTP_FTD_H_PRIMARY = 0x00,
LC3PLUS_RTP_FTD_H_SECONDARY = 0x80,
} LC3PLUS_RTP_FTD_H;
#define LC3PLUS_RTP_FTD_H_MASK 0x80
typedef enum LC3PLUS_RTP_FDL
{
LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA = 0,
LC3PLUS_RTP_FDL_SPEECH_BAD = 1,
LC3PLUS_RTP_FDL_SPEECH_SID = 2,
LC3PLUS_RTP_FDL_RESERVED_MIN = 3,
LC3PLUS_RTP_FDL_RESERVED_MAX = 19,
LC3PLUS_RTP_FDL_LENGTH_1_MIN = 20,
LC3PLUS_RTP_FDL_LENGTH_1_MAX = 254,
LC3PLUS_RTP_FDL_LENGTH_2_MIN = 255,
LC3PLUS_RTP_FDL_LENGTH_2_MAX = 509,
LC3PLUS_RTP_FDL_LENGTH_3_MIN = 510,
LC3PLUS_RTP_FDL_LENGTH_3_MAX = 765
} LC3PLUS_RTP_FDL;
/* value used to indicate that the Frame Data Length (FDL) extends to the next byte */
#define LC3PLUS_RTP_FDL_EXTENSION_VALUE 0xFF
typedef struct LC3PLUS_RTP_FTD
{
LC3PLUS_RTP_FTD_FC fc;
LC3PLUS_RTP_FTD_FDI fdi;
LC3PLUS_RTP_FTD_BWR bwr;
LC3PLUS_RTP_FTD_H h;
uint8_t *frame_data;
LC3PLUS_RTP_FDL frame_data_length;
} LC3PLUS_RTP_FTD;
#define LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL 1
#define LC3PLUS_RTP_FDL_MIN_LENGTH 1
#define LC3PLUS_RTP_FTD_MIN_SIZE ( LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL + LC3PLUS_RTP_FDL_MIN_LENGTH )
/*! Serialize the sender_ftds structs and fdl_request into a linear compact buffer
* @param[out] serialized_buffer pointer to the start of the memory location where the serialized buffer will be written to
* @param[in] serialized_buffer_capacity capacity of the serialized_buffer in bytes
* @param[out] packed_buffer_actual_size actually used size of in bytes of the packed_buffer (<=serialized_buffer_capacity)
* @param[in] fdl_request frame data length request
* @param[in,out] sender_ftds the function will overwrite the frame_data pointer with the correct memory location in
* the packed_buffer (so it can subsequently be used as input for the LC3plus encode call)
* @param[in] sender_ftds_num number of sender_ftds
* @return LC3PLUS_RTP_ERR_NO_ERROR in case of success */
LC3PLUS_RTP_ERR LC3PLUS_RTP_payload_serialize(
uint8_t *serialized_buffer,
const size_t serialized_buffer_capacity,
size_t *packed_buffer_actual_size,
const LC3PLUS_RTP_FDL fdl_request,
LC3PLUS_RTP_FTD *sender_ftds,
const size_t sender_ftds_num );
/*! Get size of the frame data length field for a certain frame data length value in bytes.
* @param[out] length size of the frame data length field in bytes [1,2,3]
* @param[in] frameDataLengthValue frame data length value
* @return LC3PLUS_RTP_ERR_NO_ERROR in case of success */
LC3PLUS_RTP_ERR LC3PLUS_RTP_frame_data_length_get_size( int32_t *length, const LC3PLUS_RTP_FDL frameDataLengthValue );
#define LC3PLUS_RTP_PAYLOAD_MAX_NUM_CHANNELS 16
#define LC3PLUS_RTP_PAYLOAD_MAX_NUM_MEDIA_TIMES 8 /* max ivas frame duration/min lc3plus frame duration: 20000/2500 */
#define LC3PLUS_RTP_PAYLOAD_MAX_NUM_FTDS LC3PLUS_RTP_PAYLOAD_MAX_NUM_CHANNELS *LC3PLUS_RTP_PAYLOAD_MAX_NUM_MEDIA_TIMES
typedef struct LC3PLUS_RTP_PAYLOAD_CONFIG
{
/* frame duration in us shared among all FTDs */
int32_t frame_duration_us;
/* high resolution flag shared among all FTDs */
int16_t high_resolution_enabled;
/* sampling frequency shared among all FTDs */
int32_t sampling_rate_hz;
/* number of individual channels in the payload */
int16_t num_channels;
/* number of individual media times in the payload */
int16_t num_media_times;
/* frame data length request */
LC3PLUS_RTP_FDL fdl_request;
/* FTD data with pointer to raw frame data */
LC3PLUS_RTP_FTD ftds[LC3PLUS_RTP_PAYLOAD_MAX_NUM_FTDS];
/* actual number of ftds */
int16_t num_ftds;
} LC3PLUS_RTP_PAYLOAD;
/*! Deserialized a serialized buffer into a LC3PLUS_RTP_PAYLOAD struct
* @param payload pointer to target LC3PLUS_RTP_PAYLOAD object. Note: frame_data pointers in the struct will point to the respective memory locations in the serialized_buffer.
* @param serialized_buffer pointer to the start of the serialized input buffer
* @param serialized_buffer_size size of the serialized input buffer in bytes
* @return LC3PLUS_RTP_ERR_NO_ERROR in case of success */
LC3PLUS_RTP_ERR LC3PLUS_RTP_payload_deserialize(
LC3PLUS_RTP_PAYLOAD *payload,
uint8_t *serialized_buffer,
const size_t serialized_buffer_size );
#endif /* ISAR_BITSTREAM_UPDATE_LC3PLUS */
#endif /* #ifdef SPLIT_REND_WITH_HEAD_ROT */
#endif /* ISAR_LC3PLUS_PAYLOAD_H */
...@@ -33,11 +33,11 @@ ...@@ -33,11 +33,11 @@
#include <stdint.h> #include <stdint.h>
#include "options.h" #include "options.h"
#ifdef SPLIT_REND_WITH_HEAD_ROT #ifdef SPLIT_REND_WITH_HEAD_ROT
#include "ivas_lcld_prot.h" #include "isar_lcld_prot.h"
#include "ivas_lcld_rom_tables.h" #include "isar_rom_lcld_tables.h"
#include "prot.h" #include "prot.h"
#include <assert.h> #include <assert.h>
#include "ivas_prot_rend.h" #include "isar_prot.h"
#include "wmc_auto.h" #include "wmc_auto.h"
...@@ -93,6 +93,7 @@ struct LCLD_DECODER ...@@ -93,6 +93,7 @@ struct LCLD_DECODER
int32_t ***pppiAlloc; int32_t ***pppiAlloc;
int32_t iAllocOffset; int32_t iAllocOffset;
int32_t iRealOnlyOut;
int32_t ***pppiLCLDSignReal; int32_t ***pppiLCLDSignReal;
int32_t ***pppiLCLDSignImag; int32_t ***pppiLCLDSignImag;
...@@ -105,14 +106,14 @@ struct LCLD_DECODER ...@@ -105,14 +106,14 @@ struct LCLD_DECODER
NoiseGen *psNoiseGen; NoiseGen *psNoiseGen;
}; };
static void CreateDecodeTable( LCLDDecoder *psLCLDDecoder, int32_t num, const uint16_t ( *ppuiEncTable )[2], int32_t iSize, int32_t iReadLength, uint32_t *iTables ); static void CreateDecodeTable( LCLDDecoder *psLCLDDecoder, const int32_t num, const uint16_t ( *ppuiEncTable )[2], const int32_t iSize, const int32_t iReadLength, uint32_t *iTables );
static TableNode *CreateTableList( int32_t iReadLength ); static TableNode *CreateTableList( const int32_t iReadLength );
static void DeleteTableList( TableList *ptable_list, int32_t iTables ); static void DeleteTableList( TableList *ptable_list, int32_t iTables );
static TableNode *GetNextTable( int32_t iIndex, TableList *table_list, TableNode *poParent, int32_t iReadLength, uint32_t *iTablesCreated ); static TableNode *GetNextTable( const int32_t iIndex, TableList *table_list, TableNode *poParent, const int32_t iReadLength, uint32_t *iTablesCreated );
static void AddcodeTableList( TableList *ptable_list, int32_t iLength, int32_t iCode, int32_t iCodeIndex, int32_t iReadLength, uint32_t *iTables ); static void AddcodeTableList( TableList *ptable_list, const int32_t iLength, const int32_t iCode, const int32_t iCodeIndex, const int32_t iReadLength, uint32_t *iTables );
static void CompleteTables( LCLDDecoder *psLCLDDecoder, int32_t n, TableList *ptable_list, int32_t iReadLength, int32_t iTablesCreated ); static void CompleteTables( LCLDDecoder *psLCLDDecoder, const int32_t n, TableList *ptable_list, const int32_t iReadLength, const int32_t iTablesCreated );
static TableNode *CreateTableList( int32_t iReadLength ) static TableNode *CreateTableList( const int32_t iReadLength )
{ {
int32_t n; int32_t n;
int32_t iMaxTables; int32_t iMaxTables;
...@@ -172,7 +173,7 @@ static void DeleteTableList( TableList *ptable_list, int32_t iTables ) ...@@ -172,7 +173,7 @@ static void DeleteTableList( TableList *ptable_list, int32_t iTables )
free( ptable_list ); free( ptable_list );
} }
} }
static TableNode *GetNextTable( int32_t iIndex, TableList *table_list, TableNode *poParent, int32_t iReadLength, uint32_t *iTablesCreated ) static TableNode *GetNextTable( const int32_t iIndex, TableList *table_list, TableNode *poParent, const int32_t iReadLength, uint32_t *iTablesCreated )
{ {
TableNode *poNextNode; TableNode *poNextNode;
...@@ -193,7 +194,7 @@ static TableNode *GetNextTable( int32_t iIndex, TableList *table_list, TableNode ...@@ -193,7 +194,7 @@ static TableNode *GetNextTable( int32_t iIndex, TableList *table_list, TableNode
return poNextNode; return poNextNode;
} }
static void CompleteTables( LCLDDecoder *psLCLDDecoder, int32_t n, TableList *ptable_list, int32_t iReadLength, int32_t iTablesCreated ) static void CompleteTables( LCLDDecoder *psLCLDDecoder, const int32_t n, TableList *ptable_list, const int32_t iReadLength, const int32_t iTablesCreated )
{ {
int32_t iMaxTables; int32_t iMaxTables;
...@@ -202,7 +203,7 @@ static void CompleteTables( LCLDDecoder *psLCLDDecoder, int32_t n, TableList *pt ...@@ -202,7 +203,7 @@ static void CompleteTables( LCLDDecoder *psLCLDDecoder, int32_t n, TableList *pt
iMaxTables = 1 << iReadLength; iMaxTables = 1 << iReadLength;
psLCLDDecoder->c_apauiHuffDecTable_RAM[n] = psLCLDDecoder->c_apauiHuffDecTable_RAM[n] =
malloc( iTablesCreated * iMaxTables * sizeof( uint32_t * ) ); malloc( iTablesCreated * iMaxTables * sizeof( uint32_t ) );
poNode = ptable_list->poOrderedTop; poNode = ptable_list->poOrderedTop;
for ( j = 0; j < iTablesCreated; j++ ) for ( j = 0; j < iTablesCreated; j++ )
...@@ -222,7 +223,7 @@ static void CompleteTables( LCLDDecoder *psLCLDDecoder, int32_t n, TableList *pt ...@@ -222,7 +223,7 @@ static void CompleteTables( LCLDDecoder *psLCLDDecoder, int32_t n, TableList *pt
poNode = poNode->poOrderedNext; poNode = poNode->poOrderedNext;
} }
} }
static void AddcodeTableList( TableList *ptable_list, int32_t iLength, int32_t iCode, int32_t iCodeIndex, int32_t iReadLength, uint32_t *iTables ) static void AddcodeTableList( TableList *ptable_list, const int32_t iLength, const int32_t iCode, const int32_t iCodeIndex, const int32_t iReadLength, uint32_t *iTables )
{ {
int32_t iDifference; int32_t iDifference;
int32_t iMask; int32_t iMask;
...@@ -257,7 +258,7 @@ static void AddcodeTableList( TableList *ptable_list, int32_t iLength, int32_t i ...@@ -257,7 +258,7 @@ static void AddcodeTableList( TableList *ptable_list, int32_t iLength, int32_t i
} }
} }
static void CreateDecodeTable( LCLDDecoder *psLCLDDecoder, int32_t num, const uint16_t ( *ppuiEncTable )[2], int32_t iSize, int32_t iReadLength, uint32_t *iTables ) static void CreateDecodeTable( LCLDDecoder *psLCLDDecoder, const int32_t num, const uint16_t ( *ppuiEncTable )[2], const int32_t iSize, const int32_t iReadLength, uint32_t *iTables )
{ {
int32_t n; int32_t n;
uint32_t **ppsort_enc_table; uint32_t **ppsort_enc_table;
...@@ -345,7 +346,8 @@ ivas_error CreateLCLDDecoder( ...@@ -345,7 +346,8 @@ ivas_error CreateLCLDDecoder(
LCLDDecoder **psLCLDDecoder_out, LCLDDecoder **psLCLDDecoder_out,
const int32_t iSampleRate, const int32_t iSampleRate,
const int32_t iChannels, const int32_t iChannels,
const int32_t iNumBlocks ) const int32_t iNumBlocks,
const int32_t iRealOnlyOut )
{ {
int32_t n; int32_t n;
int32_t read_length; int32_t read_length;
...@@ -360,9 +362,16 @@ ivas_error CreateLCLDDecoder( ...@@ -360,9 +362,16 @@ ivas_error CreateLCLDDecoder(
} }
psLCLDDecoder->iSampleRate = iSampleRate; psLCLDDecoder->iSampleRate = iSampleRate;
psLCLDDecoder->iChannels = iChannels; psLCLDDecoder->iChannels = iChannels;
psLCLDDecoder->iNumBlocks = iNumBlocks;
psLCLDDecoder->iAllocOffset = 0; psLCLDDecoder->iAllocOffset = 0;
psLCLDDecoder->iRealOnlyOut = iRealOnlyOut;
if ( iRealOnlyOut == 1 )
{
psLCLDDecoder->iNumBlocks = iNumBlocks / 2;
}
else
{
psLCLDDecoder->iNumBlocks = iNumBlocks;
}
psLCLDDecoder->iNumBands = 0; /* read from bitstream*/ psLCLDDecoder->iNumBands = 0; /* read from bitstream*/
psLCLDDecoder->piBandwidths = c_aiBandwidths48; psLCLDDecoder->piBandwidths = c_aiBandwidths48;
...@@ -702,23 +711,108 @@ static void InvQuantizeSpectrum( const int32_t iNumGroups, const int32_t *piGrou ...@@ -702,23 +711,108 @@ static void InvQuantizeSpectrum( const int32_t iNumGroups, const int32_t *piGrou
static void InvMSCoding( const int32_t iNumBlocks, const int32_t iNumBands, const int32_t *piBandwidths, const int32_t iMSMode, const int32_t *piMSFlags, const int32_t *piLRPhaseDiffs, const int32_t *piMSPredCoefs, float ***pppfReal, float ***pppfImag ); static void InvMSCoding( const int32_t iNumBlocks, const int32_t iNumBands, const int32_t *piBandwidths, const int32_t iMSMode, const int32_t *piMSFlags, const int32_t *piLRPhaseDiffs, const int32_t *piMSPredCoefs, float ***pppfReal, float ***pppfImag );
static int32_t ReadHeaderInformation( int32_t *piNumBands, IVAS_SPLIT_REND_BITS_HANDLE pBits ); static int32_t ReadHeaderInformation( int32_t *piNumBands, ISAR_SPLIT_REND_BITS_HANDLE pBits );
static int32_t ReadMSInformation( const int32_t iNumBands, int32_t *piMSMode, int32_t *piMSFlags, int32_t *piLRPhaseDiffs, int32_t *piMSPredCoefs, IVAS_SPLIT_REND_BITS_HANDLE pBits ); static int32_t ReadMSInformation( const int32_t iNumBands, int32_t *piMSMode, int32_t *piMSFlags, int32_t *piLRPhaseDiffs, int32_t *piMSPredCoefs, ISAR_SPLIT_REND_BITS_HANDLE pBits );
static int32_t ReadGroupInformation( const int32_t iChannels, const int32_t iNumBlocks, int32_t *piCommonGrouping, int32_t *piNumGroups, int32_t **ppiGroupLengths, IVAS_SPLIT_REND_BITS_HANDLE pBits ); static int32_t ReadGroupInformation( const int32_t iChannels, const int32_t iNumBlocks, int32_t *piCommonGrouping, int32_t *piNumGroups, int32_t **ppiGroupLengths, ISAR_SPLIT_REND_BITS_HANDLE pBits );
static int32_t ReadHuff( const uint32_t ( *pauiHuffDecTable )[HUFF_DEC_TABLE_SIZE], int32_t *piSymbol, IVAS_SPLIT_REND_BITS_HANDLE pBits ); static int32_t ReadHuff( const uint32_t ( *pauiHuffDecTable )[HUFF_DEC_TABLE_SIZE], int32_t *piSymbol, ISAR_SPLIT_REND_BITS_HANDLE pBits );
static int32_t ReadRMSEnvelope( const int32_t iChannels, const int32_t *piNumGroups, const int32_t iNumBands, int32_t ***pppiRMSEnvelope, IVAS_SPLIT_REND_BITS_HANDLE pBits ); static int32_t ReadRMSEnvelope( const int32_t iChannels, const int32_t *piNumGroups, const int32_t iNumBands, int32_t ***pppiRMSEnvelope, ISAR_SPLIT_REND_BITS_HANDLE pBits );
static int32_t ReadAllocInformation( int32_t *piAllocOffset, IVAS_SPLIT_REND_BITS_HANDLE pBits );
static int32_t ReadAllocInformation( int32_t *piAllocOffset, ISAR_SPLIT_REND_BITS_HANDLE pBits );
static int32_t static int32_t
ReadLCLDData( const int32_t iNumGroups, const int32_t *piGroupLengths, const int32_t iNumBands, const int32_t *piBandwidths, const int32_t *piPredEnable, int32_t **ppiAlloc, int32_t **ppiSignReal, int32_t **ppiSignImag, int32_t **ppiQReal, int32_t **ppiQImag, IVAS_SPLIT_REND_BITS_HANDLE pBits, uint32_t ( *c_apauiHuffDecTables[2 * ALLOC_TABLE_SIZE] )[HUFF_DEC_TABLE_SIZE] ); ReadLCLDData( const int32_t *piNumGroups, int32_t **ppiGroupLengths, const int32_t iNumBands, const int32_t iNumChannels, int32_t **ppiDecodingUnresolved, int32_t **ppiPredEnable, const int32_t iNumSubSets, const int32_t iSubSetId, int32_t ***pppiAlloc, int32_t ***pppiSignReal, int32_t ***pppiSignImag, int32_t ***pppiQReal, int32_t ***pppiQImag, int32_t **ppiDecodingFailed, ISAR_SPLIT_REND_BITS_HANDLE pBits, uint32_t ( *c_apauiHuffDecTables[2 * ALLOC_TABLE_SIZE] )[HUFF_DEC_TABLE_SIZE] );
static void ComputeAllocation( const int32_t iChannels, const int32_t *piNumGroups, const int32_t iNumBands, int32_t ***pppiSMR, const int32_t iAllocOffset, int32_t ***pppiAlloc ); static void ComputeAllocation( const int32_t iChannels, const int32_t *piNumGroups, const int32_t iNumBands, int32_t ***pppiSMR, const int32_t iAllocOffset, int32_t ***pppiAlloc );
void SetDecodingUnresolved( LCLDDecoder *psLCLDDecoder )
{
int32_t n, ch;
PredictionDecoder *psPredictionDecoder = psLCLDDecoder->psPredictionDecoder;
for ( ch = 0; ch < psPredictionDecoder->iChannels; ch++ )
{
for ( n = 0; n < psPredictionDecoder->iNumSubSets; n++ )
{
psPredictionDecoder->ppiDecodingUnresolved[ch][n] = 1;
psPredictionDecoder->ppiDecodingFailed[ch][n] = 1;
psPredictionDecoder->ppiDecodingFailedPrev[ch][n] = 1;
}
}
}
int32_t AnyDecodingFailedPrev( LCLDDecoder *psLCLDDecoder )
{
int32_t n, ch;
PredictionDecoder *psPredictionDecoder = psLCLDDecoder->psPredictionDecoder;
for ( ch = 0; ch < psPredictionDecoder->iChannels; ch++ )
{
for ( n = 0; n < psPredictionDecoder->iNumSubSets; n++ )
{
if ( psPredictionDecoder->ppiDecodingFailedPrev[ch][n] == 1 )
{
return 1;
}
}
}
return 0;
}
int32_t AnyDecodingFailed( LCLDDecoder *psLCLDDecoder )
{
int32_t n, ch;
PredictionDecoder *psPredictionDecoder = psLCLDDecoder->psPredictionDecoder;
for ( ch = 0; ch < psPredictionDecoder->iChannels; ch++ )
{
for ( n = 0; n < psPredictionDecoder->iNumSubSets; n++ )
{
if ( psPredictionDecoder->ppiDecodingFailed[ch][n] == 1 )
{
return 1;
}
}
}
return 0;
}
int32_t **GetDecodingFailedStatus( LCLDDecoder *psLCLDDecoder )
{
return psLCLDDecoder->psPredictionDecoder->ppiDecodingFailed;
}
int16_t GetNumSubSets( LCLDDecoder *psLCLDDecoder )
{
return (int16_t) psLCLDDecoder->psPredictionDecoder->iNumSubSets;
}
int32_t **GetDecodingFailedPrevStatus( LCLDDecoder *psLCLDDecoder )
{
return psLCLDDecoder->psPredictionDecoder->ppiDecodingFailedPrev;
}
static void UnpackReal(
const int32_t iChannels,
const int32_t iNumBlocks,
float ***pppfReal,
float ***pppfImag )
{
int32_t ch, b, n;
for ( ch = 0; ch < iChannels; ch++ )
{
for ( b = 0; b < LCLD_BANDS; b++ )
{
int32_t iRealBlock = iNumBlocks - 1;
for ( n = iNumBlocks / 2 - 1; n >= 0; n-- )
{
pppfReal[ch][iRealBlock][b] = pppfImag[ch][n][b] * 2.0f;
pppfReal[ch][iRealBlock - 1][b] = pppfReal[ch][n][b] * 2.0f;
pppfImag[ch][iRealBlock][b] = 0.0f;
pppfImag[ch][iRealBlock - 1][b] = 0.0f;
iRealBlock -= 2;
}
}
}
}
/*------------------------------------------------------------------------------------------* /*------------------------------------------------------------------------------------------*
* Function DecodeLCLDFrame() * Function DecodeLCLDFrame()
...@@ -728,7 +822,7 @@ static void ComputeAllocation( const int32_t iChannels, const int32_t *piNumGrou ...@@ -728,7 +822,7 @@ static void ComputeAllocation( const int32_t iChannels, const int32_t *piNumGrou
int32_t DecodeLCLDFrame( int32_t DecodeLCLDFrame(
LCLDDecoder *psLCLDDecoder, LCLDDecoder *psLCLDDecoder,
IVAS_SPLIT_REND_BITS_HANDLE pBits, ISAR_SPLIT_REND_BITS_HANDLE pBits,
float ***pppfLCLDReal, float ***pppfLCLDReal,
float ***pppfLCLDImag ) float ***pppfLCLDImag )
{ {
...@@ -742,6 +836,8 @@ int32_t DecodeLCLDFrame( ...@@ -742,6 +836,8 @@ int32_t DecodeLCLDFrame(
} }
ReadPredictors( psLCLDDecoder->psPredictionDecoder, pBits ); ReadPredictors( psLCLDDecoder->psPredictionDecoder, pBits );
UpdateDecodingUnresolved( psLCLDDecoder->psPredictionDecoder );
UpdateDecodingFailedStatus( psLCLDDecoder->psPredictionDecoder );
ReadGroupInformation( psLCLDDecoder->iChannels, psLCLDDecoder->iNumBlocks, &psLCLDDecoder->iCommonGrouping, psLCLDDecoder->piNumGroups, psLCLDDecoder->ppiGroupLengths, pBits ); ReadGroupInformation( psLCLDDecoder->iChannels, psLCLDDecoder->iNumBlocks, &psLCLDDecoder->iCommonGrouping, psLCLDDecoder->piNumGroups, psLCLDDecoder->ppiGroupLengths, pBits );
...@@ -776,20 +872,23 @@ int32_t DecodeLCLDFrame( ...@@ -776,20 +872,23 @@ int32_t DecodeLCLDFrame(
ComputeAllocation( psLCLDDecoder->iChannels, (const int32_t *) psLCLDDecoder->piNumGroups, psLCLDDecoder->iNumBands, psLCLDDecoder->pppiSMR, psLCLDDecoder->iAllocOffset, psLCLDDecoder->pppiAlloc ); ComputeAllocation( psLCLDDecoder->iChannels, (const int32_t *) psLCLDDecoder->piNumGroups, psLCLDDecoder->iNumBands, psLCLDDecoder->pppiSMR, psLCLDDecoder->iAllocOffset, psLCLDDecoder->pppiAlloc );
for ( n = 0; n < psLCLDDecoder->iChannels; n++ )
{
ReadLCLDData( ReadLCLDData(
psLCLDDecoder->piNumGroups[n], psLCLDDecoder->piNumGroups,
(const int32_t *) psLCLDDecoder->ppiGroupLengths[n], psLCLDDecoder->ppiGroupLengths,
psLCLDDecoder->iNumBands, psLCLDDecoder->piBandwidths, psLCLDDecoder->iNumBands,
(const int32_t *) psLCLDDecoder->iChannels,
psLCLDDecoder->psPredictionDecoder->ppiPredBandEnable[n], psLCLDDecoder->psPredictionDecoder->ppiDecodingUnresolved,
psLCLDDecoder->pppiAlloc[n], psLCLDDecoder->psPredictionDecoder->ppiPredBandEnable,
psLCLDDecoder->pppiLCLDSignReal[n], psLCLDDecoder->pppiLCLDSignImag[n], psLCLDDecoder->psPredictionDecoder->iNumSubSets,
psLCLDDecoder->pppiQLCLDReal[n], psLCLDDecoder->pppiQLCLDImag[n], psLCLDDecoder->psPredictionDecoder->iSubSetId,
psLCLDDecoder->pppiAlloc,
psLCLDDecoder->pppiLCLDSignReal,
psLCLDDecoder->pppiLCLDSignImag,
psLCLDDecoder->pppiQLCLDReal,
psLCLDDecoder->pppiQLCLDImag,
psLCLDDecoder->psPredictionDecoder->ppiDecodingFailed,
pBits, pBits,
psLCLDDecoder->c_apauiHuffDecTable_RAM ); psLCLDDecoder->c_apauiHuffDecTable_RAM );
}
for ( n = 0; n < psLCLDDecoder->iChannels; n++ ) for ( n = 0; n < psLCLDDecoder->iChannels; n++ )
{ {
...@@ -843,7 +942,15 @@ int32_t DecodeLCLDFrame( ...@@ -843,7 +942,15 @@ int32_t DecodeLCLDFrame(
pppfLCLDReal, pppfLCLDImag ); pppfLCLDReal, pppfLCLDImag );
} }
return 0; if ( psLCLDDecoder->iRealOnlyOut == 1 )
{
UnpackReal( psLCLDDecoder->iChannels,
psLCLDDecoder->iNumBlocks * 2,
pppfLCLDReal,
pppfLCLDImag );
}
return AnyDecodingUnresolved( psLCLDDecoder->psPredictionDecoder );
} }
...@@ -1051,7 +1158,7 @@ static void InvMSCoding( ...@@ -1051,7 +1158,7 @@ static void InvMSCoding(
if ( iMSMode == 3 ) if ( iMSMode == 3 )
{ {
cplxmult( &fRightReal, &fRightImag, c_afRotRealImag[phaseIdx][0], -c_afRotRealImag[phaseIdx][1] ); cplxmult_lcld( &fRightReal, &fRightImag, c_afRotRealImag[phaseIdx][0], -c_afRotRealImag[phaseIdx][1] );
} }
pppfReal[0][k][iFBOffset] = fLeftReal; pppfReal[0][k][iFBOffset] = fLeftReal;
...@@ -1077,12 +1184,12 @@ static void InvMSCoding( ...@@ -1077,12 +1184,12 @@ static void InvMSCoding(
/* Currently only the number of bands in frame */ /* Currently only the number of bands in frame */
static int32_t ReadHeaderInformation( static int32_t ReadHeaderInformation(
int32_t *piNumBands, int32_t *piNumBands,
IVAS_SPLIT_REND_BITS_HANDLE pBits ) ISAR_SPLIT_REND_BITS_HANDLE pBits )
{ {
int32_t iBitsRead; int32_t iBitsRead;
iBitsRead = 0; iBitsRead = 0;
*piNumBands = ivas_split_rend_bitstream_read_int32( pBits, 5 ); *piNumBands = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 5 );
iBitsRead += 5; iBitsRead += 5;
return iBitsRead; return iBitsRead;
...@@ -1095,12 +1202,12 @@ static int32_t ReadMSInformation( ...@@ -1095,12 +1202,12 @@ static int32_t ReadMSInformation(
int32_t *piMSFlags, int32_t *piMSFlags,
int32_t *piLRPhaseDiffs, int32_t *piLRPhaseDiffs,
int32_t *piMSPredCoefs, int32_t *piMSPredCoefs,
IVAS_SPLIT_REND_BITS_HANDLE pBits ) ISAR_SPLIT_REND_BITS_HANDLE pBits )
{ {
int32_t iBitsRead; int32_t iBitsRead;
iBitsRead = 0; iBitsRead = 0;
*piMSMode = ivas_split_rend_bitstream_read_int32( pBits, 2 ); *piMSMode = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 2 );
iBitsRead += 2; iBitsRead += 2;
if ( *piMSMode == 0 ) if ( *piMSMode == 0 )
...@@ -1124,7 +1231,7 @@ static int32_t ReadMSInformation( ...@@ -1124,7 +1231,7 @@ static int32_t ReadMSInformation(
int32_t n; int32_t n;
for ( n = 0; n < iNumBands; n++ ) for ( n = 0; n < iNumBands; n++ )
{ {
piMSFlags[n] = ivas_split_rend_bitstream_read_int32( pBits, 1 ); piMSFlags[n] = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 1 );
iBitsRead += 1; iBitsRead += 1;
} }
} }
...@@ -1134,7 +1241,7 @@ static int32_t ReadMSInformation( ...@@ -1134,7 +1241,7 @@ static int32_t ReadMSInformation(
int32_t iMSPredAll; int32_t iMSPredAll;
int32_t iNumMSPredBands = 0; int32_t iNumMSPredBands = 0;
int32_t anyNonZero; int32_t anyNonZero;
iMSPredAll = ivas_split_rend_bitstream_read_int32( pBits, 1 ); iMSPredAll = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 1 );
iBitsRead += 1; iBitsRead += 1;
if ( iMSPredAll ) if ( iMSPredAll )
{ {
...@@ -1148,7 +1255,7 @@ static int32_t ReadMSInformation( ...@@ -1148,7 +1255,7 @@ static int32_t ReadMSInformation(
{ {
for ( n = 0; n < iNumBands; n++ ) for ( n = 0; n < iNumBands; n++ )
{ {
piMSFlags[n] = ivas_split_rend_bitstream_read_int32( pBits, 1 ); piMSFlags[n] = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 1 );
iBitsRead += 1; iBitsRead += 1;
if ( piMSFlags[n] ) if ( piMSFlags[n] )
{ {
...@@ -1156,10 +1263,10 @@ static int32_t ReadMSInformation( ...@@ -1156,10 +1263,10 @@ static int32_t ReadMSInformation(
} }
} }
} }
anyNonZero = ivas_split_rend_bitstream_read_int32( pBits, 1 ); anyNonZero = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 1 );
if ( anyNonZero ) if ( anyNonZero )
{ {
piLRPhaseDiffs[0] = ivas_split_rend_bitstream_read_int32( pBits, PHASE_BAND0_BITS ); piLRPhaseDiffs[0] = ISAR_SPLIT_REND_BITStream_read_int32( pBits, PHASE_BAND0_BITS );
piLRPhaseDiffs[0] += PHASE_MIN_VAL; piLRPhaseDiffs[0] += PHASE_MIN_VAL;
iBitsRead += PHASE_BAND0_BITS; iBitsRead += PHASE_BAND0_BITS;
for ( n = 1; n < iNumMSPredBands; n++ ) for ( n = 1; n < iNumMSPredBands; n++ )
...@@ -1177,10 +1284,10 @@ static int32_t ReadMSInformation( ...@@ -1177,10 +1284,10 @@ static int32_t ReadMSInformation(
piLRPhaseDiffs[n] = 0; piLRPhaseDiffs[n] = 0;
} }
} }
anyNonZero = ivas_split_rend_bitstream_read_int32( pBits, 1 ); anyNonZero = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 1 );
if ( anyNonZero ) if ( anyNonZero )
{ {
piMSPredCoefs[0] = ivas_split_rend_bitstream_read_int32( pBits, PRED_BAND0_BITS ); piMSPredCoefs[0] = ISAR_SPLIT_REND_BITStream_read_int32( pBits, PRED_BAND0_BITS );
piMSPredCoefs[0] += PRED_MIN_VAL; piMSPredCoefs[0] += PRED_MIN_VAL;
iBitsRead += PRED_BAND0_BITS; iBitsRead += PRED_BAND0_BITS;
for ( n = 1; n < iNumMSPredBands; n++ ) for ( n = 1; n < iNumMSPredBands; n++ )
...@@ -1221,14 +1328,14 @@ static int32_t ReadGroupInformation( ...@@ -1221,14 +1328,14 @@ static int32_t ReadGroupInformation(
int32_t *piCommonGrouping, int32_t *piCommonGrouping,
int32_t *piNumGroups, int32_t *piNumGroups,
int32_t **ppiGroupLengths, int32_t **ppiGroupLengths,
IVAS_SPLIT_REND_BITS_HANDLE pBits ) ISAR_SPLIT_REND_BITS_HANDLE pBits )
{ {
int32_t c, k, iBitsRead; int32_t c, k, iBitsRead;
iBitsRead = 0; iBitsRead = 0;
if ( iChannels == 2 ) if ( iChannels == 2 )
{ {
*piCommonGrouping = ivas_split_rend_bitstream_read_int32( pBits, 1 ); *piCommonGrouping = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 1 );
iBitsRead += 1; iBitsRead += 1;
if ( *piCommonGrouping == 1 ) if ( *piCommonGrouping == 1 )
...@@ -1239,7 +1346,7 @@ static int32_t ReadGroupInformation( ...@@ -1239,7 +1346,7 @@ static int32_t ReadGroupInformation(
{ {
int32_t iGroupStart; int32_t iGroupStart;
iGroupStart = ivas_split_rend_bitstream_read_int32( pBits, 1 ); iGroupStart = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 1 );
iBitsRead += 1; iBitsRead += 1;
if ( iGroupStart == 1 ) if ( iGroupStart == 1 )
...@@ -1270,7 +1377,7 @@ static int32_t ReadGroupInformation( ...@@ -1270,7 +1377,7 @@ static int32_t ReadGroupInformation(
{ {
int32_t iGroupStart; int32_t iGroupStart;
iGroupStart = ivas_split_rend_bitstream_read_int32( pBits, 1 ); iGroupStart = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 1 );
iBitsRead += 1; iBitsRead += 1;
if ( iGroupStart == 1 ) if ( iGroupStart == 1 )
...@@ -1297,7 +1404,7 @@ static int32_t ReadGroupInformation( ...@@ -1297,7 +1404,7 @@ static int32_t ReadGroupInformation(
{ {
int32_t iGroupStart; int32_t iGroupStart;
iGroupStart = ivas_split_rend_bitstream_read_int32( pBits, 1 ); iGroupStart = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 1 );
iBitsRead += 1; iBitsRead += 1;
if ( iGroupStart == 1 ) if ( iGroupStart == 1 )
...@@ -1319,7 +1426,7 @@ static int32_t ReadGroupInformation( ...@@ -1319,7 +1426,7 @@ static int32_t ReadGroupInformation(
static int32_t BSForceBack( static int32_t BSForceBack(
IVAS_SPLIT_REND_BITS_HANDLE pBits, ISAR_SPLIT_REND_BITS_HANDLE pBits,
int32_t iValue, int32_t iValue,
int32_t iBitCount ) int32_t iBitCount )
{ {
...@@ -1332,7 +1439,7 @@ static int32_t BSForceBack( ...@@ -1332,7 +1439,7 @@ static int32_t BSForceBack(
static int32_t ReadHuff( static int32_t ReadHuff(
const uint32_t ( *pauiHuffDecTable )[HUFF_DEC_TABLE_SIZE], const uint32_t ( *pauiHuffDecTable )[HUFF_DEC_TABLE_SIZE],
int32_t *piSymbol, int32_t *piSymbol,
IVAS_SPLIT_REND_BITS_HANDLE pBits ) ISAR_SPLIT_REND_BITS_HANDLE pBits )
{ {
int32_t iBitsRead; int32_t iBitsRead;
int32_t iSymbol; int32_t iSymbol;
...@@ -1345,7 +1452,7 @@ static int32_t ReadHuff( ...@@ -1345,7 +1452,7 @@ static int32_t ReadHuff(
iBitsRead = 0; iBitsRead = 0;
while ( iSymbol == 0xFFFF ) while ( iSymbol == 0xFFFF )
{ {
iIndex = ivas_split_rend_bitstream_read_int32( pBits, HUFF_READ_SIZE ); iIndex = ISAR_SPLIT_REND_BITStream_read_int32( pBits, HUFF_READ_SIZE );
iBitsRead += HUFF_READ_SIZE; iBitsRead += HUFF_READ_SIZE;
iIndex = pauiHuffDecTable[iVal][iIndex]; iIndex = pauiHuffDecTable[iVal][iIndex];
...@@ -1371,7 +1478,7 @@ static int32_t ReadRMSEnvelope( ...@@ -1371,7 +1478,7 @@ static int32_t ReadRMSEnvelope(
const int32_t *piNumGroups, const int32_t *piNumGroups,
const int32_t iNumBands, const int32_t iNumBands,
int32_t ***pppiRMSEnvelope, int32_t ***pppiRMSEnvelope,
IVAS_SPLIT_REND_BITS_HANDLE pBits ) ISAR_SPLIT_REND_BITS_HANDLE pBits )
{ {
int32_t b, k, n; int32_t b, k, n;
int32_t iBitsRead, iLastRMSVal; int32_t iBitsRead, iLastRMSVal;
...@@ -1381,7 +1488,7 @@ static int32_t ReadRMSEnvelope( ...@@ -1381,7 +1488,7 @@ static int32_t ReadRMSEnvelope(
{ {
for ( k = 0; k < piNumGroups[n]; k++ ) for ( k = 0; k < piNumGroups[n]; k++ )
{ {
iLastRMSVal = ivas_split_rend_bitstream_read_int32( pBits, ENV0_BITS ); iLastRMSVal = ISAR_SPLIT_REND_BITStream_read_int32( pBits, ENV0_BITS );
iBitsRead += ENV0_BITS; iBitsRead += ENV0_BITS;
iLastRMSVal += ENV_MIN; iLastRMSVal += ENV_MIN;
...@@ -1405,12 +1512,12 @@ static int32_t ReadRMSEnvelope( ...@@ -1405,12 +1512,12 @@ static int32_t ReadRMSEnvelope(
static int32_t ReadAllocInformation( static int32_t ReadAllocInformation(
int32_t *piAllocOffset, int32_t *piAllocOffset,
IVAS_SPLIT_REND_BITS_HANDLE pBits ) ISAR_SPLIT_REND_BITS_HANDLE pBits )
{ {
int32_t iBitsRead; int32_t iBitsRead;
iBitsRead = 0; iBitsRead = 0;
*piAllocOffset = ivas_split_rend_bitstream_read_int32( pBits, ALLOC_OFFSET_BITS ); *piAllocOffset = ISAR_SPLIT_REND_BITStream_read_int32( pBits, ALLOC_OFFSET_BITS );
*piAllocOffset += MIN_ALLOC_OFFSET; *piAllocOffset += MIN_ALLOC_OFFSET;
iBitsRead += ALLOC_OFFSET_BITS; iBitsRead += ALLOC_OFFSET_BITS;
...@@ -1418,67 +1525,102 @@ static int32_t ReadAllocInformation( ...@@ -1418,67 +1525,102 @@ static int32_t ReadAllocInformation(
} }
static int32_t ReadLCLDData( static int32_t ReadLCLDData(
const int32_t iNumGroups, const int32_t *piNumGroups,
const int32_t *piGroupLengths, int32_t **ppiGroupLengths,
const int32_t iNumBands, const int32_t iNumBands,
const int32_t *piBandwidths, const int32_t iNumChannels,
const int32_t *piPredEnable, int32_t **ppiDecodingUnresolved,
int32_t **ppiAlloc, int32_t **ppiPredEnable,
int32_t **ppiSignReal, const int32_t iNumSubSets,
int32_t **ppiSignImag, const int32_t iSubSetId,
int32_t **ppiQReal, int32_t ***pppiAlloc,
int32_t **ppiQImag, int32_t ***pppiSignReal,
IVAS_SPLIT_REND_BITS_HANDLE pBits, int32_t ***pppiSignImag,
int32_t ***pppiQReal,
int32_t ***pppiQImag,
int32_t **ppiDecodingFailed,
ISAR_SPLIT_REND_BITS_HANDLE pBits,
uint32_t ( *c_apauiHuffDecTables[2 * ALLOC_TABLE_SIZE] )[HUFF_DEC_TABLE_SIZE] ) uint32_t ( *c_apauiHuffDecTables[2 * ALLOC_TABLE_SIZE] )[HUFF_DEC_TABLE_SIZE] )
{ {
int32_t b, k, m, n; int32_t iBitsRead;
int32_t iBitsRead, iBlockOffest, iFBOffset; int32_t iDecodingStopped = 0;
int32_t iAlloc, iHuffDim, iHuffMod; int32_t iNumLcldBands = c_aiNumLcldBandsPerBand[iNumBands - 1];
int32_t s;
int32_t iSet = iSubSetId;
iBitsRead = 0; iBitsRead = 0;
for ( s = 0; s < iNumSubSets; s++, iSet-- )
{
int32_t ch;
if ( iSet < 0 )
{
iSet = iNumSubSets - 1;
}
for ( ch = 0; ch < iNumChannels; ch++ )
{
int32_t n;
int32_t iBlockOffest;
if ( ppiDecodingUnresolved[ch][iSet] == 1 )
{
iDecodingStopped = 1;
ppiDecodingFailed[ch][iSet] = 1; /* mark as not decoded (is also initialized like that when a frame is lost */
}
else
{
ppiDecodingFailed[ch][iSet] = 0; /* mark as correctly decoded */
}
iBlockOffest = 0; iBlockOffest = 0;
for ( n = 0; n < iNumGroups; n++ ) for ( n = 0; n < piNumGroups[ch]; n++ )
{ {
for ( k = 0; k < piGroupLengths[n]; k++ ) int32_t k;
for ( k = 0; k < ppiGroupLengths[ch][n]; k++ )
{ {
iFBOffset = 0; int32_t iFBOffset;
for ( b = 0; b < iNumBands; b++ )
for ( iFBOffset = iSet; iFBOffset < iNumLcldBands; iFBOffset += iNumSubSets )
{ {
iAlloc = ppiAlloc[n][b]; int32_t b;
int32_t iAlloc;
int32_t iHuffDim;
int32_t iHuffMod;
b = c_aiBandIdPerLcldBand[iFBOffset];
iAlloc = pppiAlloc[ch][n][b];
iHuffDim = c_aiHuffmanDim[iAlloc]; iHuffDim = c_aiHuffmanDim[iAlloc];
iHuffMod = c_aiHuffmanMod[iAlloc]; iHuffMod = c_aiHuffmanMod[iAlloc];
if ( iAlloc > 0 ) if ( iDecodingStopped == 1 )
{
pppiQReal[ch][iBlockOffest][iFBOffset] = 0;
pppiQImag[ch][iBlockOffest][iFBOffset] = 0;
pppiSignReal[ch][iBlockOffest][iFBOffset] = 0;
pppiSignImag[ch][iBlockOffest][iFBOffset] = 0;
}
else if ( iAlloc > 0 )
{ {
const uint32_t( *pauiHuffmanTable )[HUFF_DEC_TABLE_SIZE] = NULL; const uint32_t( *pauiHuffmanTable )[HUFF_DEC_TABLE_SIZE] = NULL;
const uint32_t( *pauiHuffmanTableDPCM )[HUFF_DEC_TABLE_SIZE] = NULL; const uint32_t( *pauiHuffmanTableDPCM )[HUFF_DEC_TABLE_SIZE] = NULL;
#ifdef USE_DEMOD_TABLES int32_t iQuantValue1 = 0;
const int32_t( *paiDemodTable )[2] = NULL; int32_t iQuantValue2 = 0;
#endif
pauiHuffmanTable = (const uint32_t( * )[HUFF_DEC_TABLE_SIZE]) c_apauiHuffDecTables[iAlloc]; pauiHuffmanTable = (const uint32_t( * )[HUFF_DEC_TABLE_SIZE]) c_apauiHuffDecTables[iAlloc];
pauiHuffmanTableDPCM = (const uint32_t( * )[HUFF_DEC_TABLE_SIZE]) c_apauiHuffDecTables[ALLOC_TABLE_SIZE + iAlloc]; pauiHuffmanTableDPCM = (const uint32_t( * )[HUFF_DEC_TABLE_SIZE]) c_apauiHuffDecTables[ALLOC_TABLE_SIZE + iAlloc];
#ifdef USE_DEMOD_TABLES #ifdef LCLD_HANDLE_PRED_START_SAMPLE
paiDemodTable = c_apaiDemodTables[iAlloc]; if ( ppiPredEnable[ch][iFBOffset] == 1 && ( iBlockOffest > 0 || iSet != iSubSetId ) )
#else
if ( ppiPredEnable[ch][iFBOffset] == 1 )
#endif #endif
for ( m = 0; m < piBandwidths[b]; m++ )
{
int32_t iQuantValue1 = 0;
int32_t iQuantValue2 = 0;
if ( piPredEnable[iFBOffset] == 1 )
{ {
if ( iHuffDim == 2 ) if ( iHuffDim == 2 )
{ {
int32_t iSymbol; int32_t iSymbol;
iBitsRead += ReadHuff( pauiHuffmanTableDPCM, &iSymbol, pBits ); iBitsRead += ReadHuff( pauiHuffmanTableDPCM, &iSymbol, pBits );
#ifdef USE_DEMOD_TABLES
iQuantValue1 = paiDemodTable[iSymbol][0];
iQuantValue2 = paiDemodTable[iSymbol][1];
#else
iQuantValue1 = iSymbol / iHuffMod; iQuantValue1 = iSymbol / iHuffMod;
iQuantValue2 = iSymbol % iHuffMod; iQuantValue2 = iSymbol % iHuffMod;
#endif
} }
else else
{ {
...@@ -1493,13 +1635,8 @@ static int32_t ReadLCLDData( ...@@ -1493,13 +1635,8 @@ static int32_t ReadLCLDData(
int32_t iSymbol; int32_t iSymbol;
iBitsRead += ReadHuff( pauiHuffmanTable, &iSymbol, pBits ); iBitsRead += ReadHuff( pauiHuffmanTable, &iSymbol, pBits );
#ifdef USE_DEMOD_TABLES
iQuantValue1 = paiDemodTable[iSymbol][0];
iQuantValue2 = paiDemodTable[iSymbol][1];
#else
iQuantValue1 = iSymbol / iHuffMod; iQuantValue1 = iSymbol / iHuffMod;
iQuantValue2 = iSymbol % iHuffMod; iQuantValue2 = iSymbol % iHuffMod;
#endif
} }
else else
{ {
...@@ -1508,50 +1645,43 @@ static int32_t ReadLCLDData( ...@@ -1508,50 +1645,43 @@ static int32_t ReadLCLDData(
} }
} }
ppiQReal[iBlockOffest][iFBOffset] = iQuantValue1; pppiQReal[ch][iBlockOffest][iFBOffset] = iQuantValue1;
ppiQImag[iBlockOffest][iFBOffset] = iQuantValue2; pppiQImag[ch][iBlockOffest][iFBOffset] = iQuantValue2;
if ( iQuantValue1 > 0 ) if ( iQuantValue1 > 0 )
{ {
ppiSignReal[iBlockOffest][iFBOffset] = ivas_split_rend_bitstream_read_int32( pBits, 1 ); pppiSignReal[ch][iBlockOffest][iFBOffset] = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 1 );
iBitsRead += 1; iBitsRead += 1;
} }
else else
{ {
ppiSignReal[iBlockOffest][iFBOffset] = 0; pppiSignReal[ch][iBlockOffest][iFBOffset] = 0;
} }
if ( iQuantValue2 > 0 ) if ( iQuantValue2 > 0 )
{ {
ppiSignImag[iBlockOffest][iFBOffset] = ivas_split_rend_bitstream_read_int32( pBits, 1 ); pppiSignImag[ch][iBlockOffest][iFBOffset] = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 1 );
iBitsRead += 1; iBitsRead += 1;
} }
else else
{ {
ppiSignImag[iBlockOffest][iFBOffset] = 0; pppiSignImag[ch][iBlockOffest][iFBOffset] = 0;
}
iFBOffset++;
} }
} }
else else
{ {
for ( m = 0; m < piBandwidths[b]; m++ ) pppiSignReal[ch][iBlockOffest][iFBOffset] = 0;
{ pppiSignImag[ch][iBlockOffest][iFBOffset] = 0;
ppiSignReal[iBlockOffest][iFBOffset] = 0;
ppiSignImag[iBlockOffest][iFBOffset] = 0;
iFBOffset++;
}
} }
} }
iBlockOffest++; iBlockOffest++;
} }
} }
}
}
return iBitsRead; return iBitsRead;
} }
static void ComputeAllocation( static void ComputeAllocation(
const int32_t iChannels, const int32_t iChannels,
const int32_t *piNumGroups, const int32_t *piNumGroups,
......
...@@ -35,10 +35,8 @@ ...@@ -35,10 +35,8 @@
#ifdef SPLIT_REND_WITH_HEAD_ROT #ifdef SPLIT_REND_WITH_HEAD_ROT
#include <math.h> #include <math.h>
#include <assert.h> #include <assert.h>
#include "ivas_lcld_prot.h"
#include "ivas_lcld_rom_tables.h"
#include "prot.h" #include "prot.h"
#include "ivas_prot_rend.h" #include "isar_prot.h"
#include "wmc_auto.h" #include "wmc_auto.h"
/*------------------------------------------------------------------------------------------* /*------------------------------------------------------------------------------------------*
...@@ -62,6 +60,7 @@ struct LCLD_ENCODER ...@@ -62,6 +60,7 @@ struct LCLD_ENCODER
int32_t piLRPhaseDiffs[MAX_BANDS]; int32_t piLRPhaseDiffs[MAX_BANDS];
int32_t iAllowSidePred; int32_t iAllowSidePred;
int32_t iRealOnlyOut;
RMSEnvelopeGrouping *psRMSEnvelopeGrouping; RMSEnvelopeGrouping *psRMSEnvelopeGrouping;
...@@ -136,6 +135,28 @@ static float UnQuantize( ...@@ -136,6 +135,28 @@ static float UnQuantize(
return fVal; return fVal;
} }
static void PackReal(
const int32_t iChannels,
const int32_t iNumBlocks,
float ***pppfReal,
float ***pppfImag )
{
int32_t ch, b, n;
for ( ch = 0; ch < iChannels; ch++ )
{
for ( b = 0; b < LCLD_BANDS; b++ )
{
int32_t iRealBlock = 0;
for ( n = 0; n < iNumBlocks; n += 2 )
{
pppfImag[ch][iRealBlock][b] = pppfReal[ch][n + 1][b];
pppfReal[ch][iRealBlock][b] = pppfReal[ch][n][b];
iRealBlock++;
}
}
}
}
/*------------------------------------------------------------------------------------------* /*------------------------------------------------------------------------------------------*
* Function CreateLCLDEncoder() * Function CreateLCLDEncoder()
* *
...@@ -149,14 +170,15 @@ ivas_error CreateLCLDEncoder( ...@@ -149,14 +170,15 @@ ivas_error CreateLCLDEncoder(
const int32_t iTargetBitRate, const int32_t iTargetBitRate,
const int32_t iAllowSidePred, const int32_t iAllowSidePred,
const int16_t iNumBlocks, const int16_t iNumBlocks,
const int16_t iNumSubSets ) const int16_t iNumSubSets,
const int32_t iRealOnlyOut )
{ {
int32_t n; int32_t n;
LCLDEncoder *psLCLDEncoder; LCLDEncoder *psLCLDEncoder;
ivas_error error; ivas_error error;
int32_t iMaxNumPredBands = 0; int32_t iMaxNumPredBands = 0;
assert( iSampleRate == 48000 ); // Fix assert( iSampleRate == 48000 );
assert( iNumBlocks == 16 || iNumBlocks == 8 || iNumBlocks == 4 ); assert( iNumBlocks == 16 || iNumBlocks == 8 || iNumBlocks == 4 );
assert( iNumSubSets > 0 && iNumSubSets <= LCLD_MAX_NUM_PRED_SUBSETS ); assert( iNumSubSets > 0 && iNumSubSets <= LCLD_MAX_NUM_PRED_SUBSETS );
...@@ -167,19 +189,24 @@ ivas_error CreateLCLDEncoder( ...@@ -167,19 +189,24 @@ ivas_error CreateLCLDEncoder(
psLCLDEncoder->iSampleRate = iSampleRate; psLCLDEncoder->iSampleRate = iSampleRate;
psLCLDEncoder->iChannels = iChannels; psLCLDEncoder->iChannels = iChannels;
psLCLDEncoder->iNumBlocks = (int32_t) iNumBlocks; psLCLDEncoder->iRealOnlyOut = iRealOnlyOut;
psLCLDEncoder->iAllocOffset = 0; psLCLDEncoder->iAllocOffset = 0;
psLCLDEncoder->iTargetBitRate = iTargetBitRate; psLCLDEncoder->iTargetBitRate = iTargetBitRate;
psLCLDEncoder->piBandwidths = c_aiBandwidths48; psLCLDEncoder->piBandwidths = c_aiBandwidths48;
psLCLDEncoder->iNumBands = DEF_BANDS_48; /* 22 bands = 50 CLDFB bands (rather than 23 bands) */ psLCLDEncoder->iNumBands = DEF_BANDS_48; /* 22 bands = 50 CLDFB bands (rather than 23 bands) */
for ( n = 0; n < psLCLDEncoder->iNumBands; n++ ) iMaxNumPredBands = min( c_aiNumLcldBandsPerBand[psLCLDEncoder->iNumBands - 1], 50 );
if ( iRealOnlyOut == 1 )
{ {
iMaxNumPredBands += psLCLDEncoder->piBandwidths[n]; iMaxNumPredBands = 0;
assert( iNumSubSets == 1 );
psLCLDEncoder->iNumBlocks = iNumBlocks / 2;
}
else
{
psLCLDEncoder->iNumBlocks = iNumBlocks;
} }
psLCLDEncoder->iMSMode = 0; psLCLDEncoder->iMSMode = 0;
if ( ( psLCLDEncoder->piMSFlags = (int32_t *) malloc( MAX_BANDS * sizeof( int32_t ) ) ) == NULL ) if ( ( psLCLDEncoder->piMSFlags = (int32_t *) malloc( MAX_BANDS * sizeof( int32_t ) ) ) == NULL )
{ {
...@@ -192,10 +219,9 @@ ivas_error CreateLCLDEncoder( ...@@ -192,10 +219,9 @@ ivas_error CreateLCLDEncoder(
psLCLDEncoder->piMSPredCoefs[n] = 0; psLCLDEncoder->piMSPredCoefs[n] = 0;
} }
psLCLDEncoder->iAllowSidePred = iAllowSidePred; psLCLDEncoder->iAllowSidePred = iAllowSidePred;
psLCLDEncoder->psRMSEnvelopeGrouping = CreateRMSEnvelopeGrouping( psLCLDEncoder->iNumBlocks ); psLCLDEncoder->psRMSEnvelopeGrouping = CreateRMSEnvelopeGrouping( psLCLDEncoder->iNumBlocks );
psLCLDEncoder->iCommonGrouping = 1; //*Common grouping always on only impacts stereo */ psLCLDEncoder->iCommonGrouping = 1; /*Common grouping always on only impacts stereo */
if ( ( psLCLDEncoder->piNumGroups = (int32_t *) malloc( psLCLDEncoder->iChannels * sizeof( int32_t ) ) ) == NULL ) if ( ( psLCLDEncoder->piNumGroups = (int32_t *) malloc( psLCLDEncoder->iChannels * sizeof( int32_t ) ) ) == NULL )
{ {
return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) );
...@@ -505,23 +531,23 @@ void DeleteLCLDEncoder( ...@@ -505,23 +531,23 @@ void DeleteLCLDEncoder(
* Local function declarations * Local function declarations
*------------------------------------------------------------------------------------------*/ *------------------------------------------------------------------------------------------*/
static int32_t MSModeCalculation( const int32_t iNumBlocks, const int32_t iNumBands, const int32_t *piBandwidths, float ***pppfReal, float ***pppfImag, int32_t *piMSMode, int32_t *piLRPhaseDiff, int32_t *piMSPredCoef, const int32_t iAllowSidePred, int32_t *piMSFlags ); static int32_t MSModeCalculation( const int32_t iNumBlocks, const int32_t iNumBands, const int32_t *piBandwidths, float ***pppfReal, float ***pppfImag, int32_t *piMSMode, int32_t *piLRPhaseDiff, int32_t *piMSPredCoef, const int32_t iAllowSidePred, const int32_t iRealOnlyOut, int32_t *piMSFlags );
static void RemoveRMSEnvelope( const int32_t iNumBands, const int32_t *piBandwidths, const int32_t iNumGroups, const int32_t *piGroupLengths, int32_t **ppiRMSEnvelope, float **ppfReal, float **ppfImag ); static void RemoveRMSEnvelope( const int32_t iNumBands, const int32_t *piBandwidths, const int32_t iNumGroups, const int32_t *piGroupLengths, int32_t **ppiRMSEnvelope, float **ppfReal, float **ppfImag );
static int32_t CountLCLDBits( const int32_t iNumGroups, const int32_t *piGroupLengths, const int32_t iNumBands, const int32_t *piBandwidths, const int32_t *piPredEnable, int32_t **ppiAlloc, int32_t **ppiQReal, int32_t **ppiQImag ); static int32_t CountLCLDBits( const int32_t iNumGroups, const int32_t *piGroupLengths, const int32_t iNumBands, const int32_t *piBandwidths, const int32_t *piPredEnable, int32_t **ppiAlloc, int32_t **ppiQReal, int32_t **ppiQImag );
static int32_t WriteHeaderInformation( const int32_t iNumBands, IVAS_SPLIT_REND_BITS_HANDLE pBits ); static int32_t WriteHeaderInformation( const int32_t iNumBands, ISAR_SPLIT_REND_BITS_HANDLE pBits );
static int32_t WriteMSInformation( const int32_t iNumBands, const int32_t iMSMode, const int32_t *piMSFlags, const int32_t *piLRPhaseDiffs, const int32_t *piMSPredCoefs, int32_t iNumMSPredBands, IVAS_SPLIT_REND_BITS_HANDLE pBits ); static int32_t WriteMSInformation( const int32_t iNumBands, const int32_t iMSMode, const int32_t *piMSFlags, const int32_t *piLRPhaseDiffs, const int32_t *piMSPredCoefs, int32_t iNumMSPredBands, ISAR_SPLIT_REND_BITS_HANDLE pBits );
static int32_t WriteGroupInformation( const int32_t iChannels, const int32_t iCommonGrouping, const int32_t *piNumGroups, int32_t **ppiGroupLengths, IVAS_SPLIT_REND_BITS_HANDLE pBits ); static int32_t WriteGroupInformation( const int32_t iChannels, const int32_t iCommonGrouping, const int32_t *piNumGroups, int32_t **ppiGroupLengths, ISAR_SPLIT_REND_BITS_HANDLE pBits );
static int32_t WriteRMSEnvelope( const int32_t iChannels, const int32_t *piNumGroups, const int32_t iNumBands, int32_t ***pppiRMSEnvelope, IVAS_SPLIT_REND_BITS_HANDLE pBits ); static int32_t WriteRMSEnvelope( const int32_t iChannels, const int32_t *piNumGroups, const int32_t iNumBands, int32_t ***pppiRMSEnvelope, ISAR_SPLIT_REND_BITS_HANDLE pBits );
static int32_t WriteAllocInformation( const int32_t iAllocOffset, IVAS_SPLIT_REND_BITS_HANDLE pBits ); static int32_t WriteAllocInformation( const int32_t iAllocOffset, ISAR_SPLIT_REND_BITS_HANDLE pBits );
static int32_t WriteLCLDData( const int32_t iNumGroups, const int32_t *piGroupLengths, const int32_t iNumBands, const int32_t *piBandwidths, const int32_t *piPredEnable, int32_t **ppiAlloc, int32_t **ppiSignReal, int32_t **ppiSignImag, int32_t **ppiQReal, int32_t **ppiQImag, IVAS_SPLIT_REND_BITS_HANDLE pBits ); static int32_t WriteLCLDData( const int32_t *piNumGroups, int32_t **ppiGroupLengths, const int32_t iNumBands, const int32_t iNumChannels, int32_t **ppiPredEnable, const int32_t iNumSubSets, const int32_t iSubSetId, int32_t ***pppiAlloc, int32_t ***pppiSignReal, int32_t ***pppiSignImag, int32_t ***pppiQReal, int32_t ***pppiQImag, ISAR_SPLIT_REND_BITS_HANDLE pBits );
static int32_t ComputeAllocation( const int32_t iChannels, const int32_t *piNumGroups, int32_t **ppiGroupLengths, const int32_t iNumBands, const int32_t *piBandwidths, float ***pppfReal, float ***pppfImag, int32_t ***pppiSMR, const int32_t iAvailableBits, int32_t *piAllocOffset, int32_t ***pppiAlloc, int32_t ***pppiQReal, int32_t ***pppiQImag, int32_t ***pppiSignReal, int32_t ***pppiSignImag, PredictionEncoder *psPredictionEncoder ); static int32_t ComputeAllocation( const int32_t iChannels, const int32_t *piNumGroups, int32_t **ppiGroupLengths, const int32_t iNumBands, const int32_t *piBandwidths, float ***pppfReal, float ***pppfImag, int32_t ***pppiSMR, const int32_t iAvailableBits, int32_t *piAllocOffset, int32_t ***pppiAlloc, int32_t ***pppiQReal, int32_t ***pppiQImag, int32_t ***pppiSignReal, int32_t ***pppiSignImag, PredictionEncoder *psPredictionEncoder );
...@@ -537,15 +563,22 @@ int32_t EncodeLCLDFrame( ...@@ -537,15 +563,22 @@ int32_t EncodeLCLDFrame(
float ***pppfLCLDImag, float ***pppfLCLDImag,
int32_t *piBitsWritten, int32_t *piBitsWritten,
const int32_t available_bits, const int32_t available_bits,
IVAS_SPLIT_REND_BITS_HANDLE pBits ) ISAR_SPLIT_REND_BITS_HANDLE pBits )
{ {
int32_t n; int32_t n;
int32_t iAvailableBits, iBitsWritten; int32_t iAvailableBits, iBitsWritten;
int32_t iNumMSBands = 0; int32_t iNumMSBands = 0;
iAvailableBits = available_bits; // HCBR for now int32_t iAudioBitsWritten;
iAvailableBits = available_bits; /* HCBR for now*/
iBitsWritten = 0; iBitsWritten = 0;
assert( available_bits <= pBits->buf_len * 8 ); assert( available_bits <= pBits->buf_len * 8 );
if ( psLCLDEncoder->iRealOnlyOut == 1 )
{
PackReal( psLCLDEncoder->iChannels, psLCLDEncoder->iNumBlocks * 2, pppfLCLDReal, pppfLCLDImag );
}
/* Do MS calc here */ /* Do MS calc here */
if ( psLCLDEncoder->iChannels == 2 ) if ( psLCLDEncoder->iChannels == 2 )
{ {
...@@ -558,11 +591,12 @@ int32_t EncodeLCLDFrame( ...@@ -558,11 +591,12 @@ int32_t EncodeLCLDFrame(
psLCLDEncoder->piLRPhaseDiffs, psLCLDEncoder->piLRPhaseDiffs,
psLCLDEncoder->piMSPredCoefs, psLCLDEncoder->piMSPredCoefs,
psLCLDEncoder->iAllowSidePred, psLCLDEncoder->iAllowSidePred,
psLCLDEncoder->iRealOnlyOut,
psLCLDEncoder->piMSFlags ); psLCLDEncoder->piMSFlags );
if ( psLCLDEncoder->iMSMode > 0 ) if ( psLCLDEncoder->iMSMode > 0 )
{ {
psLCLDEncoder->iCommonGrouping = 1; // Make sure common grouping is enabled when MS is in use psLCLDEncoder->iCommonGrouping = 1; /* Make sure common grouping is enabled when MS is in use */
} }
} }
...@@ -699,36 +733,26 @@ int32_t EncodeLCLDFrame( ...@@ -699,36 +733,26 @@ int32_t EncodeLCLDFrame(
iBitsWritten += WriteAllocInformation( psLCLDEncoder->iAllocOffset, iBitsWritten += WriteAllocInformation( psLCLDEncoder->iAllocOffset,
pBits ); pBits );
iAudioBitsWritten = iBitsWritten;
for ( n = 0; n < psLCLDEncoder->iChannels; n++ ) iBitsWritten += WriteLCLDData( psLCLDEncoder->piNumGroups,
{ psLCLDEncoder->ppiGroupLengths,
iBitsWritten += WriteLCLDData( psLCLDEncoder->piNumGroups[n],
(const int32_t *) psLCLDEncoder->ppiGroupLengths[n],
psLCLDEncoder->iNumBands, psLCLDEncoder->iNumBands,
psLCLDEncoder->piBandwidths, psLCLDEncoder->iChannels,
(const int32_t *) psLCLDEncoder->psPredictionEncoder->ppiPredBandEnable[n], psLCLDEncoder->psPredictionEncoder->ppiPredBandEnable,
psLCLDEncoder->pppiAlloc[n], psLCLDEncoder->psPredictionEncoder->iNumSubSets,
psLCLDEncoder->pppiLCLDSignReal[n], psLCLDEncoder->psPredictionEncoder->iSubSetId,
psLCLDEncoder->pppiLCLDSignImag[n], psLCLDEncoder->pppiAlloc,
psLCLDEncoder->pppiQLCLDReal[n], psLCLDEncoder->pppiLCLDSignReal,
psLCLDEncoder->pppiQLCLDImag[n], psLCLDEncoder->pppiLCLDSignImag,
psLCLDEncoder->pppiQLCLDReal,
psLCLDEncoder->pppiQLCLDImag,
pBits ); pBits );
}
*piBitsWritten = iBitsWritten; *piBitsWritten = iBitsWritten;
iAudioBitsWritten = iBitsWritten - iAudioBitsWritten;
return 0; UpdatePredictionSubSetId( psLCLDEncoder->psPredictionEncoder );
}
return 0;
/*------------------------------------------------------------------------------------------*
* Function GetNumGroups()
*
*
*------------------------------------------------------------------------------------------*/
int32_t GetNumGroups( LCLDEncoder *psLCLDEncoder )
{
return psLCLDEncoder->piNumGroups[0];
} }
...@@ -763,6 +787,7 @@ static int32_t MSModeCalculation( ...@@ -763,6 +787,7 @@ static int32_t MSModeCalculation(
int32_t *piLRPhaseDiffs, int32_t *piLRPhaseDiffs,
int32_t *piMSPredCoefs, int32_t *piMSPredCoefs,
const int32_t iAllowSidePred, const int32_t iAllowSidePred,
const int32_t iRealOnlyOut,
int32_t *piMSFlags ) int32_t *piMSFlags )
{ {
int32_t b; int32_t b;
...@@ -770,25 +795,39 @@ static int32_t MSModeCalculation( ...@@ -770,25 +795,39 @@ static int32_t MSModeCalculation(
int32_t iNumMSBands; int32_t iNumMSBands;
int32_t iMSPredType; int32_t iMSPredType;
float fMSBitGain = 0.0f; float fMSBitGain = 0.0f;
float pfMSPredBitGain[3] = { 0.0f }; float pfMSPredBitGain[3];
float fPred; float fPred;
int32_t piMSPredFlags0[MAX_BANDS] = { 0 }; int32_t piMSPredFlags0[MAX_BANDS];
int32_t piMSPredFlags1[MAX_BANDS] = { 0 }; int32_t piMSPredFlags1[MAX_BANDS];
int32_t piMSPredFlags2[MAX_BANDS] = { 0 }; int32_t piMSPredFlags2[MAX_BANDS];
int32_t *ppiMSPredFlags[3]; int32_t *ppiMSPredFlags[3];
int32_t piMSPredCoefs0[MAX_BANDS] = { 0 }; int32_t piMSPredCoefs0[MAX_BANDS];
int32_t piMSPredCoefs1[MAX_BANDS] = { 0 }; int32_t piMSPredCoefs1[MAX_BANDS];
int32_t piMSPredCoefs2[MAX_BANDS] = { 0 }; int32_t piMSPredCoefs2[MAX_BANDS];
int32_t *ppiMSPredCoefs[3]; int32_t *ppiMSPredCoefs[3];
int32_t piMSPredPhase0[MAX_BANDS] = { 0 }; int32_t piMSPredPhase0[MAX_BANDS];
int32_t piMSPredPhase1[MAX_BANDS] = { 0 }; int32_t piMSPredPhase1[MAX_BANDS];
int32_t piMSPredPhase2[MAX_BANDS] = { 0 }; int32_t piMSPredPhase2[MAX_BANDS];
int32_t *ppiMSPredPhase[3]; int32_t *ppiMSPredPhase[3];
int32_t iMsInfoBits; int32_t iMsInfoBits;
int32_t piMsPredInfoBits[3] = { 0 }; int32_t piMsPredInfoBits[3];
const float feps = 1e-12f; const float feps = 1e-12f;
float fBitsFactor = 3.32192809488736f; /* = 1/log10(2), from dB/10 to bits assuming 1 bit per log2(SNR) or 1 bit per 3dB SNR */ float fBitsFactor = 3.32192809488736f; /* = 1/log10(2), from dB/10 to bits assuming 1 bit per log2(SNR) or 1 bit per 3dB SNR */
set_zero( pfMSPredBitGain, 3 );
set_l( piMsPredInfoBits, 0, 3 );
set_l( piMSPredFlags0, 0, MAX_BANDS );
set_l( piMSPredFlags1, 0, MAX_BANDS );
set_l( piMSPredFlags2, 0, MAX_BANDS );
set_l( piMSPredCoefs0, 0, MAX_BANDS );
set_l( piMSPredCoefs1, 0, MAX_BANDS );
set_l( piMSPredCoefs2, 0, MAX_BANDS );
set_l( piMSPredPhase0, 0, MAX_BANDS );
set_l( piMSPredPhase1, 0, MAX_BANDS );
set_l( piMSPredPhase2, 0, MAX_BANDS );
if ( iNumBlocks < LCLD_BLOCKS_PER_FRAME ) if ( iNumBlocks < LCLD_BLOCKS_PER_FRAME )
{ {
fBitsFactor *= ( 0.7f + (float) ( iNumBlocks - 4 ) / (float) ( LCLD_BLOCKS_PER_FRAME - 4 ) * ( 1.0f - 0.7f ) ); /* Tuning for relatively higher side rate due to shorter frame length */ fBitsFactor *= ( 0.7f + (float) ( iNumBlocks - 4 ) / (float) ( LCLD_BLOCKS_PER_FRAME - 4 ) * ( 1.0f - 0.7f ) ); /* Tuning for relatively higher side rate due to shorter frame length */
...@@ -826,7 +865,7 @@ static int32_t MSModeCalculation( ...@@ -826,7 +865,7 @@ static int32_t MSModeCalculation(
int32_t iPhase; int32_t iPhase;
int32_t iPred; int32_t iPred;
int32_t tabIdx = 0; int32_t tabIdx = 0;
float fNumLines = (float) ( iNumBlocks * piBandwidths[b] * 2 ); /* per band per channel */ float fNumLines = (float) ( iRealOnlyOut == 1 ? iNumBlocks * piBandwidths[b] * 4 : iNumBlocks * piBandwidths[b] * 2 ); /* per band per channel */
float fLevelToSMRdBFactor = (float) c_aiDefaultTheta48[b] / (float) ( 1 << PERCEPTUAL_MODEL_SLGAIN_SHIFT ); /* frequency dependent SMR slope in psy model */ float fLevelToSMRdBFactor = (float) c_aiDefaultTheta48[b] / (float) ( 1 << PERCEPTUAL_MODEL_SLGAIN_SHIFT ); /* frequency dependent SMR slope in psy model */
fLeftEnergy = 0.0f; fLeftEnergy = 0.0f;
fRightEnergy = 0.0f; fRightEnergy = 0.0f;
...@@ -880,7 +919,7 @@ static int32_t MSModeCalculation( ...@@ -880,7 +919,7 @@ static int32_t MSModeCalculation(
/* adjust covariance */ /* adjust covariance */
tabIdx = iPhase - PHASE_MIN_VAL; tabIdx = iPhase - PHASE_MIN_VAL;
cplxmult( &fLRCovReal, &fLRCovImag, c_afRotRealImag[tabIdx][0], -c_afRotRealImag[tabIdx][1] ); cplxmult_lcld( &fLRCovReal, &fLRCovImag, c_afRotRealImag[tabIdx][0], -c_afRotRealImag[tabIdx][1] );
/* compute MS prediction coefficient based on adjusted covariance */ /* compute MS prediction coefficient based on adjusted covariance */
fMidEnergyPred = 0.25f * ( fLeftEnergy + fRightEnergy + 2.0f * fLRCovReal ); fMidEnergyPred = 0.25f * ( fLeftEnergy + fRightEnergy + 2.0f * fLRCovReal );
...@@ -942,9 +981,16 @@ static int32_t MSModeCalculation( ...@@ -942,9 +981,16 @@ static int32_t MSModeCalculation(
} }
/* find the best M/S Pred type */ /* find the best M/S Pred type */
if ( iRealOnlyOut == 1 )
{
iMSPredType = MS_PRED_ONLY;
}
else
{
iMSPredType = MS_PHASE_AND_PRED; iMSPredType = MS_PHASE_AND_PRED;
iMSPredType = ( pfMSPredBitGain[MS_PRED_ONLY] > pfMSPredBitGain[iMSPredType] ? MS_PRED_ONLY : iMSPredType ); iMSPredType = ( pfMSPredBitGain[MS_PRED_ONLY] > pfMSPredBitGain[iMSPredType] ? MS_PRED_ONLY : iMSPredType );
iMSPredType = ( pfMSPredBitGain[MS_PHASE_ONLY] > pfMSPredBitGain[iMSPredType] ? MS_PHASE_ONLY : iMSPredType ); iMSPredType = ( pfMSPredBitGain[MS_PHASE_ONLY] > pfMSPredBitGain[iMSPredType] ? MS_PHASE_ONLY : iMSPredType );
}
/* plain M/S */ /* plain M/S */
iMsInfoBits = CountMSBits( iNumBands, MS_SOME, piMSFlags, NULL, NULL ); iMsInfoBits = CountMSBits( iNumBands, MS_SOME, piMSFlags, NULL, NULL );
...@@ -1013,7 +1059,7 @@ static int32_t MSModeCalculation( ...@@ -1013,7 +1059,7 @@ static int32_t MSModeCalculation(
if ( *piMSMode == MS_PRED ) if ( *piMSMode == MS_PRED )
{ {
cplxmult( &pppfReal[1][k][iFBOffset], &pppfImag[1][k][iFBOffset], c_afRotRealImag[phaseIdx][0], c_afRotRealImag[phaseIdx][1] ); cplxmult_lcld( &pppfReal[1][k][iFBOffset], &pppfImag[1][k][iFBOffset], c_afRotRealImag[phaseIdx][0], c_afRotRealImag[phaseIdx][1] );
} }
fMidReal = 0.5f * ( pppfReal[0][k][iFBOffset] + pppfReal[1][k][iFBOffset] ); fMidReal = 0.5f * ( pppfReal[0][k][iFBOffset] + pppfReal[1][k][iFBOffset] );
...@@ -1120,9 +1166,9 @@ static void QuantizeSpectrumDPCM_Opt( ...@@ -1120,9 +1166,9 @@ static void QuantizeSpectrumDPCM_Opt(
int32_t **ppiQImag, int32_t **ppiQImag,
int32_t **ppiSignReal, int32_t **ppiSignReal,
int32_t **ppiSignImag, int32_t **ppiSignImag,
int32_t iNumSubSets, const int32_t iNumSubSets,
int32_t iSubSetId, const int32_t iSubSetId,
int32_t *piPredEnable, const int32_t *piPredEnable,
float *pfA1Real, float *pfA1Real,
float *pfA1Imag, float *pfA1Imag,
float *pfPredStateReal, float *pfPredStateReal,
...@@ -1314,12 +1360,12 @@ static int32_t CountLCLDBits( ...@@ -1314,12 +1360,12 @@ static int32_t CountLCLDBits(
/* Currently only the number of bands in frame */ /* Currently only the number of bands in frame */
static int32_t WriteHeaderInformation( static int32_t WriteHeaderInformation(
const int32_t iNumBands, const int32_t iNumBands,
IVAS_SPLIT_REND_BITS_HANDLE pBits ) ISAR_SPLIT_REND_BITS_HANDLE pBits )
{ {
int32_t iBitsWritten; int32_t iBitsWritten;
iBitsWritten = 0; iBitsWritten = 0;
ivas_split_rend_bitstream_write_int32( pBits, iNumBands, 5 ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, iNumBands, 5 );
iBitsWritten += 5; iBitsWritten += 5;
return iBitsWritten; return iBitsWritten;
...@@ -1333,7 +1379,7 @@ static int32_t WriteMSInformation( ...@@ -1333,7 +1379,7 @@ static int32_t WriteMSInformation(
const int32_t *piLRPhaseDiff, const int32_t *piLRPhaseDiff,
const int32_t *piMSPredCoef, const int32_t *piMSPredCoef,
int32_t iNumMSPredBands, int32_t iNumMSPredBands,
IVAS_SPLIT_REND_BITS_HANDLE pBits ) ISAR_SPLIT_REND_BITS_HANDLE pBits )
{ {
int32_t iBitsWritten; int32_t iBitsWritten;
int32_t iMSPredAll = ( iNumMSPredBands == iNumBands ); int32_t iMSPredAll = ( iNumMSPredBands == iNumBands );
...@@ -1341,12 +1387,12 @@ static int32_t WriteMSInformation( ...@@ -1341,12 +1387,12 @@ static int32_t WriteMSInformation(
int32_t iBitsWrittenTmp = 0; int32_t iBitsWrittenTmp = 0;
#endif #endif
iBitsWritten = 0; iBitsWritten = 0;
ivas_split_rend_bitstream_write_int32( pBits, iMSMode, 2 ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, iMSMode, 2 );
iBitsWritten += 2; iBitsWritten += 2;
if ( iMSMode == 3 ) if ( iMSMode == 3 )
{ {
ivas_split_rend_bitstream_write_int32( pBits, iMSPredAll, 1 ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, iMSPredAll, 1 );
iBitsWritten += 1; iBitsWritten += 1;
} }
...@@ -1355,7 +1401,7 @@ static int32_t WriteMSInformation( ...@@ -1355,7 +1401,7 @@ static int32_t WriteMSInformation(
int32_t n; int32_t n;
for ( n = 0; n < iNumBands; n++ ) for ( n = 0; n < iNumBands; n++ )
{ {
ivas_split_rend_bitstream_write_int32( pBits, piMSFlags[n], 1 ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, piMSFlags[n], 1 );
iBitsWritten += 1; iBitsWritten += 1;
} }
} }
...@@ -1376,17 +1422,17 @@ static int32_t WriteMSInformation( ...@@ -1376,17 +1422,17 @@ static int32_t WriteMSInformation(
break; break;
} }
} }
ivas_split_rend_bitstream_write_int32( pBits, anyNonZero, 1 ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, anyNonZero, 1 );
iBitsWritten++; iBitsWritten++;
if ( anyNonZero ) if ( anyNonZero )
{ {
ivas_split_rend_bitstream_write_int32( pBits, piLRPhaseDiff[0] - PHASE_MIN_VAL, PHASE_BAND0_BITS ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, piLRPhaseDiff[0] - PHASE_MIN_VAL, PHASE_BAND0_BITS );
iBitsWritten += PHASE_BAND0_BITS; iBitsWritten += PHASE_BAND0_BITS;
for ( b = 1; b < iNumMSPredBands; b++ ) for ( b = 1; b < iNumMSPredBands; b++ )
{ {
int32_t tabIdx = piLRPhaseDiff[b] - ENV_DELTA_MIN; int32_t tabIdx = piLRPhaseDiff[b] - ENV_DELTA_MIN;
ivas_split_rend_bitstream_write_int32( pBits, c_aaiRMSEnvHuffEnc[tabIdx][1], c_aaiRMSEnvHuffEnc[tabIdx][0] ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, c_aaiRMSEnvHuffEnc[tabIdx][1], c_aaiRMSEnvHuffEnc[tabIdx][0] );
iBitsWritten += c_aaiRMSEnvHuffEnc[tabIdx][0]; iBitsWritten += c_aaiRMSEnvHuffEnc[tabIdx][0];
} }
} }
...@@ -1401,17 +1447,17 @@ static int32_t WriteMSInformation( ...@@ -1401,17 +1447,17 @@ static int32_t WriteMSInformation(
} }
} }
ivas_split_rend_bitstream_write_int32( pBits, anyNonZero, 1 ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, anyNonZero, 1 );
iBitsWritten++; iBitsWritten++;
if ( anyNonZero ) if ( anyNonZero )
{ {
ivas_split_rend_bitstream_write_int32( pBits, piMSPredCoef[0] - PRED_MIN_VAL, PRED_BAND0_BITS ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, piMSPredCoef[0] - PRED_MIN_VAL, PRED_BAND0_BITS );
iBitsWritten += PRED_BAND0_BITS; iBitsWritten += PRED_BAND0_BITS;
for ( b = 1; b < iNumMSPredBands; b++ ) for ( b = 1; b < iNumMSPredBands; b++ )
{ {
int32_t tabIdx = piMSPredCoef[b] - ENV_DELTA_MIN; int32_t tabIdx = piMSPredCoef[b] - ENV_DELTA_MIN;
ivas_split_rend_bitstream_write_int32( pBits, c_aaiRMSEnvHuffEnc[tabIdx][1], c_aaiRMSEnvHuffEnc[tabIdx][0] ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, c_aaiRMSEnvHuffEnc[tabIdx][1], c_aaiRMSEnvHuffEnc[tabIdx][0] );
iBitsWritten += c_aaiRMSEnvHuffEnc[tabIdx][0]; iBitsWritten += c_aaiRMSEnvHuffEnc[tabIdx][0];
} }
} }
...@@ -1436,33 +1482,33 @@ static int32_t WriteGroupInformation( ...@@ -1436,33 +1482,33 @@ static int32_t WriteGroupInformation(
const int32_t iCommonGrouping, const int32_t iCommonGrouping,
const int32_t *piNumGroups, const int32_t *piNumGroups,
int32_t **ppiGroupLengths, int32_t **ppiGroupLengths,
IVAS_SPLIT_REND_BITS_HANDLE pBits ) ISAR_SPLIT_REND_BITS_HANDLE pBits )
{ {
int32_t c, k, n, iBitsWritten; int32_t c, k, n, iBitsWritten;
iBitsWritten = 0; iBitsWritten = 0;
if ( iChannels == 2 && iCommonGrouping == 1 ) if ( iChannels == 2 && iCommonGrouping == 1 )
{ {
ivas_split_rend_bitstream_write_int32( pBits, iCommonGrouping, 1 ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, iCommonGrouping, 1 );
iBitsWritten += 1; iBitsWritten += 1;
for ( n = 0; n < piNumGroups[0]; n++ ) for ( n = 0; n < piNumGroups[0]; n++ )
{ {
for ( k = 1; k < ppiGroupLengths[0][n]; k++ ) for ( k = 1; k < ppiGroupLengths[0][n]; k++ )
{ {
ivas_split_rend_bitstream_write_int32( pBits, 0, 1 ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, 0, 1 );
iBitsWritten += 1; iBitsWritten += 1;
} }
if ( n < ( piNumGroups[0] - 1 ) ) if ( n < ( piNumGroups[0] - 1 ) )
{ {
ivas_split_rend_bitstream_write_int32( pBits, 1, 1 ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, 1, 1 );
iBitsWritten += 1; iBitsWritten += 1;
} }
} }
} }
else if ( iChannels == 2 ) else if ( iChannels == 2 )
{ {
ivas_split_rend_bitstream_write_int32( pBits, iCommonGrouping, 1 ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, iCommonGrouping, 1 );
iBitsWritten += 1; iBitsWritten += 1;
for ( c = 0; c < iChannels; c++ ) for ( c = 0; c < iChannels; c++ )
...@@ -1471,12 +1517,12 @@ static int32_t WriteGroupInformation( ...@@ -1471,12 +1517,12 @@ static int32_t WriteGroupInformation(
{ {
for ( k = 1; k < ppiGroupLengths[c][n]; k++ ) for ( k = 1; k < ppiGroupLengths[c][n]; k++ )
{ {
ivas_split_rend_bitstream_write_int32( pBits, 0, 1 ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, 0, 1 );
iBitsWritten += 1; iBitsWritten += 1;
} }
if ( n < ( piNumGroups[c] - 1 ) ) if ( n < ( piNumGroups[c] - 1 ) )
{ {
ivas_split_rend_bitstream_write_int32( pBits, 1, 1 ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, 1, 1 );
iBitsWritten += 1; iBitsWritten += 1;
} }
} }
...@@ -1490,13 +1536,13 @@ static int32_t WriteGroupInformation( ...@@ -1490,13 +1536,13 @@ static int32_t WriteGroupInformation(
{ {
for ( k = 1; k < ppiGroupLengths[c][n]; k++ ) for ( k = 1; k < ppiGroupLengths[c][n]; k++ )
{ {
ivas_split_rend_bitstream_write_int32( pBits, 0, 1 ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, 0, 1 );
iBitsWritten += 1; iBitsWritten += 1;
} }
if ( n < ( piNumGroups[c] - 1 ) ) if ( n < ( piNumGroups[c] - 1 ) )
{ {
ivas_split_rend_bitstream_write_int32( pBits, 1, 1 ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, 1, 1 );
iBitsWritten += 1; iBitsWritten += 1;
} }
} }
...@@ -1512,7 +1558,7 @@ static int32_t WriteRMSEnvelope( ...@@ -1512,7 +1558,7 @@ static int32_t WriteRMSEnvelope(
const int32_t *piNumGroups, const int32_t *piNumGroups,
const int32_t iNumBands, const int32_t iNumBands,
int32_t ***pppiRMSEnvelope, int32_t ***pppiRMSEnvelope,
IVAS_SPLIT_REND_BITS_HANDLE pBits ) ISAR_SPLIT_REND_BITS_HANDLE pBits )
{ {
int32_t k, n; int32_t k, n;
int32_t iBitsWritten; int32_t iBitsWritten;
...@@ -1528,7 +1574,7 @@ static int32_t WriteRMSEnvelope( ...@@ -1528,7 +1574,7 @@ static int32_t WriteRMSEnvelope(
iLastRMSVal = pppiRMSEnvelope[n][k][0]; iLastRMSVal = pppiRMSEnvelope[n][k][0];
iLastRMSVal = ( iLastRMSVal > ENV_MIN ) ? iLastRMSVal : ENV_MIN; iLastRMSVal = ( iLastRMSVal > ENV_MIN ) ? iLastRMSVal : ENV_MIN;
iLastRMSVal = ( iLastRMSVal < ENV_MAX ) ? iLastRMSVal : ENV_MAX; iLastRMSVal = ( iLastRMSVal < ENV_MAX ) ? iLastRMSVal : ENV_MAX;
ivas_split_rend_bitstream_write_int32( pBits, ( iLastRMSVal - ENV_MIN ), ENV0_BITS ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, ( iLastRMSVal - ENV_MIN ), ENV0_BITS );
iBitsWritten += ENV0_BITS; iBitsWritten += ENV0_BITS;
for ( b = 1; b < iNumBands; b++ ) for ( b = 1; b < iNumBands; b++ )
...@@ -1539,7 +1585,7 @@ static int32_t WriteRMSEnvelope( ...@@ -1539,7 +1585,7 @@ static int32_t WriteRMSEnvelope(
iDelta = ( iDelta > ENV_DELTA_MIN ) ? iDelta : ENV_DELTA_MIN; iDelta = ( iDelta > ENV_DELTA_MIN ) ? iDelta : ENV_DELTA_MIN;
iDelta = ( iDelta < ENV_DELTA_MAX ) ? iDelta : ENV_DELTA_MAX; iDelta = ( iDelta < ENV_DELTA_MAX ) ? iDelta : ENV_DELTA_MAX;
iDelta -= ENV_DELTA_MIN; iDelta -= ENV_DELTA_MIN;
ivas_split_rend_bitstream_write_int32( pBits, c_aaiRMSEnvHuffEnc[iDelta][1], c_aaiRMSEnvHuffEnc[iDelta][0] ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, c_aaiRMSEnvHuffEnc[iDelta][1], c_aaiRMSEnvHuffEnc[iDelta][0] );
iBitsWritten += c_aaiRMSEnvHuffEnc[iDelta][0]; iBitsWritten += c_aaiRMSEnvHuffEnc[iDelta][0];
iLastRMSVal = pppiRMSEnvelope[n][k][b]; iLastRMSVal = pppiRMSEnvelope[n][k][b];
...@@ -1553,7 +1599,7 @@ static int32_t WriteRMSEnvelope( ...@@ -1553,7 +1599,7 @@ static int32_t WriteRMSEnvelope(
static int32_t WriteAllocInformation( static int32_t WriteAllocInformation(
const int32_t iAllocOffset, const int32_t iAllocOffset,
IVAS_SPLIT_REND_BITS_HANDLE pBits ) ISAR_SPLIT_REND_BITS_HANDLE pBits )
{ {
int32_t iBitsWritten; int32_t iBitsWritten;
...@@ -1564,50 +1610,61 @@ static int32_t WriteAllocInformation( ...@@ -1564,50 +1610,61 @@ static int32_t WriteAllocInformation(
printf( "Serious error\n" ); printf( "Serious error\n" );
} }
ivas_split_rend_bitstream_write_int32( pBits, ( iAllocOffset - MIN_ALLOC_OFFSET ), ALLOC_OFFSET_BITS ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, ( iAllocOffset - MIN_ALLOC_OFFSET ), ALLOC_OFFSET_BITS );
iBitsWritten += ALLOC_OFFSET_BITS; iBitsWritten += ALLOC_OFFSET_BITS;
return iBitsWritten; return iBitsWritten;
} }
static int32_t WriteLCLDData( static int32_t WriteLCLDData(
const int32_t iNumGroups, const int32_t *piNumGroups,
const int32_t *piGroupLengths, int32_t **ppiGroupLengths,
const int32_t iNumBands, const int32_t iNumBands,
const int32_t *piBandwidths, const int32_t iNumChannels,
const int32_t *piPredEnable, int32_t **ppiPredEnable,
int32_t **ppiAlloc, const int32_t iNumSubSets,
int32_t **ppiSignReal, const int32_t iSubSetId,
int32_t **ppiSignImag, int32_t ***pppiAlloc,
int32_t **ppiQReal, int32_t ***pppiSignReal,
int32_t **ppiQImag, int32_t ***pppiSignImag,
IVAS_SPLIT_REND_BITS_HANDLE pBits ) int32_t ***pppiQReal,
int32_t ***pppiQImag,
ISAR_SPLIT_REND_BITS_HANDLE pBits )
{ {
int32_t n;
int32_t iBitsWritten; int32_t iBitsWritten;
int32_t iBlockOffest; int32_t iNumLcldBands = c_aiNumLcldBandsPerBand[iNumBands - 1];
int32_t s;
int32_t iSet = iSubSetId;
iBitsWritten = 0; iBitsWritten = 0;
iBlockOffest = 0; for ( s = 0; s < iNumSubSets; s++, iSet-- )
{
int32_t ch;
if ( iSet < 0 )
{
iSet = iNumSubSets - 1;
}
for ( n = 0; n < iNumGroups; n++ ) for ( ch = 0; ch < iNumChannels; ch++ )
{
int32_t iBlockOffest = 0;
int32_t n;
for ( n = 0; n < piNumGroups[ch]; n++ )
{ {
int32_t k; int32_t k;
for ( k = 0; k < piGroupLengths[n]; k++ ) for ( k = 0; k < ppiGroupLengths[ch][n]; k++ )
{ {
int32_t b;
int32_t iFBOffset; int32_t iFBOffset;
for ( iFBOffset = iSet; iFBOffset < iNumLcldBands; iFBOffset += iNumSubSets )
iFBOffset = 0;
for ( b = 0; b < iNumBands; b++ )
{ {
int32_t m; int32_t b;
int32_t iAlloc; int32_t iAlloc;
int32_t iHuffDim; int32_t iHuffDim;
int32_t iHuffMod; int32_t iHuffMod;
iAlloc = ppiAlloc[n][b]; b = c_aiBandIdPerLcldBand[iFBOffset];
iAlloc = pppiAlloc[ch][n][b];
iHuffDim = c_aiHuffmanDim[iAlloc]; iHuffDim = c_aiHuffmanDim[iAlloc];
iHuffMod = c_aiHuffmanMod[iAlloc]; iHuffMod = c_aiHuffmanMod[iAlloc];
...@@ -1616,17 +1673,18 @@ static int32_t WriteLCLDData( ...@@ -1616,17 +1673,18 @@ static int32_t WriteLCLDData(
{ {
const uint16_t( *pauiHuffmanTable )[2] = NULL; const uint16_t( *pauiHuffmanTable )[2] = NULL;
const uint16_t( *pauiHuffmanTableDPCM )[2] = NULL; const uint16_t( *pauiHuffmanTableDPCM )[2] = NULL;
pauiHuffmanTable = c_apauiHuffEncTabels[iAlloc];
pauiHuffmanTableDPCM = c_apauiHuffEncTabels[ALLOC_TABLE_SIZE + iAlloc];
for ( m = 0; m < piBandwidths[b]; m++ )
{
int32_t iQuantValue1; int32_t iQuantValue1;
int32_t iQuantValue2; int32_t iQuantValue2;
pauiHuffmanTable = c_apauiHuffEncTabels[iAlloc];
pauiHuffmanTableDPCM = c_apauiHuffEncTabels[ALLOC_TABLE_SIZE + iAlloc];
iQuantValue1 = ppiQReal[iBlockOffest][iFBOffset]; iQuantValue1 = pppiQReal[ch][iBlockOffest][iFBOffset];
iQuantValue2 = ppiQImag[iBlockOffest][iFBOffset]; iQuantValue2 = pppiQImag[ch][iBlockOffest][iFBOffset];
#ifdef LCLD_HANDLE_PRED_START_SAMPLE
if ( piPredEnable[iFBOffset] == 1 ) if ( ppiPredEnable[ch][iFBOffset] == 1 && ( iBlockOffest > 0 || iSet != iSubSetId ) )
#else
if ( ppiPredEnable[ch][iFBOffset] == 1 )
#endif
{ {
if ( iHuffDim == 2 ) if ( iHuffDim == 2 )
{ {
...@@ -1634,15 +1692,15 @@ static int32_t WriteLCLDData( ...@@ -1634,15 +1692,15 @@ static int32_t WriteLCLDData(
iSymbol = iQuantValue1; iSymbol = iQuantValue1;
iSymbol *= iHuffMod; iSymbol *= iHuffMod;
iSymbol += iQuantValue2; iSymbol += iQuantValue2;
ivas_split_rend_bitstream_write_int32( pBits, pauiHuffmanTableDPCM[iSymbol][1], pauiHuffmanTableDPCM[iSymbol][0] ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, pauiHuffmanTableDPCM[iSymbol][1], pauiHuffmanTableDPCM[iSymbol][0] );
iBitsWritten += pauiHuffmanTableDPCM[iSymbol][0]; iBitsWritten += pauiHuffmanTableDPCM[iSymbol][0];
} }
else else
{ {
ivas_split_rend_bitstream_write_int32( pBits, pauiHuffmanTableDPCM[iQuantValue1][1], pauiHuffmanTableDPCM[iQuantValue1][0] ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, pauiHuffmanTableDPCM[iQuantValue1][1], pauiHuffmanTableDPCM[iQuantValue1][0] );
iBitsWritten += pauiHuffmanTableDPCM[iQuantValue1][0]; iBitsWritten += pauiHuffmanTableDPCM[iQuantValue1][0];
ivas_split_rend_bitstream_write_int32( pBits, pauiHuffmanTableDPCM[iQuantValue2][1], pauiHuffmanTableDPCM[iQuantValue2][0] ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, pauiHuffmanTableDPCM[iQuantValue2][1], pauiHuffmanTableDPCM[iQuantValue2][0] );
iBitsWritten += pauiHuffmanTableDPCM[iQuantValue2][0]; iBitsWritten += pauiHuffmanTableDPCM[iQuantValue2][0];
} }
} }
...@@ -1654,47 +1712,40 @@ static int32_t WriteLCLDData( ...@@ -1654,47 +1712,40 @@ static int32_t WriteLCLDData(
iSymbol = iQuantValue1; iSymbol = iQuantValue1;
iSymbol *= iHuffMod; iSymbol *= iHuffMod;
iSymbol += iQuantValue2; iSymbol += iQuantValue2;
ivas_split_rend_bitstream_write_int32( pBits, pauiHuffmanTable[iSymbol][1], pauiHuffmanTable[iSymbol][0] ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, pauiHuffmanTable[iSymbol][1], pauiHuffmanTable[iSymbol][0] );
iBitsWritten += pauiHuffmanTable[iSymbol][0]; iBitsWritten += pauiHuffmanTable[iSymbol][0];
} }
else else
{ {
ivas_split_rend_bitstream_write_int32( pBits, pauiHuffmanTable[iQuantValue1][1], pauiHuffmanTable[iQuantValue1][0] ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, pauiHuffmanTable[iQuantValue1][1], pauiHuffmanTable[iQuantValue1][0] );
iBitsWritten += pauiHuffmanTable[iQuantValue1][0]; iBitsWritten += pauiHuffmanTable[iQuantValue1][0];
ivas_split_rend_bitstream_write_int32( pBits, pauiHuffmanTable[iQuantValue2][1], pauiHuffmanTable[iQuantValue2][0] ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, pauiHuffmanTable[iQuantValue2][1], pauiHuffmanTable[iQuantValue2][0] );
iBitsWritten += pauiHuffmanTable[iQuantValue2][0]; iBitsWritten += pauiHuffmanTable[iQuantValue2][0];
} }
} }
if ( iQuantValue1 > 0 ) if ( iQuantValue1 > 0 )
{ {
ivas_split_rend_bitstream_write_int32( pBits, ppiSignReal[iBlockOffest][iFBOffset], 1 ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, pppiSignReal[ch][iBlockOffest][iFBOffset], 1 );
iBitsWritten += 1; iBitsWritten += 1;
} }
if ( iQuantValue2 > 0 ) if ( iQuantValue2 > 0 )
{ {
ivas_split_rend_bitstream_write_int32( pBits, ppiSignImag[iBlockOffest][iFBOffset], 1 ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, pppiSignImag[ch][iBlockOffest][iFBOffset], 1 );
iBitsWritten += 1; iBitsWritten += 1;
} }
iFBOffset++;
} }
} }
else iBlockOffest++;
{
iFBOffset += piBandwidths[b];
} }
} }
iBlockOffest++;
} }
} }
return iBitsWritten; return iBitsWritten;
} }
static int32_t ComputeAllocation( static int32_t ComputeAllocation(
const int32_t iChannels, const int32_t iChannels,
const int32_t *piNumGroups, const int32_t *piNumGroups,
...@@ -1785,7 +1836,7 @@ static int32_t ComputeAllocation( ...@@ -1785,7 +1836,7 @@ static int32_t ComputeAllocation(
#ifdef DEBUG_VERBOSE #ifdef DEBUG_VERBOSE
printf( "Frame can not be coded with the number of bits available\n" ); printf( "Frame can not be coded with the number of bits available\n" );
#endif #endif
// iLastError = ENC_ERROR_STREAM_FAILURE; /* iLastError = ENC_ERROR_STREAM_FAILURE;*/
return -1; return -1;
} }
else if ( *piAllocOffset >= MAX_ALLOC_OFFSET && iBitsUsed < iAvailableBits ) else if ( *piAllocOffset >= MAX_ALLOC_OFFSET && iBitsUsed < iAvailableBits )
...@@ -1828,16 +1879,14 @@ static int32_t ComputeAllocation( ...@@ -1828,16 +1879,14 @@ static int32_t ComputeAllocation(
mvr2r( psPredictionEncoder->ppfPredStateRealTmp[n], psPredictionEncoder->ppfPredStateReal[n], LCLD_BANDS ); mvr2r( psPredictionEncoder->ppfPredStateRealTmp[n], psPredictionEncoder->ppfPredStateReal[n], LCLD_BANDS );
mvr2r( psPredictionEncoder->ppfPredStateImagTmp[n], psPredictionEncoder->ppfPredStateImag[n], LCLD_BANDS ); mvr2r( psPredictionEncoder->ppfPredStateImagTmp[n], psPredictionEncoder->ppfPredStateImag[n], LCLD_BANDS );
} }
if ( ++psPredictionEncoder->iSubSetId == psPredictionEncoder->iNumSubSets )
{
psPredictionEncoder->iSubSetId = 0;
}
} }
// printf("%d\n",*piAllocOffset); /*
// printf("%d\t%d\t%d\n",pppiAlloc[0][0][0],pppiAlloc[0][0][1],pppiAlloc[0][0][22]); printf("%d\n",*piAllocOffset);
printf("%d\t%d\t%d\n",pppiAlloc[0][0][0],pppiAlloc[0][0][1],pppiAlloc[0][0][22]);
// printf("%d\t%d\t%d\t%d\n",*piAllocOffset,iAvailableBits,iBitsUsed,iAvailableBits - iBitsUsed); printf("%d\t%d\t%d\t%d\n",*piAllocOffset,iAvailableBits,iBitsUsed,iAvailableBits - iBitsUsed);
*/
return iBitsUsed; return iBitsUsed;
} }
......
...@@ -30,13 +30,13 @@ ...@@ -30,13 +30,13 @@
*******************************************************************************************************/ *******************************************************************************************************/
#ifndef _IVAS_LCLD_ENCODER_H_ #ifndef ISAR_LCLD_PROT_H
#define _IVAS_LCLD_ENCODER_H_ #define ISAR_LCLD_PROT_H
#include "options.h" #include "options.h"
#ifdef SPLIT_REND_WITH_HEAD_ROT #ifdef SPLIT_REND_WITH_HEAD_ROT
#include "lib_rend.h" #include "common_api_types.h"
#include "ivas_lcld_rom_tables.h" #include "isar_rom_lcld_tables.h"
/* clang-format off */ /* clang-format off */
...@@ -49,7 +49,9 @@ ivas_error CreateLCLDEncoder( ...@@ -49,7 +49,9 @@ ivas_error CreateLCLDEncoder(
const int32_t iTargetBitRate, const int32_t iTargetBitRate,
const int32_t iAllowSidePred, const int32_t iAllowSidePred,
const int16_t iNumBlocks, const int16_t iNumBlocks,
const int16_t iNumSubSets ); const int16_t iNumSubSets,
const int32_t iRealOnlyOut
);
void DeleteLCLDEncoder( void DeleteLCLDEncoder(
LCLDEncoder *psLCLDEncoder LCLDEncoder *psLCLDEncoder
...@@ -61,11 +63,7 @@ int32_t EncodeLCLDFrame( ...@@ -61,11 +63,7 @@ int32_t EncodeLCLDFrame(
float ***pppfLCLDImag, float ***pppfLCLDImag,
int32_t *piNumiBites, int32_t *piNumiBites,
const int32_t available_bits, const int32_t available_bits,
IVAS_SPLIT_REND_BITS_HANDLE pBits ); ISAR_SPLIT_REND_BITS_HANDLE pBits );
int32_t GetNumGroups(
LCLDEncoder *psLCLDEncoder
);
typedef struct LCLD_DECODER LCLDDecoder; typedef struct LCLD_DECODER LCLDDecoder;
...@@ -74,7 +72,8 @@ ivas_error CreateLCLDDecoder( ...@@ -74,7 +72,8 @@ ivas_error CreateLCLDDecoder(
LCLDDecoder **psLCLDDecoder_out, LCLDDecoder **psLCLDDecoder_out,
const int32_t iSampleRate, const int32_t iSampleRate,
const int32_t iChannels, const int32_t iChannels,
const int32_t iNumBlocks ); const int32_t iNumBlocks,
const int32_t iRealOnlyOut);
void DeleteLCLDDecoder( void DeleteLCLDDecoder(
LCLDDecoder *psLCLDDecoder LCLDDecoder *psLCLDDecoder
...@@ -82,7 +81,7 @@ void DeleteLCLDDecoder( ...@@ -82,7 +81,7 @@ void DeleteLCLDDecoder(
int32_t DecodeLCLDFrame( int32_t DecodeLCLDFrame(
LCLDDecoder *psLCLDDecoder, LCLDDecoder *psLCLDDecoder,
IVAS_SPLIT_REND_BITS_HANDLE pBits, ISAR_SPLIT_REND_BITS_HANDLE pBits,
float ***pppfLCLDReal, float ***pppfLCLDReal,
float ***pppfLCLDImag float ***pppfLCLDImag
); );
...@@ -96,11 +95,11 @@ int32_t quantPhase( ...@@ -96,11 +95,11 @@ int32_t quantPhase(
float phase float phase
); );
void cplxmult( void cplxmult_lcld(
float *pr1, float *pr1,
float *pi1, float *pi1,
float r2, const float r2,
float i2 const float i2
); );
...@@ -238,8 +237,6 @@ typedef struct PREDICTION_ENCODER ...@@ -238,8 +237,6 @@ typedef struct PREDICTION_ENCODER
float **ppfPredStateImagTmp; float **ppfPredStateImagTmp;
float **ppfInpPrevReal; /* channels, bands */ float **ppfInpPrevReal; /* channels, bands */
float **ppfInpPrevImag; float **ppfInpPrevImag;
float *pfWindow;
float pfRxxReal[2]; float pfRxxReal[2];
float pfRxxImag[2]; float pfRxxImag[2];
...@@ -272,15 +269,10 @@ void ComputePredictors( ...@@ -272,15 +269,10 @@ void ComputePredictors(
float ***pppfImag float ***pppfImag
); );
void ApplyForwardPredictors(
PredictionEncoder *psPredictionEncoder,
float ***pppfReal,
float ***pppfImag
);
int32_t WritePredictors( int32_t WritePredictors(
PredictionEncoder *psPredictionEncoder, PredictionEncoder *psPredictionEncoder,
IVAS_SPLIT_REND_BITS_HANDLE pBits ISAR_SPLIT_REND_BITS_HANDLE pBits
); );
typedef struct PREDICTION_DECODER typedef struct PREDICTION_DECODER
...@@ -295,6 +287,11 @@ typedef struct PREDICTION_DECODER ...@@ -295,6 +287,11 @@ typedef struct PREDICTION_DECODER
int32_t *piPredChanEnable; int32_t *piPredChanEnable;
int32_t **ppiPredBandEnable; int32_t **ppiPredBandEnable;
/* PLC_IMPROVEMENT */
int32_t **ppiDecodingUnresolved;
int32_t **ppiDecodingFailed;
int32_t **ppiDecodingFailedPrev;
float **ppfA1Real; float **ppfA1Real;
float **ppfA1Imag; float **ppfA1Imag;
...@@ -319,9 +316,43 @@ void DeletePredictionDecoder( ...@@ -319,9 +316,43 @@ void DeletePredictionDecoder(
int32_t ReadPredictors( int32_t ReadPredictors(
PredictionDecoder *psPredictionDecoder, PredictionDecoder *psPredictionDecoder,
IVAS_SPLIT_REND_BITS_HANDLE pBits ISAR_SPLIT_REND_BITS_HANDLE pBits
); );
/* PLC_IMPROVEMENT */
void UpdatePredictionSubSetId(
PredictionEncoder *psPredictionEncoder);
void SetDecodingUnresolved(
LCLDDecoder *psLCLDDecoder);
int32_t AnyDecodingFailedPrev(
LCLDDecoder *psLCLDDecoder);
int32_t AnyDecodingFailed(
LCLDDecoder *psLCLDDecoder);
int32_t **GetDecodingFailedStatus(
LCLDDecoder *psLCLDDecoder);
int16_t GetNumSubSets(
LCLDDecoder *psLCLDDecoder);
int32_t **GetDecodingFailedPrevStatus(
LCLDDecoder *psLCLDDecoder);
void SetDecodingPassed(
PredictionDecoder *psPredictionDecoder);
void UpdateDecodingUnresolved(
PredictionDecoder *psPredictionDecoder);
void UpdateDecodingFailedStatus(
PredictionDecoder *psPredictionDecoder);
int32_t AnyDecodingUnresolved(
PredictionDecoder *psPredictionDecoder);
void ApplyInversePredictors( void ApplyInversePredictors(
PredictionDecoder *psPredictionDecoder, PredictionDecoder *psPredictionDecoder,
float ***pppfReal, float ***pppfReal,
......
/******************************************************************************************************
(C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
contributors to this repository. All Rights Reserved.
This software is protected by copyright law and by international treaties.
The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
contributors to this repository retain full ownership rights in their respective contributions in
the software. This notice grants no license of any kind, including but not limited to patent
license, nor is any license granted by implication, estoppel or otherwise.
Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
contributions.
This software is provided "AS IS", without any express or implied warranties. The software is in the
development stage. It is intended exclusively for experts who have experience with such software and
solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
and fitness for a particular purpose are hereby disclaimed and excluded.
Any dispute, controversy or claim arising under or in relation to providing this software shall be
submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
the United Nations Convention on Contracts on the International Sales of Goods.
*******************************************************************************************************/
#ifndef ISAR_PROT_H
#define ISAR_PROT_H
#include "isar_stat.h"
#ifdef SPLIT_REND_WITH_HEAD_ROT
#include <stdint.h>
#include "options.h"
#include "ivas_error.h"
#include "lib_isar_post_rend.h"
ivas_error isar_splitBinPreRendOpen(
ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE *hBinHrSplitPreRend,
MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData
#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG
,
const int32_t output_Fs
#endif
);
ivas_error split_renderer_open_lc3plus(
SPLIT_REND_WRAPPER *hSplitRendWrapper,
const ISAR_SPLIT_REND_CONFIG_DATA *pSplitRendConfig,
const int32_t OutSampleRate,
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
const IVAS_RENDER_FRAMESIZE ivas_frame_size
#else
const int16_t num_subframes
#endif
);
void isar_splitBinPreRendClose(
ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE *hBinHrSplitPreRend );
void lc3plusTimeAlignCldfbPoseCorr(
SPLIT_REND_WRAPPER *hSplitBin,
float Cldfb_In_BinReal[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
float Cldfb_In_BinImag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] );
ivas_error splitRendLc3plusEncodeAndWrite(
SPLIT_REND_WRAPPER *hSplitBin,
ISAR_SPLIT_REND_BITS_HANDLE pBits,
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
const int32_t available_bits,
#else
const int32_t SplitRendBitRate,
#endif
float *in[] );
int32_t ISAR_SPLIT_REND_BITStream_read_int32(
ISAR_SPLIT_REND_BITS_HANDLE pBits,
const int32_t bits );
void ISAR_SPLIT_REND_BITStream_write_int32(
ISAR_SPLIT_REND_BITS_HANDLE pBits,
const int32_t val,
const int32_t bits );
ivas_error isar_splitBinLCLDEncOpen(
ISAR_BIN_HR_SPLIT_LCLD_ENC_HANDLE *hSplitBinLCLDEnc,
const int32_t iSampleRate,
const int16_t iChannels,
const int32_t iDataRate,
const int16_t iNumBlocks,
const int16_t iNumIterations );
ivas_error isar_splitBinRendPLCOpen(
ISAR_SPLIT_REND_PLC_HANDLE *phSplitRendPLC,
const int16_t iNumSubSets );
void isar_splitBinRendPLCClose(
ISAR_SPLIT_REND_PLC_HANDLE *phSplitRendPLC );
ivas_error isar_splitBinLCLDDecOpen(
ISAR_BIN_HR_SPLIT_LCLD_DEC_HANDLE *hSplitBinLCLDDec,
const int32_t iSampleRate,
const int16_t iChannels,
const int16_t iNumBlocks,
const int16_t iNumIterations );
void isar_splitBinLCLDDecClose(
ISAR_BIN_HR_SPLIT_LCLD_DEC_HANDLE *hSplitBinLCLDDec );
void isar_splitBinRendPLCsaveState(
ISAR_SPLIT_REND_PLC_HANDLE hSplitRendPLC,
float Cldfb_RealBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
float Cldfb_ImagBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
const int16_t num_chs,
const int16_t iNumBlocks,
const int16_t iNumIterations );
void isar_splitBinRendPLC_xf(
ISAR_SPLIT_REND_PLC_HANDLE hSplitRendPLC,
float Cldfb_RealBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
float Cldfb_ImagBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
const int16_t num_chs,
const int16_t iNumBlocks,
const int16_t iNumIterations,
int32_t **ppiDecodingFailed,
int32_t **ppiDecodingFailedPrev );
void isar_splitBinRendPLC(
ISAR_SPLIT_REND_PLC_HANDLE hSplitRendPLC,
float Cldfb_RealBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
float Cldfb_ImagBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
const int16_t num_chs,
const int16_t iNumBlocks,
const int16_t iNumIterations,
int32_t **ppiDecodingFailed );
#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG
void isar_log_cldfb2wav_data(
float Cldfb_In_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
float Cldfb_In_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
HANDLE_CLDFB_FILTER_BANK *cldfbSyn,
const int16_t num_chs,
const int16_t num_freq_bands,
const int32_t output_Fs,
const int16_t start_slot_idx,
const int16_t md_band_idx,
const char *filename );
#endif
void isar_splitBinLCLDDecProcess(
ISAR_BIN_HR_SPLIT_LCLD_DEC_HANDLE hSplitBinLCLDDec,
ISAR_SPLIT_REND_BITS_HANDLE pBits,
float Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
float Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
const int16_t bfi );
void set_fix_rotation_mat(
float fix_pos_rot_mat[][BINAURAL_CHANNELS][BINAURAL_CHANNELS],
MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData );
void isar_splitBinLCLDEncClose(
ISAR_BIN_HR_SPLIT_LCLD_ENC_HANDLE *hSplitBinLCLDEnc );
void isar_splitBinLCLDEncProcess(
ISAR_BIN_HR_SPLIT_LCLD_ENC_HANDLE hSplitBinLCLDEnc,
float Cldfb_In_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
float Cldfb_In_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
const int32_t available_bits,
ISAR_SPLIT_REND_BITS_HANDLE pBits );
void set_pose_types(
ISAR_SPLIT_REND_POSE_TYPE pose_type[MAX_HEAD_ROT_POSES - 1],
MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData );
void isar_split_rend_init_huff_cfg(
ISAR_BIN_HR_SPLIT_REND_HUFF_HANDLE pHuff_cfg );
ivas_error isar_splitBinPostRendOpen(
ISAR_BIN_HR_SPLIT_POST_REND_HANDLE *hBinHrSplitPostRend,
MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData,
const int32_t output_Fs );
void isar_splitBinPostRendClose(
ISAR_BIN_HR_SPLIT_POST_REND_HANDLE *hBinHrSplitPostRend );
void isar_SplitRenderer_getdiagdiff(
int16_t in_idx[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
int16_t out_idx[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
const int16_t sign,
const int16_t min_val,
const int16_t max_val );
void isar_split_rend_get_quant_params(
const int16_t num_md_bands,
int16_t pred_real_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS],
int16_t pred_imag_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS],
int16_t pred_quant_pnts_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS],
float pred_quantstep_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS],
float pred_1byquantstep_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS],
int16_t d_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS],
int16_t bands_pitch[ISAR_SPLIT_REND_NUM_QUANT_STRATS],
int16_t pred_real_bands_roll[ISAR_SPLIT_REND_NUM_QUANT_STRATS],
int16_t pred_imag_bands_roll[ISAR_SPLIT_REND_NUM_QUANT_STRATS],
#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS
const int16_t ro_flag,
#endif
int16_t *num_quant_strats
#ifndef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS
,
int16_t *num_complex_bands
#endif
);
void isar_splitBinPostRendMdDec(
ISAR_SPLIT_REND_BITS_HANDLE pBits,
ISAR_BIN_HR_SPLIT_POST_REND_HANDLE hBinHrSplitPostRend,
#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG
MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData,
BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend
#else
MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData
#endif
);
void Quat2EulerDegree(
const IVAS_QUATERNION quat, /* i : quaternion describing the rotation */
float *yaw, /* o : yaw */
float *pitch, /* o : pitch */
float *roll /* o : roll */
);
void isar_mat_mult_2by2_complex(
float in_re1[2][2],
float in_im1[2][2],
float in_re2[2][2],
float in_im2[2][2],
float out_re2[2][2],
float out_im2[2][2] );
void isar_rend_CldfbSplitPostRendProcess(
ISAR_BIN_HR_SPLIT_POST_REND_HANDLE hBinHrSplitPostRend,
MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData,
const IVAS_QUATERNION QuaternionPost,
float Cldfb_RealBuffer_Binaural[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX],
float Cldfb_ImagBuffer_Binaural[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX],
float output[][L_FRAME48k],
const int16_t cldfb_in_flag );
void isar_rend_CldfbSplitPreRendProcess(
const ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend,
const IVAS_QUATERNION headPosition,
MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData,
float Cldfb_In_BinReal[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
float Cldfb_In_BinImag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
ISAR_SPLIT_REND_BITS_HANDLE pBits,
const int32_t target_md_bits,
const int16_t low_res_pre_rend_rot,
const int16_t ro_md_flag );
ivas_error isar_renderMultiTDBinToSplitBinaural(
SPLIT_REND_WRAPPER *hSplitBin,
const IVAS_QUATERNION headPosition,
const int32_t SplitRendBitRate,
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
const int16_t isar_frame_size_ms,
#endif
const int16_t codec_frame_size_ms,
ISAR_SPLIT_REND_BITS_HANDLE pBits,
const int16_t max_bands,
float *in[],
const int16_t low_res_pre_rend_rot,
const int16_t pcm_out_flag,
const int16_t ro_md_flag );
void isar_init_multi_bin_pose_data(
MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData );
void isar_renderSplitGetMultiBinPoseData(
const ISAR_SPLIT_REND_CONFIG_DATA *pSplit_rend_config,
MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData,
const ISAR_SPLIT_REND_ROT_AXIS rot_axis );
#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS
int16_t isar_renderSplitGetRot_axisNumBits(
const int16_t dof );
ISAR_SPLIT_REND_ROT_AXIS isar_renderSplitGetRot_axisFromCode(
const int16_t dof,
const int16_t code );
int16_t isar_renderSplitGetCodeFromRot_axis(
const int16_t dof,
const ISAR_SPLIT_REND_ROT_AXIS rot_axis,
int16_t *num_bits );
#endif
void isar_init_split_post_rend_handles(
ISAR_SPLIT_POST_REND_WRAPPER *hSplitRendWrapper );
void isar_set_split_rend_ht_setup(
SPLIT_REND_WRAPPER *hSplitrend,
IVAS_QUATERNION Quaternions[MAX_PARAM_SPATIAL_SUBFRAMES],
float Rmat[MAX_PARAM_SPATIAL_SUBFRAMES][3][3] );
#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
int32_t isar_get_lc3plus_bitrate(
const int32_t SplitRendBitRate,
const ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrectionMode,
const int16_t split_prerender_frame_size_ms );
#endif
ivas_error isar_split_rend_validate_config(
const ISAR_SPLIT_REND_CONFIG_DATA *pSplitRendConfig,
const int16_t pcm_out_flag );
int32_t isar_get_lcld_bitrate(
const int32_t SplitRendBitRate,
const ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrectionMode );
#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
int8_t isar_get_lc3plus_bitrate_id(
const int32_t SplitRendBitRate );
#endif
int32_t isar_get_split_rend_md_target_brate(
const int32_t SplitRendBitRate,
const int16_t pcm_out_flag );
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
ivas_error isar_framesize_to_ms(
const IVAS_RENDER_FRAMESIZE frame_size, /* i : frame size enum */
int16_t *ms /* o : frame size in ms */
);
#endif
ivas_error isar_split_rend_choose_default_codec(
ISAR_SPLIT_REND_CODEC *pCodec, /* i/o: pointer to codec setting */
#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS
int16_t *pIsar_frame_size_ms, /* i/o: pointer to isar frame size setting */
#endif
int16_t *pCodec_frame_size_ms, /* i/o: pointer to codec frame size setting */
const int16_t cldfb_in_flag, /* i : flag indicating rendering in TD */
const int16_t pcm_out_flag, /* i : flag to indicate PCM output */
const int16_t num_subframes /* i : number of subframes */
);
void ISAR_SPLIT_REND_BITStream_init(
ISAR_SPLIT_REND_BITS_HANDLE pBits,
const int32_t buf_len_bytes,
uint8_t *pbuf );
void isar_split_rend_huffman_dec_init_min_max_len(
isar_split_rend_huffman_cfg_t *p_huff_cfg );
int16_t wrap_a(
int16_t val,
const int16_t min_val,
const int16_t max_val );
#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS
int32_t isar_get_lc3plus_size_from_id(
const int8_t SplitRendBitRateId,
const ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrectionMode,
const int16_t split_prerender_frame_size_ms );
#endif
void isar_renderSplitUpdateNoCorrectionPoseData(
const ISAR_SPLIT_REND_CONFIG_DATA *pSplit_rend_config,
MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData );
int32_t get_bit(
const int32_t state,
const int32_t bit_id );
ISAR_POST_REND_AudioConfigType isar_getAudioConfigType(
const IVAS_AUDIO_CONFIG config );
void isar_init_split_rend_handles(
SPLIT_REND_WRAPPER *hSplitRendWrapper );
#endif
/* clang-format on */
#endif /* ISAR_PROT_H */
...@@ -30,15 +30,22 @@ ...@@ -30,15 +30,22 @@
*******************************************************************************************************/ *******************************************************************************************************/
#include "ivas_lcld_rom_tables.h" #include "isar_rom_lcld_tables.h"
#include "options.h" #include "options.h"
#ifdef SPLIT_REND_WITH_HEAD_ROT #ifdef SPLIT_REND_WITH_HEAD_ROT
#include "wmc_auto.h" #include "wmc_auto.h"
#include "prot.h" #include "prot.h"
#include "ivas_lcld_prot.h" #include "isar_lcld_prot.h"
/* clang-format off */ /* clang-format off */
const int32_t c_aiNumLcldBandsPerBand[MAX_BANDS_48] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 21, 24, 27, 31, 37, 43, 50, 60
};
const int32_t c_aiBandIdPerLcldBand[LCLD_BANDS] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18,
18, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22
};
/* phi = (-12:12)'/12 *pi; tmp = [cos(phi),sin(phi)]; tmp = tmp';sprintf('{%.8ff, %.8ff},\n',tmp(:)) */ /* phi = (-12:12)'/12 *pi; tmp = [cos(phi),sin(phi)]; tmp = tmp';sprintf('{%.8ff, %.8ff},\n',tmp(:)) */
const float c_afRotRealImag[PHASE_MAX_VAL - PHASE_MIN_VAL + 1][2] = const float c_afRotRealImag[PHASE_MAX_VAL - PHASE_MIN_VAL + 1][2] =
...@@ -70,7 +77,6 @@ const float c_afRotRealImag[PHASE_MAX_VAL - PHASE_MIN_VAL + 1][2] = ...@@ -70,7 +77,6 @@ const float c_afRotRealImag[PHASE_MAX_VAL - PHASE_MIN_VAL + 1][2] =
{ -1.00000000f, 0.00000000f } { -1.00000000f, 0.00000000f }
}; };
/* Move this to perceptual model ? */
const int32_t c_aiBandwidths48[MAX_BANDS_48] = const int32_t c_aiBandwidths48[MAX_BANDS_48] =
{ {
1, 1,
...@@ -10934,7763 +10940,6 @@ const uint32_t num_row_aauiLCLDHuff[2 * ALLOC_TABLE_SIZE] = { 0, 16, 16, 25, 36, ...@@ -10934,7763 +10940,6 @@ const uint32_t num_row_aauiLCLDHuff[2 * ALLOC_TABLE_SIZE] = { 0, 16, 16, 25, 36,
100, 169, 196, 289, 324, 400, 576, 729, 729, 28, 100, 169, 196, 289, 324, 400, 576, 729, 729, 28,
29, 32, 37, 39, 46, 55, 65, 77, 91, 109, 29, 32, 37, 39, 46, 55, 65, 77, 91, 109,
129, 153, 181 }; 129, 153, 181 };
#ifdef USE_DEMOD_TABLES
const int32_t c_aaiHuffDemod1[16][2] = {
0,
0,
0,
1,
0,
2,
0,
3,
1,
0,
1,
1,
1,
2,
1,
3,
2,
0,
2,
1,
2,
2,
2,
3,
3,
0,
3,
1,
3,
2,
3,
3,
};
const int32_t c_aaiHuffDemod2[16][2] = {
0,
0,
0,
1,
0,
2,
0,
3,
1,
0,
1,
1,
1,
2,
1,
3,
2,
0,
2,
1,
2,
2,
2,
3,
3,
0,
3,
1,
3,
2,
3,
3,
};
const int32_t c_aaiHuffDemod3[25][2] = {
0,
0,
0,
1,
0,
2,
0,
3,
0,
4,
1,
0,
1,
1,
1,
2,
1,
3,
1,
4,
2,
0,
2,
1,
2,
2,
2,
3,
2,
4,
3,
0,
3,
1,
3,
2,
3,
3,
3,
4,
4,
0,
4,
1,
4,
2,
4,
3,
4,
4,
};
const int32_t c_aaiHuffDemod4[36][2] = {
0,
0,
0,
1,
0,
2,
0,
3,
0,
4,
0,
5,
1,
0,
1,
1,
1,
2,
1,
3,
1,
4,
1,
5,
2,
0,
2,
1,
2,
2,
2,
3,
2,
4,
2,
5,
3,
0,
3,
1,
3,
2,
3,
3,
3,
4,
3,
5,
4,
0,
4,
1,
4,
2,
4,
3,
4,
4,
4,
5,
5,
0,
5,
1,
5,
2,
5,
3,
5,
4,
5,
5,
};
const int32_t c_aaiHuffDemod5[36][2] = {
0,
0,
0,
1,
0,
2,
0,
3,
0,
4,
0,
5,
1,
0,
1,
1,
1,
2,
1,
3,
1,
4,
1,
5,
2,
0,
2,
1,
2,
2,
2,
3,
2,
4,
2,
5,
3,
0,
3,
1,
3,
2,
3,
3,
3,
4,
3,
5,
4,
0,
4,
1,
4,
2,
4,
3,
4,
4,
4,
5,
5,
0,
5,
1,
5,
2,
5,
3,
5,
4,
5,
5,
};
const int32_t c_aaiHuffDemod6[49][2] = {
0,
0,
0,
1,
0,
2,
0,
3,
0,
4,
0,
5,
0,
6,
1,
0,
1,
1,
1,
2,
1,
3,
1,
4,
1,
5,
1,
6,
2,
0,
2,
1,
2,
2,
2,
3,
2,
4,
2,
5,
2,
6,
3,
0,
3,
1,
3,
2,
3,
3,
3,
4,
3,
5,
3,
6,
4,
0,
4,
1,
4,
2,
4,
3,
4,
4,
4,
5,
4,
6,
5,
0,
5,
1,
5,
2,
5,
3,
5,
4,
5,
5,
5,
6,
6,
0,
6,
1,
6,
2,
6,
3,
6,
4,
6,
5,
6,
6,
};
const int32_t c_aaiHuffDemod7[64][2] = {
0,
0,
0,
1,
0,
2,
0,
3,
0,
4,
0,
5,
0,
6,
0,
7,
1,
0,
1,
1,
1,
2,
1,
3,
1,
4,
1,
5,
1,
6,
1,
7,
2,
0,
2,
1,
2,
2,
2,
3,
2,
4,
2,
5,
2,
6,
2,
7,
3,
0,
3,
1,
3,
2,
3,
3,
3,
4,
3,
5,
3,
6,
3,
7,
4,
0,
4,
1,
4,
2,
4,
3,
4,
4,
4,
5,
4,
6,
4,
7,
5,
0,
5,
1,
5,
2,
5,
3,
5,
4,
5,
5,
5,
6,
5,
7,
6,
0,
6,
1,
6,
2,
6,
3,
6,
4,
6,
5,
6,
6,
6,
7,
7,
0,
7,
1,
7,
2,
7,
3,
7,
4,
7,
5,
7,
6,
7,
7,
};
const int32_t c_aaiHuffDemod8[81][2] = {
0,
0,
0,
1,
0,
2,
0,
3,
0,
4,
0,
5,
0,
6,
0,
7,
0,
8,
1,
0,
1,
1,
1,
2,
1,
3,
1,
4,
1,
5,
1,
6,
1,
7,
1,
8,
2,
0,
2,
1,
2,
2,
2,
3,
2,
4,
2,
5,
2,
6,
2,
7,
2,
8,
3,
0,
3,
1,
3,
2,
3,
3,
3,
4,
3,
5,
3,
6,
3,
7,
3,
8,
4,
0,
4,
1,
4,
2,
4,
3,
4,
4,
4,
5,
4,
6,
4,
7,
4,
8,
5,
0,
5,
1,
5,
2,
5,
3,
5,
4,
5,
5,
5,
6,
5,
7,
5,
8,
6,
0,
6,
1,
6,
2,
6,
3,
6,
4,
6,
5,
6,
6,
6,
7,
6,
8,
7,
0,
7,
1,
7,
2,
7,
3,
7,
4,
7,
5,
7,
6,
7,
7,
7,
8,
8,
0,
8,
1,
8,
2,
8,
3,
8,
4,
8,
5,
8,
6,
8,
7,
8,
8,
};
const int32_t c_aaiHuffDemod9[100][2] = {
0,
0,
0,
1,
0,
2,
0,
3,
0,
4,
0,
5,
0,
6,
0,
7,
0,
8,
0,
9,
1,
0,
1,
1,
1,
2,
1,
3,
1,
4,
1,
5,
1,
6,
1,
7,
1,
8,
1,
9,
2,
0,
2,
1,
2,
2,
2,
3,
2,
4,
2,
5,
2,
6,
2,
7,
2,
8,
2,
9,
3,
0,
3,
1,
3,
2,
3,
3,
3,
4,
3,
5,
3,
6,
3,
7,
3,
8,
3,
9,
4,
0,
4,
1,
4,
2,
4,
3,
4,
4,
4,
5,
4,
6,
4,
7,
4,
8,
4,
9,
5,
0,
5,
1,
5,
2,
5,
3,
5,
4,
5,
5,
5,
6,
5,
7,
5,
8,
5,
9,
6,
0,
6,
1,
6,
2,
6,
3,
6,
4,
6,
5,
6,
6,
6,
7,
6,
8,
6,
9,
7,
0,
7,
1,
7,
2,
7,
3,
7,
4,
7,
5,
7,
6,
7,
7,
7,
8,
7,
9,
8,
0,
8,
1,
8,
2,
8,
3,
8,
4,
8,
5,
8,
6,
8,
7,
8,
8,
8,
9,
9,
0,
9,
1,
9,
2,
9,
3,
9,
4,
9,
5,
9,
6,
9,
7,
9,
8,
9,
9,
};
const int32_t c_aaiHuffDemod10[169][2] = {
0,
0,
0,
1,
0,
2,
0,
3,
0,
4,
0,
5,
0,
6,
0,
7,
0,
8,
0,
9,
0,
10,
0,
11,
0,
12,
1,
0,
1,
1,
1,
2,
1,
3,
1,
4,
1,
5,
1,
6,
1,
7,
1,
8,
1,
9,
1,
10,
1,
11,
1,
12,
2,
0,
2,
1,
2,
2,
2,
3,
2,
4,
2,
5,
2,
6,
2,
7,
2,
8,
2,
9,
2,
10,
2,
11,
2,
12,
3,
0,
3,
1,
3,
2,
3,
3,
3,
4,
3,
5,
3,
6,
3,
7,
3,
8,
3,
9,
3,
10,
3,
11,
3,
12,
4,
0,
4,
1,
4,
2,
4,
3,
4,
4,
4,
5,
4,
6,
4,
7,
4,
8,
4,
9,
4,
10,
4,
11,
4,
12,
5,
0,
5,
1,
5,
2,
5,
3,
5,
4,
5,
5,
5,
6,
5,
7,
5,
8,
5,
9,
5,
10,
5,
11,
5,
12,
6,
0,
6,
1,
6,
2,
6,
3,
6,
4,
6,
5,
6,
6,
6,
7,
6,
8,
6,
9,
6,
10,
6,
11,
6,
12,
7,
0,
7,
1,
7,
2,
7,
3,
7,
4,
7,
5,
7,
6,
7,
7,
7,
8,
7,
9,
7,
10,
7,
11,
7,
12,
8,
0,
8,
1,
8,
2,
8,
3,
8,
4,
8,
5,
8,
6,
8,
7,
8,
8,
8,
9,
8,
10,
8,
11,
8,
12,
9,
0,
9,
1,
9,
2,
9,
3,
9,
4,
9,
5,
9,
6,
9,
7,
9,
8,
9,
9,
9,
10,
9,
11,
9,
12,
10,
0,
10,
1,
10,
2,
10,
3,
10,
4,
10,
5,
10,
6,
10,
7,
10,
8,
10,
9,
10,
10,
10,
11,
10,
12,
11,
0,
11,
1,
11,
2,
11,
3,
11,
4,
11,
5,
11,
6,
11,
7,
11,
8,
11,
9,
11,
10,
11,
11,
11,
12,
12,
0,
12,
1,
12,
2,
12,
3,
12,
4,
12,
5,
12,
6,
12,
7,
12,
8,
12,
9,
12,
10,
12,
11,
12,
12,
};
const int32_t c_aaiHuffDemod11[196][2] = {
0,
0,
0,
1,
0,
2,
0,
3,
0,
4,
0,
5,
0,
6,
0,
7,
0,
8,
0,
9,
0,
10,
0,
11,
0,
12,
0,
13,
1,
0,
1,
1,
1,
2,
1,
3,
1,
4,
1,
5,
1,
6,
1,
7,
1,
8,
1,
9,
1,
10,
1,
11,
1,
12,
1,
13,
2,
0,
2,
1,
2,
2,
2,
3,
2,
4,
2,
5,
2,
6,
2,
7,
2,
8,
2,
9,
2,
10,
2,
11,
2,
12,
2,
13,
3,
0,
3,
1,
3,
2,
3,
3,
3,
4,
3,
5,
3,
6,
3,
7,
3,
8,
3,
9,
3,
10,
3,
11,
3,
12,
3,
13,
4,
0,
4,
1,
4,
2,
4,
3,
4,
4,
4,
5,
4,
6,
4,
7,
4,
8,
4,
9,
4,
10,
4,
11,
4,
12,
4,
13,
5,
0,
5,
1,
5,
2,
5,
3,
5,
4,
5,
5,
5,
6,
5,
7,
5,
8,
5,
9,
5,
10,
5,
11,
5,
12,
5,
13,
6,
0,
6,
1,
6,
2,
6,
3,
6,
4,
6,
5,
6,
6,
6,
7,
6,
8,
6,
9,
6,
10,
6,
11,
6,
12,
6,
13,
7,
0,
7,
1,
7,
2,
7,
3,
7,
4,
7,
5,
7,
6,
7,
7,
7,
8,
7,
9,
7,
10,
7,
11,
7,
12,
7,
13,
8,
0,
8,
1,
8,
2,
8,
3,
8,
4,
8,
5,
8,
6,
8,
7,
8,
8,
8,
9,
8,
10,
8,
11,
8,
12,
8,
13,
9,
0,
9,
1,
9,
2,
9,
3,
9,
4,
9,
5,
9,
6,
9,
7,
9,
8,
9,
9,
9,
10,
9,
11,
9,
12,
9,
13,
10,
0,
10,
1,
10,
2,
10,
3,
10,
4,
10,
5,
10,
6,
10,
7,
10,
8,
10,
9,
10,
10,
10,
11,
10,
12,
10,
13,
11,
0,
11,
1,
11,
2,
11,
3,
11,
4,
11,
5,
11,
6,
11,
7,
11,
8,
11,
9,
11,
10,
11,
11,
11,
12,
11,
13,
12,
0,
12,
1,
12,
2,
12,
3,
12,
4,
12,
5,
12,
6,
12,
7,
12,
8,
12,
9,
12,
10,
12,
11,
12,
12,
12,
13,
13,
0,
13,
1,
13,
2,
13,
3,
13,
4,
13,
5,
13,
6,
13,
7,
13,
8,
13,
9,
13,
10,
13,
11,
13,
12,
13,
13,
};
const int32_t c_aaiHuffDemod12[289][2] = {
0,
0,
0,
1,
0,
2,
0,
3,
0,
4,
0,
5,
0,
6,
0,
7,
0,
8,
0,
9,
0,
10,
0,
11,
0,
12,
0,
13,
0,
14,
0,
15,
0,
16,
1,
0,
1,
1,
1,
2,
1,
3,
1,
4,
1,
5,
1,
6,
1,
7,
1,
8,
1,
9,
1,
10,
1,
11,
1,
12,
1,
13,
1,
14,
1,
15,
1,
16,
2,
0,
2,
1,
2,
2,
2,
3,
2,
4,
2,
5,
2,
6,
2,
7,
2,
8,
2,
9,
2,
10,
2,
11,
2,
12,
2,
13,
2,
14,
2,
15,
2,
16,
3,
0,
3,
1,
3,
2,
3,
3,
3,
4,
3,
5,
3,
6,
3,
7,
3,
8,
3,
9,
3,
10,
3,
11,
3,
12,
3,
13,
3,
14,
3,
15,
3,
16,
4,
0,
4,
1,
4,
2,
4,
3,
4,
4,
4,
5,
4,
6,
4,
7,
4,
8,
4,
9,
4,
10,
4,
11,
4,
12,
4,
13,
4,
14,
4,
15,
4,
16,
5,
0,
5,
1,
5,
2,
5,
3,
5,
4,
5,
5,
5,
6,
5,
7,
5,
8,
5,
9,
5,
10,
5,
11,
5,
12,
5,
13,
5,
14,
5,
15,
5,
16,
6,
0,
6,
1,
6,
2,
6,
3,
6,
4,
6,
5,
6,
6,
6,
7,
6,
8,
6,
9,
6,
10,
6,
11,
6,
12,
6,
13,
6,
14,
6,
15,
6,
16,
7,
0,
7,
1,
7,
2,
7,
3,
7,
4,
7,
5,
7,
6,
7,
7,
7,
8,
7,
9,
7,
10,
7,
11,
7,
12,
7,
13,
7,
14,
7,
15,
7,
16,
8,
0,
8,
1,
8,
2,
8,
3,
8,
4,
8,
5,
8,
6,
8,
7,
8,
8,
8,
9,
8,
10,
8,
11,
8,
12,
8,
13,
8,
14,
8,
15,
8,
16,
9,
0,
9,
1,
9,
2,
9,
3,
9,
4,
9,
5,
9,
6,
9,
7,
9,
8,
9,
9,
9,
10,
9,
11,
9,
12,
9,
13,
9,
14,
9,
15,
9,
16,
10,
0,
10,
1,
10,
2,
10,
3,
10,
4,
10,
5,
10,
6,
10,
7,
10,
8,
10,
9,
10,
10,
10,
11,
10,
12,
10,
13,
10,
14,
10,
15,
10,
16,
11,
0,
11,
1,
11,
2,
11,
3,
11,
4,
11,
5,
11,
6,
11,
7,
11,
8,
11,
9,
11,
10,
11,
11,
11,
12,
11,
13,
11,
14,
11,
15,
11,
16,
12,
0,
12,
1,
12,
2,
12,
3,
12,
4,
12,
5,
12,
6,
12,
7,
12,
8,
12,
9,
12,
10,
12,
11,
12,
12,
12,
13,
12,
14,
12,
15,
12,
16,
13,
0,
13,
1,
13,
2,
13,
3,
13,
4,
13,
5,
13,
6,
13,
7,
13,
8,
13,
9,
13,
10,
13,
11,
13,
12,
13,
13,
13,
14,
13,
15,
13,
16,
14,
0,
14,
1,
14,
2,
14,
3,
14,
4,
14,
5,
14,
6,
14,
7,
14,
8,
14,
9,
14,
10,
14,
11,
14,
12,
14,
13,
14,
14,
14,
15,
14,
16,
15,
0,
15,
1,
15,
2,
15,
3,
15,
4,
15,
5,
15,
6,
15,
7,
15,
8,
15,
9,
15,
10,
15,
11,
15,
12,
15,
13,
15,
14,
15,
15,
15,
16,
16,
0,
16,
1,
16,
2,
16,
3,
16,
4,
16,
5,
16,
6,
16,
7,
16,
8,
16,
9,
16,
10,
16,
11,
16,
12,
16,
13,
16,
14,
16,
15,
16,
16,
};
const int32_t c_aaiHuffDemod13[324][2] = {
0,
0,
0,
1,
0,
2,
0,
3,
0,
4,
0,
5,
0,
6,
0,
7,
0,
8,
0,
9,
0,
10,
0,
11,
0,
12,
0,
13,
0,
14,
0,
15,
0,
16,
0,
17,
1,
0,
1,
1,
1,
2,
1,
3,
1,
4,
1,
5,
1,
6,
1,
7,
1,
8,
1,
9,
1,
10,
1,
11,
1,
12,
1,
13,
1,
14,
1,
15,
1,
16,
1,
17,
2,
0,
2,
1,
2,
2,
2,
3,
2,
4,
2,
5,
2,
6,
2,
7,
2,
8,
2,
9,
2,
10,
2,
11,
2,
12,
2,
13,
2,
14,
2,
15,
2,
16,
2,
17,
3,
0,
3,
1,
3,
2,
3,
3,
3,
4,
3,
5,
3,
6,
3,
7,
3,
8,
3,
9,
3,
10,
3,
11,
3,
12,
3,
13,
3,
14,
3,
15,
3,
16,
3,
17,
4,
0,
4,
1,
4,
2,
4,
3,
4,
4,
4,
5,
4,
6,
4,
7,
4,
8,
4,
9,
4,
10,
4,
11,
4,
12,
4,
13,
4,
14,
4,
15,
4,
16,
4,
17,
5,
0,
5,
1,
5,
2,
5,
3,
5,
4,
5,
5,
5,
6,
5,
7,
5,
8,
5,
9,
5,
10,
5,
11,
5,
12,
5,
13,
5,
14,
5,
15,
5,
16,
5,
17,
6,
0,
6,
1,
6,
2,
6,
3,
6,
4,
6,
5,
6,
6,
6,
7,
6,
8,
6,
9,
6,
10,
6,
11,
6,
12,
6,
13,
6,
14,
6,
15,
6,
16,
6,
17,
7,
0,
7,
1,
7,
2,
7,
3,
7,
4,
7,
5,
7,
6,
7,
7,
7,
8,
7,
9,
7,
10,
7,
11,
7,
12,
7,
13,
7,
14,
7,
15,
7,
16,
7,
17,
8,
0,
8,
1,
8,
2,
8,
3,
8,
4,
8,
5,
8,
6,
8,
7,
8,
8,
8,
9,
8,
10,
8,
11,
8,
12,
8,
13,
8,
14,
8,
15,
8,
16,
8,
17,
9,
0,
9,
1,
9,
2,
9,
3,
9,
4,
9,
5,
9,
6,
9,
7,
9,
8,
9,
9,
9,
10,
9,
11,
9,
12,
9,
13,
9,
14,
9,
15,
9,
16,
9,
17,
10,
0,
10,
1,
10,
2,
10,
3,
10,
4,
10,
5,
10,
6,
10,
7,
10,
8,
10,
9,
10,
10,
10,
11,
10,
12,
10,
13,
10,
14,
10,
15,
10,
16,
10,
17,
11,
0,
11,
1,
11,
2,
11,
3,
11,
4,
11,
5,
11,
6,
11,
7,
11,
8,
11,
9,
11,
10,
11,
11,
11,
12,
11,
13,
11,
14,
11,
15,
11,
16,
11,
17,
12,
0,
12,
1,
12,
2,
12,
3,
12,
4,
12,
5,
12,
6,
12,
7,
12,
8,
12,
9,
12,
10,
12,
11,
12,
12,
12,
13,
12,
14,
12,
15,
12,
16,
12,
17,
13,
0,
13,
1,
13,
2,
13,
3,
13,
4,
13,
5,
13,
6,
13,
7,
13,
8,
13,
9,
13,
10,
13,
11,
13,
12,
13,
13,
13,
14,
13,
15,
13,
16,
13,
17,
14,
0,
14,
1,
14,
2,
14,
3,
14,
4,
14,
5,
14,
6,
14,
7,
14,
8,
14,
9,
14,
10,
14,
11,
14,
12,
14,
13,
14,
14,
14,
15,
14,
16,
14,
17,
15,
0,
15,
1,
15,
2,
15,
3,
15,
4,
15,
5,
15,
6,
15,
7,
15,
8,
15,
9,
15,
10,
15,
11,
15,
12,
15,
13,
15,
14,
15,
15,
15,
16,
15,
17,
16,
0,
16,
1,
16,
2,
16,
3,
16,
4,
16,
5,
16,
6,
16,
7,
16,
8,
16,
9,
16,
10,
16,
11,
16,
12,
16,
13,
16,
14,
16,
15,
16,
16,
16,
17,
17,
0,
17,
1,
17,
2,
17,
3,
17,
4,
17,
5,
17,
6,
17,
7,
17,
8,
17,
9,
17,
10,
17,
11,
17,
12,
17,
13,
17,
14,
17,
15,
17,
16,
17,
17,
};
const int32_t c_aaiHuffDemod14[400][2] = {
0,
0,
0,
1,
0,
2,
0,
3,
0,
4,
0,
5,
0,
6,
0,
7,
0,
8,
0,
9,
0,
10,
0,
11,
0,
12,
0,
13,
0,
14,
0,
15,
0,
16,
0,
17,
0,
18,
0,
19,
1,
0,
1,
1,
1,
2,
1,
3,
1,
4,
1,
5,
1,
6,
1,
7,
1,
8,
1,
9,
1,
10,
1,
11,
1,
12,
1,
13,
1,
14,
1,
15,
1,
16,
1,
17,
1,
18,
1,
19,
2,
0,
2,
1,
2,
2,
2,
3,
2,
4,
2,
5,
2,
6,
2,
7,
2,
8,
2,
9,
2,
10,
2,
11,
2,
12,
2,
13,
2,
14,
2,
15,
2,
16,
2,
17,
2,
18,
2,
19,
3,
0,
3,
1,
3,
2,
3,
3,
3,
4,
3,
5,
3,
6,
3,
7,
3,
8,
3,
9,
3,
10,
3,
11,
3,
12,
3,
13,
3,
14,
3,
15,
3,
16,
3,
17,
3,
18,
3,
19,
4,
0,
4,
1,
4,
2,
4,
3,
4,
4,
4,
5,
4,
6,
4,
7,
4,
8,
4,
9,
4,
10,
4,
11,
4,
12,
4,
13,
4,
14,
4,
15,
4,
16,
4,
17,
4,
18,
4,
19,
5,
0,
5,
1,
5,
2,
5,
3,
5,
4,
5,
5,
5,
6,
5,
7,
5,
8,
5,
9,
5,
10,
5,
11,
5,
12,
5,
13,
5,
14,
5,
15,
5,
16,
5,
17,
5,
18,
5,
19,
6,
0,
6,
1,
6,
2,
6,
3,
6,
4,
6,
5,
6,
6,
6,
7,
6,
8,
6,
9,
6,
10,
6,
11,
6,
12,
6,
13,
6,
14,
6,
15,
6,
16,
6,
17,
6,
18,
6,
19,
7,
0,
7,
1,
7,
2,
7,
3,
7,
4,
7,
5,
7,
6,
7,
7,
7,
8,
7,
9,
7,
10,
7,
11,
7,
12,
7,
13,
7,
14,
7,
15,
7,
16,
7,
17,
7,
18,
7,
19,
8,
0,
8,
1,
8,
2,
8,
3,
8,
4,
8,
5,
8,
6,
8,
7,
8,
8,
8,
9,
8,
10,
8,
11,
8,
12,
8,
13,
8,
14,
8,
15,
8,
16,
8,
17,
8,
18,
8,
19,
9,
0,
9,
1,
9,
2,
9,
3,
9,
4,
9,
5,
9,
6,
9,
7,
9,
8,
9,
9,
9,
10,
9,
11,
9,
12,
9,
13,
9,
14,
9,
15,
9,
16,
9,
17,
9,
18,
9,
19,
10,
0,
10,
1,
10,
2,
10,
3,
10,
4,
10,
5,
10,
6,
10,
7,
10,
8,
10,
9,
10,
10,
10,
11,
10,
12,
10,
13,
10,
14,
10,
15,
10,
16,
10,
17,
10,
18,
10,
19,
11,
0,
11,
1,
11,
2,
11,
3,
11,
4,
11,
5,
11,
6,
11,
7,
11,
8,
11,
9,
11,
10,
11,
11,
11,
12,
11,
13,
11,
14,
11,
15,
11,
16,
11,
17,
11,
18,
11,
19,
12,
0,
12,
1,
12,
2,
12,
3,
12,
4,
12,
5,
12,
6,
12,
7,
12,
8,
12,
9,
12,
10,
12,
11,
12,
12,
12,
13,
12,
14,
12,
15,
12,
16,
12,
17,
12,
18,
12,
19,
13,
0,
13,
1,
13,
2,
13,
3,
13,
4,
13,
5,
13,
6,
13,
7,
13,
8,
13,
9,
13,
10,
13,
11,
13,
12,
13,
13,
13,
14,
13,
15,
13,
16,
13,
17,
13,
18,
13,
19,
14,
0,
14,
1,
14,
2,
14,
3,
14,
4,
14,
5,
14,
6,
14,
7,
14,
8,
14,
9,
14,
10,
14,
11,
14,
12,
14,
13,
14,
14,
14,
15,
14,
16,
14,
17,
14,
18,
14,
19,
15,
0,
15,
1,
15,
2,
15,
3,
15,
4,
15,
5,
15,
6,
15,
7,
15,
8,
15,
9,
15,
10,
15,
11,
15,
12,
15,
13,
15,
14,
15,
15,
15,
16,
15,
17,
15,
18,
15,
19,
16,
0,
16,
1,
16,
2,
16,
3,
16,
4,
16,
5,
16,
6,
16,
7,
16,
8,
16,
9,
16,
10,
16,
11,
16,
12,
16,
13,
16,
14,
16,
15,
16,
16,
16,
17,
16,
18,
16,
19,
17,
0,
17,
1,
17,
2,
17,
3,
17,
4,
17,
5,
17,
6,
17,
7,
17,
8,
17,
9,
17,
10,
17,
11,
17,
12,
17,
13,
17,
14,
17,
15,
17,
16,
17,
17,
17,
18,
17,
19,
18,
0,
18,
1,
18,
2,
18,
3,
18,
4,
18,
5,
18,
6,
18,
7,
18,
8,
18,
9,
18,
10,
18,
11,
18,
12,
18,
13,
18,
14,
18,
15,
18,
16,
18,
17,
18,
18,
18,
19,
19,
0,
19,
1,
19,
2,
19,
3,
19,
4,
19,
5,
19,
6,
19,
7,
19,
8,
19,
9,
19,
10,
19,
11,
19,
12,
19,
13,
19,
14,
19,
15,
19,
16,
19,
17,
19,
18,
19,
19,
};
const int32_t c_aaiHuffDemod15[576][2] = {
0,
0,
0,
1,
0,
2,
0,
3,
0,
4,
0,
5,
0,
6,
0,
7,
0,
8,
0,
9,
0,
10,
0,
11,
0,
12,
0,
13,
0,
14,
0,
15,
0,
16,
0,
17,
0,
18,
0,
19,
0,
20,
0,
21,
0,
22,
0,
23,
1,
0,
1,
1,
1,
2,
1,
3,
1,
4,
1,
5,
1,
6,
1,
7,
1,
8,
1,
9,
1,
10,
1,
11,
1,
12,
1,
13,
1,
14,
1,
15,
1,
16,
1,
17,
1,
18,
1,
19,
1,
20,
1,
21,
1,
22,
1,
23,
2,
0,
2,
1,
2,
2,
2,
3,
2,
4,
2,
5,
2,
6,
2,
7,
2,
8,
2,
9,
2,
10,
2,
11,
2,
12,
2,
13,
2,
14,
2,
15,
2,
16,
2,
17,
2,
18,
2,
19,
2,
20,
2,
21,
2,
22,
2,
23,
3,
0,
3,
1,
3,
2,
3,
3,
3,
4,
3,
5,
3,
6,
3,
7,
3,
8,
3,
9,
3,
10,
3,
11,
3,
12,
3,
13,
3,
14,
3,
15,
3,
16,
3,
17,
3,
18,
3,
19,
3,
20,
3,
21,
3,
22,
3,
23,
4,
0,
4,
1,
4,
2,
4,
3,
4,
4,
4,
5,
4,
6,
4,
7,
4,
8,
4,
9,
4,
10,
4,
11,
4,
12,
4,
13,
4,
14,
4,
15,
4,
16,
4,
17,
4,
18,
4,
19,
4,
20,
4,
21,
4,
22,
4,
23,
5,
0,
5,
1,
5,
2,
5,
3,
5,
4,
5,
5,
5,
6,
5,
7,
5,
8,
5,
9,
5,
10,
5,
11,
5,
12,
5,
13,
5,
14,
5,
15,
5,
16,
5,
17,
5,
18,
5,
19,
5,
20,
5,
21,
5,
22,
5,
23,
6,
0,
6,
1,
6,
2,
6,
3,
6,
4,
6,
5,
6,
6,
6,
7,
6,
8,
6,
9,
6,
10,
6,
11,
6,
12,
6,
13,
6,
14,
6,
15,
6,
16,
6,
17,
6,
18,
6,
19,
6,
20,
6,
21,
6,
22,
6,
23,
7,
0,
7,
1,
7,
2,
7,
3,
7,
4,
7,
5,
7,
6,
7,
7,
7,
8,
7,
9,
7,
10,
7,
11,
7,
12,
7,
13,
7,
14,
7,
15,
7,
16,
7,
17,
7,
18,
7,
19,
7,
20,
7,
21,
7,
22,
7,
23,
8,
0,
8,
1,
8,
2,
8,
3,
8,
4,
8,
5,
8,
6,
8,
7,
8,
8,
8,
9,
8,
10,
8,
11,
8,
12,
8,
13,
8,
14,
8,
15,
8,
16,
8,
17,
8,
18,
8,
19,
8,
20,
8,
21,
8,
22,
8,
23,
9,
0,
9,
1,
9,
2,
9,
3,
9,
4,
9,
5,
9,
6,
9,
7,
9,
8,
9,
9,
9,
10,
9,
11,
9,
12,
9,
13,
9,
14,
9,
15,
9,
16,
9,
17,
9,
18,
9,
19,
9,
20,
9,
21,
9,
22,
9,
23,
10,
0,
10,
1,
10,
2,
10,
3,
10,
4,
10,
5,
10,
6,
10,
7,
10,
8,
10,
9,
10,
10,
10,
11,
10,
12,
10,
13,
10,
14,
10,
15,
10,
16,
10,
17,
10,
18,
10,
19,
10,
20,
10,
21,
10,
22,
10,
23,
11,
0,
11,
1,
11,
2,
11,
3,
11,
4,
11,
5,
11,
6,
11,
7,
11,
8,
11,
9,
11,
10,
11,
11,
11,
12,
11,
13,
11,
14,
11,
15,
11,
16,
11,
17,
11,
18,
11,
19,
11,
20,
11,
21,
11,
22,
11,
23,
12,
0,
12,
1,
12,
2,
12,
3,
12,
4,
12,
5,
12,
6,
12,
7,
12,
8,
12,
9,
12,
10,
12,
11,
12,
12,
12,
13,
12,
14,
12,
15,
12,
16,
12,
17,
12,
18,
12,
19,
12,
20,
12,
21,
12,
22,
12,
23,
13,
0,
13,
1,
13,
2,
13,
3,
13,
4,
13,
5,
13,
6,
13,
7,
13,
8,
13,
9,
13,
10,
13,
11,
13,
12,
13,
13,
13,
14,
13,
15,
13,
16,
13,
17,
13,
18,
13,
19,
13,
20,
13,
21,
13,
22,
13,
23,
14,
0,
14,
1,
14,
2,
14,
3,
14,
4,
14,
5,
14,
6,
14,
7,
14,
8,
14,
9,
14,
10,
14,
11,
14,
12,
14,
13,
14,
14,
14,
15,
14,
16,
14,
17,
14,
18,
14,
19,
14,
20,
14,
21,
14,
22,
14,
23,
15,
0,
15,
1,
15,
2,
15,
3,
15,
4,
15,
5,
15,
6,
15,
7,
15,
8,
15,
9,
15,
10,
15,
11,
15,
12,
15,
13,
15,
14,
15,
15,
15,
16,
15,
17,
15,
18,
15,
19,
15,
20,
15,
21,
15,
22,
15,
23,
16,
0,
16,
1,
16,
2,
16,
3,
16,
4,
16,
5,
16,
6,
16,
7,
16,
8,
16,
9,
16,
10,
16,
11,
16,
12,
16,
13,
16,
14,
16,
15,
16,
16,
16,
17,
16,
18,
16,
19,
16,
20,
16,
21,
16,
22,
16,
23,
17,
0,
17,
1,
17,
2,
17,
3,
17,
4,
17,
5,
17,
6,
17,
7,
17,
8,
17,
9,
17,
10,
17,
11,
17,
12,
17,
13,
17,
14,
17,
15,
17,
16,
17,
17,
17,
18,
17,
19,
17,
20,
17,
21,
17,
22,
17,
23,
18,
0,
18,
1,
18,
2,
18,
3,
18,
4,
18,
5,
18,
6,
18,
7,
18,
8,
18,
9,
18,
10,
18,
11,
18,
12,
18,
13,
18,
14,
18,
15,
18,
16,
18,
17,
18,
18,
18,
19,
18,
20,
18,
21,
18,
22,
18,
23,
19,
0,
19,
1,
19,
2,
19,
3,
19,
4,
19,
5,
19,
6,
19,
7,
19,
8,
19,
9,
19,
10,
19,
11,
19,
12,
19,
13,
19,
14,
19,
15,
19,
16,
19,
17,
19,
18,
19,
19,
19,
20,
19,
21,
19,
22,
19,
23,
20,
0,
20,
1,
20,
2,
20,
3,
20,
4,
20,
5,
20,
6,
20,
7,
20,
8,
20,
9,
20,
10,
20,
11,
20,
12,
20,
13,
20,
14,
20,
15,
20,
16,
20,
17,
20,
18,
20,
19,
20,
20,
20,
21,
20,
22,
20,
23,
21,
0,
21,
1,
21,
2,
21,
3,
21,
4,
21,
5,
21,
6,
21,
7,
21,
8,
21,
9,
21,
10,
21,
11,
21,
12,
21,
13,
21,
14,
21,
15,
21,
16,
21,
17,
21,
18,
21,
19,
21,
20,
21,
21,
21,
22,
21,
23,
22,
0,
22,
1,
22,
2,
22,
3,
22,
4,
22,
5,
22,
6,
22,
7,
22,
8,
22,
9,
22,
10,
22,
11,
22,
12,
22,
13,
22,
14,
22,
15,
22,
16,
22,
17,
22,
18,
22,
19,
22,
20,
22,
21,
22,
22,
22,
23,
23,
0,
23,
1,
23,
2,
23,
3,
23,
4,
23,
5,
23,
6,
23,
7,
23,
8,
23,
9,
23,
10,
23,
11,
23,
12,
23,
13,
23,
14,
23,
15,
23,
16,
23,
17,
23,
18,
23,
19,
23,
20,
23,
21,
23,
22,
23,
23,
};
const int32_t c_aaiHuffDemod16[729][2] = {
0,
0,
0,
1,
0,
2,
0,
3,
0,
4,
0,
5,
0,
6,
0,
7,
0,
8,
0,
9,
0,
10,
0,
11,
0,
12,
0,
13,
0,
14,
0,
15,
0,
16,
0,
17,
0,
18,
0,
19,
0,
20,
0,
21,
0,
22,
0,
23,
0,
24,
0,
25,
0,
26,
1,
0,
1,
1,
1,
2,
1,
3,
1,
4,
1,
5,
1,
6,
1,
7,
1,
8,
1,
9,
1,
10,
1,
11,
1,
12,
1,
13,
1,
14,
1,
15,
1,
16,
1,
17,
1,
18,
1,
19,
1,
20,
1,
21,
1,
22,
1,
23,
1,
24,
1,
25,
1,
26,
2,
0,
2,
1,
2,
2,
2,
3,
2,
4,
2,
5,
2,
6,
2,
7,
2,
8,
2,
9,
2,
10,
2,
11,
2,
12,
2,
13,
2,
14,
2,
15,
2,
16,
2,
17,
2,
18,
2,
19,
2,
20,
2,
21,
2,
22,
2,
23,
2,
24,
2,
25,
2,
26,
3,
0,
3,
1,
3,
2,
3,
3,
3,
4,
3,
5,
3,
6,
3,
7,
3,
8,
3,
9,
3,
10,
3,
11,
3,
12,
3,
13,
3,
14,
3,
15,
3,
16,
3,
17,
3,
18,
3,
19,
3,
20,
3,
21,
3,
22,
3,
23,
3,
24,
3,
25,
3,
26,
4,
0,
4,
1,
4,
2,
4,
3,
4,
4,
4,
5,
4,
6,
4,
7,
4,
8,
4,
9,
4,
10,
4,
11,
4,
12,
4,
13,
4,
14,
4,
15,
4,
16,
4,
17,
4,
18,
4,
19,
4,
20,
4,
21,
4,
22,
4,
23,
4,
24,
4,
25,
4,
26,
5,
0,
5,
1,
5,
2,
5,
3,
5,
4,
5,
5,
5,
6,
5,
7,
5,
8,
5,
9,
5,
10,
5,
11,
5,
12,
5,
13,
5,
14,
5,
15,
5,
16,
5,
17,
5,
18,
5,
19,
5,
20,
5,
21,
5,
22,
5,
23,
5,
24,
5,
25,
5,
26,
6,
0,
6,
1,
6,
2,
6,
3,
6,
4,
6,
5,
6,
6,
6,
7,
6,
8,
6,
9,
6,
10,
6,
11,
6,
12,
6,
13,
6,
14,
6,
15,
6,
16,
6,
17,
6,
18,
6,
19,
6,
20,
6,
21,
6,
22,
6,
23,
6,
24,
6,
25,
6,
26,
7,
0,
7,
1,
7,
2,
7,
3,
7,
4,
7,
5,
7,
6,
7,
7,
7,
8,
7,
9,
7,
10,
7,
11,
7,
12,
7,
13,
7,
14,
7,
15,
7,
16,
7,
17,
7,
18,
7,
19,
7,
20,
7,
21,
7,
22,
7,
23,
7,
24,
7,
25,
7,
26,
8,
0,
8,
1,
8,
2,
8,
3,
8,
4,
8,
5,
8,
6,
8,
7,
8,
8,
8,
9,
8,
10,
8,
11,
8,
12,
8,
13,
8,
14,
8,
15,
8,
16,
8,
17,
8,
18,
8,
19,
8,
20,
8,
21,
8,
22,
8,
23,
8,
24,
8,
25,
8,
26,
9,
0,
9,
1,
9,
2,
9,
3,
9,
4,
9,
5,
9,
6,
9,
7,
9,
8,
9,
9,
9,
10,
9,
11,
9,
12,
9,
13,
9,
14,
9,
15,
9,
16,
9,
17,
9,
18,
9,
19,
9,
20,
9,
21,
9,
22,
9,
23,
9,
24,
9,
25,
9,
26,
10,
0,
10,
1,
10,
2,
10,
3,
10,
4,
10,
5,
10,
6,
10,
7,
10,
8,
10,
9,
10,
10,
10,
11,
10,
12,
10,
13,
10,
14,
10,
15,
10,
16,
10,
17,
10,
18,
10,
19,
10,
20,
10,
21,
10,
22,
10,
23,
10,
24,
10,
25,
10,
26,
11,
0,
11,
1,
11,
2,
11,
3,
11,
4,
11,
5,
11,
6,
11,
7,
11,
8,
11,
9,
11,
10,
11,
11,
11,
12,
11,
13,
11,
14,
11,
15,
11,
16,
11,
17,
11,
18,
11,
19,
11,
20,
11,
21,
11,
22,
11,
23,
11,
24,
11,
25,
11,
26,
12,
0,
12,
1,
12,
2,
12,
3,
12,
4,
12,
5,
12,
6,
12,
7,
12,
8,
12,
9,
12,
10,
12,
11,
12,
12,
12,
13,
12,
14,
12,
15,
12,
16,
12,
17,
12,
18,
12,
19,
12,
20,
12,
21,
12,
22,
12,
23,
12,
24,
12,
25,
12,
26,
13,
0,
13,
1,
13,
2,
13,
3,
13,
4,
13,
5,
13,
6,
13,
7,
13,
8,
13,
9,
13,
10,
13,
11,
13,
12,
13,
13,
13,
14,
13,
15,
13,
16,
13,
17,
13,
18,
13,
19,
13,
20,
13,
21,
13,
22,
13,
23,
13,
24,
13,
25,
13,
26,
14,
0,
14,
1,
14,
2,
14,
3,
14,
4,
14,
5,
14,
6,
14,
7,
14,
8,
14,
9,
14,
10,
14,
11,
14,
12,
14,
13,
14,
14,
14,
15,
14,
16,
14,
17,
14,
18,
14,
19,
14,
20,
14,
21,
14,
22,
14,
23,
14,
24,
14,
25,
14,
26,
15,
0,
15,
1,
15,
2,
15,
3,
15,
4,
15,
5,
15,
6,
15,
7,
15,
8,
15,
9,
15,
10,
15,
11,
15,
12,
15,
13,
15,
14,
15,
15,
15,
16,
15,
17,
15,
18,
15,
19,
15,
20,
15,
21,
15,
22,
15,
23,
15,
24,
15,
25,
15,
26,
16,
0,
16,
1,
16,
2,
16,
3,
16,
4,
16,
5,
16,
6,
16,
7,
16,
8,
16,
9,
16,
10,
16,
11,
16,
12,
16,
13,
16,
14,
16,
15,
16,
16,
16,
17,
16,
18,
16,
19,
16,
20,
16,
21,
16,
22,
16,
23,
16,
24,
16,
25,
16,
26,
17,
0,
17,
1,
17,
2,
17,
3,
17,
4,
17,
5,
17,
6,
17,
7,
17,
8,
17,
9,
17,
10,
17,
11,
17,
12,
17,
13,
17,
14,
17,
15,
17,
16,
17,
17,
17,
18,
17,
19,
17,
20,
17,
21,
17,
22,
17,
23,
17,
24,
17,
25,
17,
26,
18,
0,
18,
1,
18,
2,
18,
3,
18,
4,
18,
5,
18,
6,
18,
7,
18,
8,
18,
9,
18,
10,
18,
11,
18,
12,
18,
13,
18,
14,
18,
15,
18,
16,
18,
17,
18,
18,
18,
19,
18,
20,
18,
21,
18,
22,
18,
23,
18,
24,
18,
25,
18,
26,
19,
0,
19,
1,
19,
2,
19,
3,
19,
4,
19,
5,
19,
6,
19,
7,
19,
8,
19,
9,
19,
10,
19,
11,
19,
12,
19,
13,
19,
14,
19,
15,
19,
16,
19,
17,
19,
18,
19,
19,
19,
20,
19,
21,
19,
22,
19,
23,
19,
24,
19,
25,
19,
26,
20,
0,
20,
1,
20,
2,
20,
3,
20,
4,
20,
5,
20,
6,
20,
7,
20,
8,
20,
9,
20,
10,
20,
11,
20,
12,
20,
13,
20,
14,
20,
15,
20,
16,
20,
17,
20,
18,
20,
19,
20,
20,
20,
21,
20,
22,
20,
23,
20,
24,
20,
25,
20,
26,
21,
0,
21,
1,
21,
2,
21,
3,
21,
4,
21,
5,
21,
6,
21,
7,
21,
8,
21,
9,
21,
10,
21,
11,
21,
12,
21,
13,
21,
14,
21,
15,
21,
16,
21,
17,
21,
18,
21,
19,
21,
20,
21,
21,
21,
22,
21,
23,
21,
24,
21,
25,
21,
26,
22,
0,
22,
1,
22,
2,
22,
3,
22,
4,
22,
5,
22,
6,
22,
7,
22,
8,
22,
9,
22,
10,
22,
11,
22,
12,
22,
13,
22,
14,
22,
15,
22,
16,
22,
17,
22,
18,
22,
19,
22,
20,
22,
21,
22,
22,
22,
23,
22,
24,
22,
25,
22,
26,
23,
0,
23,
1,
23,
2,
23,
3,
23,
4,
23,
5,
23,
6,
23,
7,
23,
8,
23,
9,
23,
10,
23,
11,
23,
12,
23,
13,
23,
14,
23,
15,
23,
16,
23,
17,
23,
18,
23,
19,
23,
20,
23,
21,
23,
22,
23,
23,
23,
24,
23,
25,
23,
26,
24,
0,
24,
1,
24,
2,
24,
3,
24,
4,
24,
5,
24,
6,
24,
7,
24,
8,
24,
9,
24,
10,
24,
11,
24,
12,
24,
13,
24,
14,
24,
15,
24,
16,
24,
17,
24,
18,
24,
19,
24,
20,
24,
21,
24,
22,
24,
23,
24,
24,
24,
25,
24,
26,
25,
0,
25,
1,
25,
2,
25,
3,
25,
4,
25,
5,
25,
6,
25,
7,
25,
8,
25,
9,
25,
10,
25,
11,
25,
12,
25,
13,
25,
14,
25,
15,
25,
16,
25,
17,
25,
18,
25,
19,
25,
20,
25,
21,
25,
22,
25,
23,
25,
24,
25,
25,
25,
26,
26,
0,
26,
1,
26,
2,
26,
3,
26,
4,
26,
5,
26,
6,
26,
7,
26,
8,
26,
9,
26,
10,
26,
11,
26,
12,
26,
13,
26,
14,
26,
15,
26,
16,
26,
17,
26,
18,
26,
19,
26,
20,
26,
21,
26,
22,
26,
23,
26,
24,
26,
25,
26,
26,
};
const int32_t c_aaiHuffDemod17[729][2] = {
0,
0,
0,
1,
0,
2,
0,
3,
0,
4,
0,
5,
0,
6,
0,
7,
0,
8,
0,
9,
0,
10,
0,
11,
0,
12,
0,
13,
0,
14,
0,
15,
0,
16,
0,
17,
0,
18,
0,
19,
0,
20,
0,
21,
0,
22,
0,
23,
0,
24,
0,
25,
0,
26,
1,
0,
1,
1,
1,
2,
1,
3,
1,
4,
1,
5,
1,
6,
1,
7,
1,
8,
1,
9,
1,
10,
1,
11,
1,
12,
1,
13,
1,
14,
1,
15,
1,
16,
1,
17,
1,
18,
1,
19,
1,
20,
1,
21,
1,
22,
1,
23,
1,
24,
1,
25,
1,
26,
2,
0,
2,
1,
2,
2,
2,
3,
2,
4,
2,
5,
2,
6,
2,
7,
2,
8,
2,
9,
2,
10,
2,
11,
2,
12,
2,
13,
2,
14,
2,
15,
2,
16,
2,
17,
2,
18,
2,
19,
2,
20,
2,
21,
2,
22,
2,
23,
2,
24,
2,
25,
2,
26,
3,
0,
3,
1,
3,
2,
3,
3,
3,
4,
3,
5,
3,
6,
3,
7,
3,
8,
3,
9,
3,
10,
3,
11,
3,
12,
3,
13,
3,
14,
3,
15,
3,
16,
3,
17,
3,
18,
3,
19,
3,
20,
3,
21,
3,
22,
3,
23,
3,
24,
3,
25,
3,
26,
4,
0,
4,
1,
4,
2,
4,
3,
4,
4,
4,
5,
4,
6,
4,
7,
4,
8,
4,
9,
4,
10,
4,
11,
4,
12,
4,
13,
4,
14,
4,
15,
4,
16,
4,
17,
4,
18,
4,
19,
4,
20,
4,
21,
4,
22,
4,
23,
4,
24,
4,
25,
4,
26,
5,
0,
5,
1,
5,
2,
5,
3,
5,
4,
5,
5,
5,
6,
5,
7,
5,
8,
5,
9,
5,
10,
5,
11,
5,
12,
5,
13,
5,
14,
5,
15,
5,
16,
5,
17,
5,
18,
5,
19,
5,
20,
5,
21,
5,
22,
5,
23,
5,
24,
5,
25,
5,
26,
6,
0,
6,
1,
6,
2,
6,
3,
6,
4,
6,
5,
6,
6,
6,
7,
6,
8,
6,
9,
6,
10,
6,
11,
6,
12,
6,
13,
6,
14,
6,
15,
6,
16,
6,
17,
6,
18,
6,
19,
6,
20,
6,
21,
6,
22,
6,
23,
6,
24,
6,
25,
6,
26,
7,
0,
7,
1,
7,
2,
7,
3,
7,
4,
7,
5,
7,
6,
7,
7,
7,
8,
7,
9,
7,
10,
7,
11,
7,
12,
7,
13,
7,
14,
7,
15,
7,
16,
7,
17,
7,
18,
7,
19,
7,
20,
7,
21,
7,
22,
7,
23,
7,
24,
7,
25,
7,
26,
8,
0,
8,
1,
8,
2,
8,
3,
8,
4,
8,
5,
8,
6,
8,
7,
8,
8,
8,
9,
8,
10,
8,
11,
8,
12,
8,
13,
8,
14,
8,
15,
8,
16,
8,
17,
8,
18,
8,
19,
8,
20,
8,
21,
8,
22,
8,
23,
8,
24,
8,
25,
8,
26,
9,
0,
9,
1,
9,
2,
9,
3,
9,
4,
9,
5,
9,
6,
9,
7,
9,
8,
9,
9,
9,
10,
9,
11,
9,
12,
9,
13,
9,
14,
9,
15,
9,
16,
9,
17,
9,
18,
9,
19,
9,
20,
9,
21,
9,
22,
9,
23,
9,
24,
9,
25,
9,
26,
10,
0,
10,
1,
10,
2,
10,
3,
10,
4,
10,
5,
10,
6,
10,
7,
10,
8,
10,
9,
10,
10,
10,
11,
10,
12,
10,
13,
10,
14,
10,
15,
10,
16,
10,
17,
10,
18,
10,
19,
10,
20,
10,
21,
10,
22,
10,
23,
10,
24,
10,
25,
10,
26,
11,
0,
11,
1,
11,
2,
11,
3,
11,
4,
11,
5,
11,
6,
11,
7,
11,
8,
11,
9,
11,
10,
11,
11,
11,
12,
11,
13,
11,
14,
11,
15,
11,
16,
11,
17,
11,
18,
11,
19,
11,
20,
11,
21,
11,
22,
11,
23,
11,
24,
11,
25,
11,
26,
12,
0,
12,
1,
12,
2,
12,
3,
12,
4,
12,
5,
12,
6,
12,
7,
12,
8,
12,
9,
12,
10,
12,
11,
12,
12,
12,
13,
12,
14,
12,
15,
12,
16,
12,
17,
12,
18,
12,
19,
12,
20,
12,
21,
12,
22,
12,
23,
12,
24,
12,
25,
12,
26,
13,
0,
13,
1,
13,
2,
13,
3,
13,
4,
13,
5,
13,
6,
13,
7,
13,
8,
13,
9,
13,
10,
13,
11,
13,
12,
13,
13,
13,
14,
13,
15,
13,
16,
13,
17,
13,
18,
13,
19,
13,
20,
13,
21,
13,
22,
13,
23,
13,
24,
13,
25,
13,
26,
14,
0,
14,
1,
14,
2,
14,
3,
14,
4,
14,
5,
14,
6,
14,
7,
14,
8,
14,
9,
14,
10,
14,
11,
14,
12,
14,
13,
14,
14,
14,
15,
14,
16,
14,
17,
14,
18,
14,
19,
14,
20,
14,
21,
14,
22,
14,
23,
14,
24,
14,
25,
14,
26,
15,
0,
15,
1,
15,
2,
15,
3,
15,
4,
15,
5,
15,
6,
15,
7,
15,
8,
15,
9,
15,
10,
15,
11,
15,
12,
15,
13,
15,
14,
15,
15,
15,
16,
15,
17,
15,
18,
15,
19,
15,
20,
15,
21,
15,
22,
15,
23,
15,
24,
15,
25,
15,
26,
16,
0,
16,
1,
16,
2,
16,
3,
16,
4,
16,
5,
16,
6,
16,
7,
16,
8,
16,
9,
16,
10,
16,
11,
16,
12,
16,
13,
16,
14,
16,
15,
16,
16,
16,
17,
16,
18,
16,
19,
16,
20,
16,
21,
16,
22,
16,
23,
16,
24,
16,
25,
16,
26,
17,
0,
17,
1,
17,
2,
17,
3,
17,
4,
17,
5,
17,
6,
17,
7,
17,
8,
17,
9,
17,
10,
17,
11,
17,
12,
17,
13,
17,
14,
17,
15,
17,
16,
17,
17,
17,
18,
17,
19,
17,
20,
17,
21,
17,
22,
17,
23,
17,
24,
17,
25,
17,
26,
18,
0,
18,
1,
18,
2,
18,
3,
18,
4,
18,
5,
18,
6,
18,
7,
18,
8,
18,
9,
18,
10,
18,
11,
18,
12,
18,
13,
18,
14,
18,
15,
18,
16,
18,
17,
18,
18,
18,
19,
18,
20,
18,
21,
18,
22,
18,
23,
18,
24,
18,
25,
18,
26,
19,
0,
19,
1,
19,
2,
19,
3,
19,
4,
19,
5,
19,
6,
19,
7,
19,
8,
19,
9,
19,
10,
19,
11,
19,
12,
19,
13,
19,
14,
19,
15,
19,
16,
19,
17,
19,
18,
19,
19,
19,
20,
19,
21,
19,
22,
19,
23,
19,
24,
19,
25,
19,
26,
20,
0,
20,
1,
20,
2,
20,
3,
20,
4,
20,
5,
20,
6,
20,
7,
20,
8,
20,
9,
20,
10,
20,
11,
20,
12,
20,
13,
20,
14,
20,
15,
20,
16,
20,
17,
20,
18,
20,
19,
20,
20,
20,
21,
20,
22,
20,
23,
20,
24,
20,
25,
20,
26,
21,
0,
21,
1,
21,
2,
21,
3,
21,
4,
21,
5,
21,
6,
21,
7,
21,
8,
21,
9,
21,
10,
21,
11,
21,
12,
21,
13,
21,
14,
21,
15,
21,
16,
21,
17,
21,
18,
21,
19,
21,
20,
21,
21,
21,
22,
21,
23,
21,
24,
21,
25,
21,
26,
22,
0,
22,
1,
22,
2,
22,
3,
22,
4,
22,
5,
22,
6,
22,
7,
22,
8,
22,
9,
22,
10,
22,
11,
22,
12,
22,
13,
22,
14,
22,
15,
22,
16,
22,
17,
22,
18,
22,
19,
22,
20,
22,
21,
22,
22,
22,
23,
22,
24,
22,
25,
22,
26,
23,
0,
23,
1,
23,
2,
23,
3,
23,
4,
23,
5,
23,
6,
23,
7,
23,
8,
23,
9,
23,
10,
23,
11,
23,
12,
23,
13,
23,
14,
23,
15,
23,
16,
23,
17,
23,
18,
23,
19,
23,
20,
23,
21,
23,
22,
23,
23,
23,
24,
23,
25,
23,
26,
24,
0,
24,
1,
24,
2,
24,
3,
24,
4,
24,
5,
24,
6,
24,
7,
24,
8,
24,
9,
24,
10,
24,
11,
24,
12,
24,
13,
24,
14,
24,
15,
24,
16,
24,
17,
24,
18,
24,
19,
24,
20,
24,
21,
24,
22,
24,
23,
24,
24,
24,
25,
24,
26,
25,
0,
25,
1,
25,
2,
25,
3,
25,
4,
25,
5,
25,
6,
25,
7,
25,
8,
25,
9,
25,
10,
25,
11,
25,
12,
25,
13,
25,
14,
25,
15,
25,
16,
25,
17,
25,
18,
25,
19,
25,
20,
25,
21,
25,
22,
25,
23,
25,
24,
25,
25,
25,
26,
26,
0,
26,
1,
26,
2,
26,
3,
26,
4,
26,
5,
26,
6,
26,
7,
26,
8,
26,
9,
26,
10,
26,
11,
26,
12,
26,
13,
26,
14,
26,
15,
26,
16,
26,
17,
26,
18,
26,
19,
26,
20,
26,
21,
26,
22,
26,
23,
26,
24,
26,
25,
26,
26,
};
const int32_t ( *c_apaiDemodTables[ALLOC_TABLE_SIZE] )[2] = {
NULL,
c_aaiHuffDemod1,
c_aaiHuffDemod2,
c_aaiHuffDemod3,
c_aaiHuffDemod4,
c_aaiHuffDemod5,
c_aaiHuffDemod6,
c_aaiHuffDemod7,
c_aaiHuffDemod8,
c_aaiHuffDemod9,
c_aaiHuffDemod10,
c_aaiHuffDemod11,
c_aaiHuffDemod12,
c_aaiHuffDemod13,
c_aaiHuffDemod14,
c_aaiHuffDemod15,
c_aaiHuffDemod16,
c_aaiHuffDemod17,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
};
#endif
const int32_t c_aiLogAddTable[LOG_ADD_TABLE_LENGTH] = { const int32_t c_aiLogAddTable[LOG_ADD_TABLE_LENGTH] = {
0x40, 0x40,
......
...@@ -30,15 +30,16 @@ ...@@ -30,15 +30,16 @@
*******************************************************************************************************/ *******************************************************************************************************/
#ifndef _IVAS_TABLES_H_ #ifndef ISAR_ROM_LCLD_TABLES_H
#define _IVAS_TABLES_H_ #define ISAR_ROM_LCLD_TABLES_H
#include <stdint.h> #include <stdint.h>
#include "options.h" #include "options.h"
#ifdef SPLIT_REND_WITH_HEAD_ROT
#ifndef M_PI #ifndef M_PI
#define M_PI 3.14159265358979323846264338327950288f // todo: replace by EVS_PI #define M_PI 3.14159265358979323846264338327950288f
#endif #endif
...@@ -47,7 +48,6 @@ ...@@ -47,7 +48,6 @@
#define LCLD_BANDS ( 60 ) #define LCLD_BANDS ( 60 )
#define LCLD_PRED_WIN_LEN ( 16 ) #define LCLD_PRED_WIN_LEN ( 16 )
#define LCLD_MAX_NUM_PRED_SUBSETS ( 8 ) #define LCLD_MAX_NUM_PRED_SUBSETS ( 8 )
#define MAX_BANDS ( 23 ) #define MAX_BANDS ( 23 )
#define MAX_BANDS_48 ( 23 ) #define MAX_BANDS_48 ( 23 )
#define DEF_BANDS_48 ( 22 ) #define DEF_BANDS_48 ( 22 )
...@@ -93,10 +93,10 @@ ...@@ -93,10 +93,10 @@
#define PERCEPTUAL_MODEL_SLGAIN_SHIFT ( 8 ) #define PERCEPTUAL_MODEL_SLGAIN_SHIFT ( 8 )
//#define USE_DEMOD_TABLES
#define HUFF_DEC_TABLE_SIZE ( 16 ) #define HUFF_DEC_TABLE_SIZE ( 16 )
extern const int32_t c_aiNumLcldBandsPerBand[MAX_BANDS_48];
extern const int32_t c_aiBandIdPerLcldBand[LCLD_BANDS];
extern const float c_afRotRealImag[PRED_MAX_VAL - PRED_MIN_VAL + 1][2]; extern const float c_afRotRealImag[PRED_MAX_VAL - PRED_MIN_VAL + 1][2];
extern const int32_t c_aiDefaultTheta48[MAX_BANDS_48]; extern const int32_t c_aiDefaultTheta48[MAX_BANDS_48];
...@@ -190,30 +190,8 @@ extern const uint16_t c_aauiLCLDHuffEnc62[153][2]; ...@@ -190,30 +190,8 @@ extern const uint16_t c_aauiLCLDHuffEnc62[153][2];
extern const uint16_t c_aauiLCLDHuffEnc63[181][2]; extern const uint16_t c_aauiLCLDHuffEnc63[181][2];
extern const uint16_t ( *c_apauiHuffEncTabels[2 * ALLOC_TABLE_SIZE] )[2]; extern const uint16_t ( *c_apauiHuffEncTabels[2 * ALLOC_TABLE_SIZE] )[2];
extern const uint32_t num_row_aauiLCLDHuff[2 * ALLOC_TABLE_SIZE]; extern const uint32_t num_row_aauiLCLDHuff[2 * ALLOC_TABLE_SIZE];
#ifdef USE_DEMOD_TABLES
extern const int32_t c_aaiHuffDemod1[16][2];
extern const int32_t c_aaiHuffDemod2[16][2];
extern const int32_t c_aaiHuffDemod3[25][2];
extern const int32_t c_aaiHuffDemod4[36][2];
extern const int32_t c_aaiHuffDemod5[36][2];
extern const int32_t c_aaiHuffDemod6[49][2];
extern const int32_t c_aaiHuffDemod7[64][2];
extern const int32_t c_aaiHuffDemod8[81][2];
extern const int32_t c_aaiHuffDemod9[100][2];
extern const int32_t c_aaiHuffDemod10[169][2];
extern const int32_t c_aaiHuffDemod11[196][2];
extern const int32_t c_aaiHuffDemod12[289][2];
extern const int32_t c_aaiHuffDemod13[324][2];
extern const int32_t c_aaiHuffDemod14[400][2];
extern const int32_t c_aaiHuffDemod15[576][2];
extern const int32_t c_aaiHuffDemod16[729][2];
extern const int32_t c_aaiHuffDemod17[729][2];
extern const int32_t ( *c_apaiDemodTables[ALLOC_TABLE_SIZE] )[2];
#endif
extern const uint32_t c_aaiRMSEnvHuffEnc[64][2]; extern const uint32_t c_aaiRMSEnvHuffEnc[64][2];
extern const uint32_t c_aaiRMSEnvHuffDec[13][HUFF_DEC_TABLE_SIZE]; extern const uint32_t c_aaiRMSEnvHuffDec[13][HUFF_DEC_TABLE_SIZE];
#endif /*SPLIT_REND_WITH_HEAD_ROT*/
#endif /* ISAR_ROM_LCLD_TABLES_H_ */
#endif /* _TABLES_H_ */
/******************************************************************************************************
(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 <stdint.h>
#include "options.h"
#ifdef DEBUGGING
#include "debug.h"
#endif
#include "isar_cnst.h"
#include "wmc_auto.h"
/* clang-format off */
#ifdef SPLIT_REND_WITH_HEAD_ROT
/*----------------------------------------------------------------------*
* Binuaral split rendering ROM tables
*-----------------------------------------------------------------------*/
/* rotations in this array are relative to ref rotation */
const float isar_split_rend_relative_yaw_pos_angles[SPLIT_REND_MAX_YAW_ONLY_POSES] = {-15.0f, 15.0f};
const float isar_split_rend_relative_pitch_pos_angles[SPLIT_REND_MAX_PITCH_ONLY_POSES] = {10.0f, 10.0f};
const float isar_split_rend_relative_roll_pos_angles[SPLIT_REND_MAX_PITCH_ONLY_POSES] = {10.0f, 10.0f};
const float isar_split_rend_relative_one_axis_pos_angles[SPLIT_REND_MAX_ONE_AXIS_MD_POSES] = {-15.0f, 15.0f};
const float isar_split_rend_relative_yaw_pos_angles_hq[SPLIT_REND_MAX_YAW_ONLY_POSES] = {-15.0f, 15.0f};
const float isar_split_rend_relative_pitch_pos_angles_hq[SPLIT_REND_MAX_PITCH_ONLY_POSES] = {-15.0f, 15.0f};
const float isar_split_rend_relative_roll_pos_angles_hq[SPLIT_REND_MAX_PITCH_ONLY_POSES] = {-15.0f, 15.0f};
const float isar_split_rend_relative_one_axis_pos_angles_hq[SPLIT_REND_MAX_ONE_AXIS_MD_POSES] = {-15.0f, 15.0f};
const int16_t isar_split_rend_band_grouping[MAX_SPLIT_REND_MD_BANDS + 1] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 20, 25, 30, 35, 40, 50, 60
};
const int32_t isar_split_rend_huff_p_d_consts[ISAR_SPLIT_REND_D_QUANT_PNTS][3] =
{
{0,8,252},{1,8,253},{2,7,124},{3,6,60},{4,5,28},{5,4,12},
{6,3,4},{7,1,0},{8,3,5},{9,4,13},{10,5,29},{11,6,61},
{12,7,125},{13,8,254},{14,8,255}
};
const int32_t isar_split_rend_huff_p_d_diff_consts[ISAR_SPLIT_REND_D_QUANT_PNTS][3] =
{
{ 0, 1, 0 },{ 1, 2, 2 },{ 2, 3, 6 },{ 3, 4, 14 },
{ 4, 5, 30 },{ 5, 6, 62 },{ 6, 7, 126 },{ 7, 8, 254 },
{ 8, 9, 510 },{ 9, 10, 1022 },{ 10, 11, 2046 },{ 11, 12, 4094 },
{ 12, 13, 8190 },{ 13, 14, 16382 },{ 14, 14, 16383 }
};
const int32_t isar_split_rend_huff_d_consts[ISAR_SPLIT_REND_D_QUANT_PNTS][3] =
{
{ 0, 1, 0 },{ 1, 2, 2 },{ 2, 3, 6 },{ 3, 4, 14 },
{ 4, 5, 30 },{ 5, 6, 62 },{ 6, 7, 126 },{ 7, 8, 254 },
{ 8, 9, 510 },{ 9, 10, 1022 },{ 10, 11, 2046 },{ 11, 12, 4094 },
{ 12, 13, 8190 },{ 13, 14, 16382 },{ 14, 14, 16383 }
};
const int32_t isar_split_rend_huff_pred63_consts[ISAR_SPLIT_REND_PRED_63QUANT_PNTS][3] =
{
{-31,11,2040},
{-30,11,2041},
{-29,11,2042},
{-28,11,2043},
{-27,10,1012},
{-26,10,1013},
{-25,10,1014},
{-24,10,1015},
{-23,9,498},
{-22,9,499},
{-21,9,500},
{-20,9,501},
{-19,8,242},
{-18,8,243},
{-17,8,244},
{-16,8,245},
{-15,7,112},
{-14,7,113},
{-13,7,114},
{-12,7,115},
{-11,6,48},
{-10,6,49},
{-9,6,50},
{-8,6,51},
{-7,5,16},
{-6,5,17},
{-5,5,18},
{-4,5,19},
{-3,4,2},
{-2,4,3},
{-1,4,4},
{0,3,0},
{1,4,5},
{2,4,6},
{3,4,7},
{4,5,20},
{5,5,21},
{6,5,22},
{7,5,23},
{8,6,52},
{9,6,53},
{10,6,54},
{11,6,55},
{12,7,116},
{13,7,117},
{14,7,118},
{15,7,119},
{16,7,120},
{17,8,246},
{18,8,247},
{19,8,248},
{20,9,502},
{21,9,503},
{22,9,504},
{23,9,505},
{24,10,1016},
{25,10,1017},
{26,10,1018},
{27,10,1019},
{28,11,2044},
{29,11,2045},
{30,11,2046},
{31,11,2047},
};
const int32_t isar_split_rend_huff_pred31_consts[ISAR_SPLIT_REND_PRED_31QUANT_PNTS][3] =
{
{-15,10,1020},{-14,10,1021},{-13,9,506},{-12,9,507},
{-11,8,250},{-10,8,251},{-9,7,120},{-8,7,121},
{-7,6,56},{-6,6,57},{-5,5,24},{-4,5,25},{-3,4,8},
{-2,4,9},{-1,3,2},{0,2,0},{1,3,3},
{2,4,10},{3,4,11},{4,5,26},{5,5,27},
{6,6,58},{7,6,59},{8,7,122},{9,7,123},
{10,7,124},{11,8,252},{12,9,508},{13,9,509},
{14,10,1022},{15,10,1023},
};
const int32_t isar_split_rend_huff_roll_pred_consts[ISAR_SPLIT_REND_ROLL_PRED_QUANT_PNTS][3] =
{
{-15,10,1020},{-14,10,1021},{-13,9,506},{-12,9,507},
{-11,8,250},{-10,8,251},{-9,7,120},{-8,7,121},
{-7,6,56},{-6,6,57},{-5,5,24},{-4,5,25},{-3,4,8},
{-2,4,9},{-1,3,2},{0,2,0},{1,3,3},
{2,4,10},{3,4,11},{4,5,26},{5,5,27},
{6,6,58},{7,6,59},{8,7,122},{9,7,123},
{10,7,124},{11,8,252},{12,9,508},{13,9,509},
{14,10,1022},{15,10,1023},
};
#endif
/* clang-format on */
/******************************************************************************************************
(C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
contributors to this repository. All Rights Reserved.
This software is protected by copyright law and by international treaties.
The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
contributors to this repository retain full ownership rights in their respective contributions in
the software. This notice grants no license of any kind, including but not limited to patent
license, nor is any license granted by implication, estoppel or otherwise.
Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
contributions.
This software is provided "AS IS", without any express or implied warranties. The software is in the
development stage. It is intended exclusively for experts who have experience with such software and
solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
and fitness for a particular purpose are hereby disclaimed and excluded.
Any dispute, controversy or claim arising under or in relation to providing this software shall be
submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
the United Nations Convention on Contracts on the International Sales of Goods.
*******************************************************************************************************/
#ifndef ISAR_ROM_POST_REND_H
#define ISAR_ROM_POST_REND_H
#include <stdint.h>
#include "options.h"
#ifdef DEBUGGING
#include "debug.h"
#endif
#include "isar_cnst.h"
#ifdef SPLIT_REND_WITH_HEAD_ROT
/*----------------------------------------------------------------------*
* Binuaral split rendering ROM tables
*-----------------------------------------------------------------------*/
extern const float isar_split_rend_relative_yaw_pos_angles[SPLIT_REND_MAX_YAW_ONLY_POSES];
extern const float isar_split_rend_relative_pitch_pos_angles[SPLIT_REND_MAX_PITCH_ONLY_POSES];
extern const float isar_split_rend_relative_roll_pos_angles[SPLIT_REND_MAX_PITCH_ONLY_POSES];
extern const float isar_split_rend_relative_one_axis_pos_angles[SPLIT_REND_MAX_ONE_AXIS_MD_POSES];
extern const float isar_split_rend_relative_one_axis_pos_angles_hq[SPLIT_REND_MAX_ONE_AXIS_MD_POSES];
extern const float isar_split_rend_relative_yaw_pos_angles_hq[SPLIT_REND_MAX_YAW_ONLY_POSES];
extern const float isar_split_rend_relative_pitch_pos_angles_hq[SPLIT_REND_MAX_PITCH_ONLY_POSES];
extern const float isar_split_rend_relative_roll_pos_angles_hq[SPLIT_REND_MAX_PITCH_ONLY_POSES];
extern const float ivas_split_rend_relative_pos_angles[MAX_HEAD_ROT_POSES][3];
extern const int16_t isar_split_rend_band_grouping[MAX_SPLIT_REND_MD_BANDS + 1];
extern const int32_t isar_split_rend_huff_d_consts[ISAR_SPLIT_REND_D_QUANT_PNTS][3];
extern const int32_t isar_split_rend_huff_pred63_consts[ISAR_SPLIT_REND_PRED_31QUANT_PNTS][3];
extern const int32_t isar_split_rend_huff_pred31_consts[ISAR_SPLIT_REND_PRED_31QUANT_PNTS][3];
extern const int32_t isar_split_rend_huff_roll_pred_consts[ISAR_SPLIT_REND_ROLL_PRED_QUANT_PNTS][3];
extern const int32_t isar_split_rend_huff_p_d_consts[ISAR_SPLIT_REND_D_QUANT_PNTS][3];
extern const int32_t isar_split_rend_huff_p_d_diff_consts[ISAR_SPLIT_REND_D_QUANT_PNTS][3];
#endif
#endif
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
#include <stdint.h> #include <stdint.h>
#include "options.h" #include "options.h"
#ifdef SPLIT_REND_WITH_HEAD_ROT #ifdef SPLIT_REND_WITH_HEAD_ROT
#include "ivas_prot_rend.h" #include "isar_prot.h"
#include "ivas_prot.h" #include "ivas_prot.h"
#include "prot.h" #include "prot.h"
#ifdef DEBUGGING #ifdef DEBUGGING
...@@ -43,23 +43,23 @@ ...@@ -43,23 +43,23 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* Function ivas_splitBinLCLDDecOpen() * Function isar_splitBinLCLDDecOpen()
* *
* *
*------------------------------------------------------------------------*/ *------------------------------------------------------------------------*/
ivas_error ivas_splitBinLCLDDecOpen( ivas_error isar_splitBinLCLDDecOpen(
BIN_HR_SPLIT_LCLD_DEC_HANDLE *hSplitBinLCLDDec, ISAR_BIN_HR_SPLIT_LCLD_DEC_HANDLE *hSplitBinLCLDDec,
const int32_t iSampleRate, const int32_t iSampleRate,
const int16_t iChannels, const int16_t iChannels,
const int16_t iNumBlocks, const int16_t iNumBlocks,
const int16_t iNumIterations ) const int16_t iNumIterations )
{ {
int16_t n; int16_t n;
BIN_HR_SPLIT_LCLD_DEC_HANDLE splitBinLCLDDec; ISAR_BIN_HR_SPLIT_LCLD_DEC_HANDLE splitBinLCLDDec;
ivas_error error; ivas_error error;
if ( ( splitBinLCLDDec = (BIN_HR_SPLIT_LCLD_DEC_HANDLE) malloc( sizeof( BIN_HR_SPLIT_LCLD_DEC ) ) ) == NULL ) if ( ( splitBinLCLDDec = (ISAR_BIN_HR_SPLIT_LCLD_DEC_HANDLE) malloc( sizeof( ISAR_BIN_HR_SPLIT_LCLD_DEC ) ) ) == NULL )
{ {
return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD decoder Module \n" ) ); return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD decoder Module \n" ) );
} }
...@@ -68,7 +68,7 @@ ivas_error ivas_splitBinLCLDDecOpen( ...@@ -68,7 +68,7 @@ ivas_error ivas_splitBinLCLDDecOpen(
splitBinLCLDDec->iChannels = iChannels; splitBinLCLDDec->iChannels = iChannels;
if ( ( error = CreateLCLDDecoder( &splitBinLCLDDec->psLCLDDecoder, iSampleRate, iChannels, iNumBlocks ) ) != IVAS_ERR_OK ) if ( ( error = CreateLCLDDecoder( &splitBinLCLDDec->psLCLDDecoder, iSampleRate, iChannels, iNumBlocks, 0 ) ) != IVAS_ERR_OK )
{ {
return error; return error;
} }
...@@ -107,7 +107,7 @@ ivas_error ivas_splitBinLCLDDecOpen( ...@@ -107,7 +107,7 @@ ivas_error ivas_splitBinLCLDDecOpen(
fwrite( &num_bands, sizeof( int16_t ), 1, splitBinLCLDDec->cldfbOut ); fwrite( &num_bands, sizeof( int16_t ), 1, splitBinLCLDDec->cldfbOut );
#endif #endif
if ( ( error = ivas_splitBinRendPLCOpen( &splitBinLCLDDec->hSplitRendPLC ) ) != IVAS_ERR_OK ) if ( ( error = isar_splitBinRendPLCOpen( &splitBinLCLDDec->hSplitRendPLC, GetNumSubSets( splitBinLCLDDec->psLCLDDecoder ) ) ) != IVAS_ERR_OK )
{ {
return error; return error;
} }
...@@ -121,13 +121,13 @@ ivas_error ivas_splitBinLCLDDecOpen( ...@@ -121,13 +121,13 @@ ivas_error ivas_splitBinLCLDDecOpen(
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* Function ivas_splitBinLCLDDecClose() * Function isar_splitBinLCLDDecClose()
* *
* *
*------------------------------------------------------------------------*/ *------------------------------------------------------------------------*/
void ivas_splitBinLCLDDecClose( void isar_splitBinLCLDDecClose(
BIN_HR_SPLIT_LCLD_DEC_HANDLE *hSplitBinLCLDDec ) ISAR_BIN_HR_SPLIT_LCLD_DEC_HANDLE *hSplitBinLCLDDec )
{ {
int16_t n; int16_t n;
...@@ -152,7 +152,7 @@ void ivas_splitBinLCLDDecClose( ...@@ -152,7 +152,7 @@ void ivas_splitBinLCLDDecClose(
fclose( ( *hSplitBinLCLDDec )->cldfbOut ); fclose( ( *hSplitBinLCLDDec )->cldfbOut );
} }
#endif #endif
ivas_splitBinRendPLCClose( &( *hSplitBinLCLDDec )->hSplitRendPLC ); isar_splitBinRendPLCClose( &( *hSplitBinLCLDDec )->hSplitRendPLC );
free( *hSplitBinLCLDDec ); free( *hSplitBinLCLDDec );
*hSplitBinLCLDDec = NULL; *hSplitBinLCLDDec = NULL;
...@@ -163,21 +163,21 @@ void ivas_splitBinLCLDDecClose( ...@@ -163,21 +163,21 @@ void ivas_splitBinLCLDDecClose(
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* Function ivas_splitBinLCLDDecProcess() * Function isar_splitBinLCLDDecProcess()
* *
* *
*------------------------------------------------------------------------*/ *------------------------------------------------------------------------*/
void ivas_splitBinLCLDDecProcess( void isar_splitBinLCLDDecProcess(
BIN_HR_SPLIT_LCLD_DEC_HANDLE hSplitBinLCLDDec, ISAR_BIN_HR_SPLIT_LCLD_DEC_HANDLE hSplitBinLCLDDec,
IVAS_SPLIT_REND_BITS_HANDLE pBits, ISAR_SPLIT_REND_BITS_HANDLE pBits,
float Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
float Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
const int16_t bfi ) const int16_t bfi )
{ {
int16_t k, n; int16_t k, n;
int16_t itr; int16_t itr;
push_wmops( "ivas_splitBinLCLDDecProcess" ); push_wmops( "isar_splitBinLCLDDecProcess" );
assert( hSplitBinLCLDDec != NULL ); assert( hSplitBinLCLDDec != NULL );
assert( Cldfb_Out_Real != NULL ); assert( Cldfb_Out_Real != NULL );
...@@ -224,21 +224,32 @@ void ivas_splitBinLCLDDecProcess( ...@@ -224,21 +224,32 @@ void ivas_splitBinLCLDDecProcess(
} }
} }
#endif #endif
if ( hSplitBinLCLDDec->hSplitRendPLC->prev_bfi != 0 ) if ( AnyDecodingFailed( hSplitBinLCLDDec->psLCLDDecoder ) )
{
/* continue concealing */
isar_splitBinRendPLC( hSplitBinLCLDDec->hSplitRendPLC, Cldfb_Out_Real, Cldfb_Out_Imag, (int16_t) hSplitBinLCLDDec->iChannels, hSplitBinLCLDDec->iNumBlocks,
hSplitBinLCLDDec->iNumIterations, GetDecodingFailedStatus( hSplitBinLCLDDec->psLCLDDecoder ) );
}
if ( AnyDecodingFailedPrev( hSplitBinLCLDDec->psLCLDDecoder ) )
{ {
/* cross-fade recovered frame into good frame */ /* cross-fade recovered frame into good frame */
ivas_splitBinRendPLC_xf( hSplitBinLCLDDec->hSplitRendPLC, Cldfb_Out_Real, Cldfb_Out_Imag, (int16_t) hSplitBinLCLDDec->iChannels, hSplitBinLCLDDec->iNumBlocks, hSplitBinLCLDDec->iNumIterations ); isar_splitBinRendPLC_xf( hSplitBinLCLDDec->hSplitRendPLC, Cldfb_Out_Real, Cldfb_Out_Imag, (int16_t) hSplitBinLCLDDec->iChannels, hSplitBinLCLDDec->iNumBlocks,
hSplitBinLCLDDec->iNumIterations, GetDecodingFailedStatus( hSplitBinLCLDDec->psLCLDDecoder ), GetDecodingFailedPrevStatus( hSplitBinLCLDDec->psLCLDDecoder ) );
} }
} }
} }
else else
{ {
/* set states in decoder */
SetDecodingUnresolved( hSplitBinLCLDDec->psLCLDDecoder );
/* do PLC for lost split renderer frame */ /* do PLC for lost split renderer frame */
ivas_splitBinRendPLC( hSplitBinLCLDDec->hSplitRendPLC, Cldfb_Out_Real, Cldfb_Out_Imag, (int16_t) hSplitBinLCLDDec->iChannels, hSplitBinLCLDDec->iNumBlocks, hSplitBinLCLDDec->iNumIterations ); isar_splitBinRendPLC( hSplitBinLCLDDec->hSplitRendPLC, Cldfb_Out_Real, Cldfb_Out_Imag, (int16_t) hSplitBinLCLDDec->iChannels, hSplitBinLCLDDec->iNumBlocks,
hSplitBinLCLDDec->iNumIterations, GetDecodingFailedStatus( hSplitBinLCLDDec->psLCLDDecoder ) );
} }
/* save PLC state */ /* save PLC state */
ivas_splitBinRendPLCsaveState( hSplitBinLCLDDec->hSplitRendPLC, Cldfb_Out_Real, Cldfb_Out_Imag, (int16_t) hSplitBinLCLDDec->iChannels, hSplitBinLCLDDec->iNumBlocks, hSplitBinLCLDDec->iNumIterations ); isar_splitBinRendPLCsaveState( hSplitBinLCLDDec->hSplitRendPLC, Cldfb_Out_Real, Cldfb_Out_Imag, (int16_t) hSplitBinLCLDDec->iChannels, hSplitBinLCLDDec->iNumBlocks, hSplitBinLCLDDec->iNumIterations );
pop_wmops(); pop_wmops();
......