insert invalid elements when buffer underrun to improve PLC, some code clean up

This commit is contained in:
Volker Fischer 2011-06-12 06:15:32 +00:00
parent 130901ef39
commit 29f6684aba

View file

@ -37,12 +37,13 @@ void CNetBuf::Init ( const int iNewBlockSize,
iBlockSize = iNewBlockSize;
// total size -> size of one block times the number of blocks
CBufferBase<uint8_t>::Init ( iNewBlockSize * iNewNumBlocks, bPreserve );
CBufferBase<uint8_t>::Init ( iNewBlockSize * iNewNumBlocks,
bPreserve );
// use the "get" flag to make sure the buffer is cleared
// clear buffer if not preserved
if ( !bPreserve )
{
Clear ( CT_GET );
Clear();
}
}
@ -51,47 +52,10 @@ bool CNetBuf::Put ( const CVector<uint8_t>& vecbyData,
{
bool bPutOK = true;
// Check if there is not enough space available -> correct
// check if there is not enough space available
if ( GetAvailSpace() < iInSize )
{
/*
// not enough space in buffer for put operation, correct buffer to
// prepare for new data
Clear ( CT_PUT );
bPutOK = false; // return error flag
*/
/*
// TEST invalidate last written block for better PLC
// ATTENTION: We assume that mem size is factor of block size here!!!!
if ( !bIsSimulation )
{
if ( iPutPos == 0 )
{
for ( int iPos = iMemSize - iInSize; iPos < iMemSize; iPos++ )
{
vecMemory[iPos] = 0;
}
}
else
{
for ( int iPos = iPutPos - iInSize; iPos < iPutPos; iPos++ )
{
vecMemory[iPos] = 0;
}
}
}
*/
return false;
// check for special case: buffer memory is not sufficient
if ( iInSize > iMemSize )
{
// do nothing here, just return error code
return bPutOK;
}
}
// copy new data in internal buffer (implemented in base class)
@ -112,195 +76,38 @@ bool CNetBuf::Get ( CVector<uint8_t>& vecbyData )
{
return false;
}
/*
// check for invalid data in buffer
if ( iNumInvalidElements > 0 )
{
// decrease number of invalid elements by the queried number (input
// size)
iNumInvalidElements -= iInSize;
// decrease number of invalid elements by one
iNumInvalidElements -= 1;
bGetOK = false; // return error flag
// return error flag, do not return function here since we have
// to call the base Get function to pick one block out of the
// buffer
bGetOK = false;
}
*/
// Check if there is not enough data available -> correct
// check if there is not enough data available -> correct
if ( GetAvailData() < iInSize )
{
/*
// not enough data in buffer for get operation, correct buffer to
// prepare for getting data
Clear ( CT_GET );
// in case we have a buffer underrun, invalidate the next 15 blocks
// to avoid the unmusical noise resulting from a very short drop
// out (note that if you want to change this value, also change
// the value in celt_decode_lost in celt.c)
iNumInvalidElements = 15;
bGetOK = false; // return error flag
*/
return false;
// check for special case: buffer memory is not sufficient
if ( iInSize > iMemSize )
{
// do nothing here, just return error code
return bGetOK;
}
}
// copy data from internal buffer in output buffer (implemented in base
// class)
CBufferBase<uint8_t>::Get ( vecbyData );
/*
// TEST check for all zero packet
bool bAllZeroPacket = true;
for ( int iPos = 0; iPos < iInSize; iPos++ )
{
if ( vecbyData[iPos] != 0 )
{
bAllZeroPacket = false;
}
}
if ( bAllZeroPacket )
{
return false;
}
*/
return bGetOK;
}
void CNetBuf::Clear ( const EClearType eClearType )
{
// TEST
CBufferBase<uint8_t>::Clear ( eClearType );
/*
// Define the number of blocks bound for the "random offset" (1) algorithm.
// If we are above the bound, we use the "middle of buffer" (2) algorithm.
//
// Test results (with different jitter buffer sizes), given is the error
// probability of jitter buffer (probability of corrections in the buffer):
// kX, 128 samples, WLAN:
// 2: (1) 5 %, (2) 12.3 %
// 3: (1) 18.3 %, (2) 17.1 %
// 5: (1) 0.9 %, (2) 0.8 %
// kX, 128 samples, localhost:
// 2: (1) 2.5 %, (2) 13 %
// 3: (1) 0.9 %, (2) 1.1 %
// 5: (1) 0.7 %, (2) 0.6 %
// Behringer, 128 samples, WLAN:
// 2: (1) 5.8 %, (2) 9.4 %
// 3: (1) 0.9 %, (2) 0.8 %
// 5: (1) 0.4 %, (2) 0.3 %
// Behringer, 128 samples, localhost:
// 2: (1) 1 %, (2) 9.8 %
// 3: (1) 0.57 %, (2) 0.6 %
// 5: (1) 0.6 %, (2) 0.56 %
// kX, 256 samples, WLAN:
// 3: (1) 24.2 %, (2) 18.4 %
// 4: (1) 1.5 %, (2) 2.5 %
// 5: (1) 1 %, (2) 1 %
// ASIO4All, 256 samples, WLAN:
// 3: (1) 14.9 %, (2) 11.9 %
// 4: (1) 1.5 %, (2) 7 %
// 5: (1) 1.2 %, (2) 1.3 %
const int iNumBlocksBoundInclForRandom = 4; // by extensive testing: 4
int iNewFillLevel = 0;
if ( iBlockSize != 0 )
{
const int iNumBlocks = iMemSize / iBlockSize;
if ( iNumBlocks <= iNumBlocksBoundInclForRandom ) // just for small buffers
{
// Random position algorithm.
// overwrite fill level with random value, the range
// is 0 to (iMemSize - iBlockSize)
iNewFillLevel = static_cast<int> ( static_cast<double> ( rand() ) *
iNumBlocks / RAND_MAX ) * iBlockSize;
}
else
{
// Middle of buffer algorithm.
// with the following operation we set the fill level to a block
// boundary (one block below the middle of the buffer in case of odd
// number of blocks, e.g.:
// [buffer size]: [get pos]
// 1: 0 / 2: 0 / 3: 1 / 4: 1 / 5: 2 ...)
iNewFillLevel =
( ( ( iMemSize - iBlockSize) / 2 ) / iBlockSize ) * iBlockSize;
// TEST
iNewFillLevel += static_cast<int> ( static_cast<double> ( rand() ) *
iNumBlocksBoundInclForRandom / RAND_MAX ) * iBlockSize -
iNumBlocksBoundInclForRandom / 2 * iBlockSize;
}
}
// different behaviour for get and put corrections
if ( eClearType == CT_GET )
{
// clear buffer since we had a buffer underrun
if ( !bIsSimulation )
{
vecMemory.Reset ( 0 );
}
// reset buffer pointers so that they are at maximum distance after
// the get operation (assign new fill level value to the get pointer)
iPutPos = 0;
iGetPos = iNewFillLevel;
// The buffer was cleared, the next time blocks are read from the
// buffer, these are invalid ones. Calculate the number of invalid
// elements
iNumInvalidElements = iMemSize - iNewFillLevel;
// check for special case
if ( iPutPos == iGetPos )
{
eBufState = CNetBuf::BS_FULL;
}
else
{
eBufState = CNetBuf::BS_OK;
}
}
else
{
// in case of "put" correction, do not delete old data but only shift
// the pointers
iPutPos = iNewFillLevel;
// adjust put pointer relative to current get pointer, take care of
// wrap around
iPutPos += iGetPos;
if ( iPutPos > iMemSize )
{
iPutPos -= iMemSize;
}
// in case of put correction, no invalid blocks are inserted
iNumInvalidElements = 0;
// check for special case
if ( iPutPos == iGetPos )
{
eBufState = CNetBuf::BS_EMPTY;
}
else
{
eBufState = CNetBuf::BS_OK;
}
}
// TEST
//iNumInvalidElements = 8 * iMemSize;
*/
}
/* Network buffer with statistic calculations implementation ******************/
CNetBufWithStats::CNetBufWithStats() :