From 29f6684aba97783c5efeef750d24837845671874 Mon Sep 17 00:00:00 2001 From: Volker Fischer Date: Sun, 12 Jun 2011 06:15:32 +0000 Subject: [PATCH] insert invalid elements when buffer underrun to improve PLC, some code clean up --- src/buffer.cpp | 233 +++++-------------------------------------------- 1 file changed, 20 insertions(+), 213 deletions(-) diff --git a/src/buffer.cpp b/src/buffer.cpp index 3525137f..e81dea28 100755 --- a/src/buffer.cpp +++ b/src/buffer.cpp @@ -37,12 +37,13 @@ void CNetBuf::Init ( const int iNewBlockSize, iBlockSize = iNewBlockSize; // total size -> size of one block times the number of blocks - CBufferBase::Init ( iNewBlockSize * iNewNumBlocks, bPreserve ); + CBufferBase::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& 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; - } + return false; } // copy new data in internal buffer (implemented in base class) @@ -112,195 +76,38 @@ bool CNetBuf::Get ( CVector& 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; - } + return false; } // copy data from internal buffer in output buffer (implemented in base // class) CBufferBase::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::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 ( static_cast ( 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 ( static_cast ( 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() :