bug fix for a crash in the jitter buffer, patch from pljones

This commit is contained in:
Volker Fischer 2011-06-28 19:07:24 +00:00
parent 911692c5fa
commit 08c16748a8
4 changed files with 510 additions and 498 deletions

View file

@ -163,14 +163,14 @@ DISTFILES += AUTHORS \
NEWS \ NEWS \
README \ README \
TODO \ TODO \
libs\celt\AUTHORS \ libs/celt/AUTHORS \
libs\celt\ChangeLog \ libs/celt/ChangeLog \
libs\celt\COPYING \ libs/celt/COPYING \
libs\celt\INSTALL \ libs/celt/INSTALL \
libs\celt\NEWS \ libs/celt/NEWS \
libs\celt\README \ libs/celt/README \
libs\celt\README_LLCON \ libs/celt/README_LLCON \
libs\celt\TODO \ libs/celt/TODO \
src/res/CLEDBlack.png \ src/res/CLEDBlack.png \
src/res/CLEDBlackSmall.png \ src/res/CLEDBlackSmall.png \
src/res/CLEDDisabledSmall.png \ src/res/CLEDDisabledSmall.png \

View file

@ -206,10 +206,9 @@ bool CNetBufWithStats::Get ( CVector<uint8_t>& vecbyData )
const double dInitState = const double dInitState =
ErrorRateStatistic[NUM_STAT_SIMULATION_BUFFERS - 1].InitializationState(); ErrorRateStatistic[NUM_STAT_SIMULATION_BUFFERS - 1].InitializationState();
if ( dInitState < 0.2 ) if ( dInitState < 0.1 )
{ {
if ( ( dInitState > 0.1 ) && if ( ErrorRateStatistic[NUM_STAT_SIMULATION_BUFFERS - 1].GetAverage() > ERROR_RATE_BOUND )
( ErrorRateStatistic[NUM_STAT_SIMULATION_BUFFERS - 1].GetAverage() > ERROR_RATE_BOUND ) )
{ {
for ( int i = 0; i < NUM_STAT_SIMULATION_BUFFERS; i++ ) for ( int i = 0; i < NUM_STAT_SIMULATION_BUFFERS; i++ )
{ {

View file

@ -1,483 +1,485 @@
/******************************************************************************\ /******************************************************************************\
* Copyright (c) 2004-2011 * Copyright (c) 2004-2011
* *
* Author(s): * Author(s):
* Volker Fischer * Volker Fischer
* *
****************************************************************************** ******************************************************************************
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software * the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later * Foundation; either version 2 of the License, or (at your option) any later
* version. * version.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT * This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details. * details.
* *
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., * this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* *
\******************************************************************************/ \******************************************************************************/
#if !defined ( BUFFER_H__3B123453_4344_BB23945IUHF1912__INCLUDED_ ) #if !defined ( BUFFER_H__3B123453_4344_BB23945IUHF1912__INCLUDED_ )
#define BUFFER_H__3B123453_4344_BB23945IUHF1912__INCLUDED_ #define BUFFER_H__3B123453_4344_BB23945IUHF1912__INCLUDED_
#include "util.h" #include "util.h"
#include "global.h" #include "global.h"
/* Definitions ****************************************************************/ /* Definitions ****************************************************************/
// each regular buffer access lead to a count for put and get, assuming 2.66 ms // each regular buffer access lead to a count for put and get, assuming 2.66 ms
// blocks we have 15 s / 2.66 ms * 2 = approx. 11000 // blocks we have 15 s / 2.66 ms * 2 = approx. 11000
#define MAX_STATISTIC_COUNT 11000 #define MAX_STATISTIC_COUNT 11000
// definition of the error bound // definition of the error bound
#define ERROR_RATE_BOUND 0.002 #define ERROR_RATE_BOUND 0.002
// number of simulation network jitter buffers for evaluating the statistic // number of simulation network jitter buffers for evaluating the statistic
#define NUM_STAT_SIMULATION_BUFFERS 13 #define NUM_STAT_SIMULATION_BUFFERS 13
/* Classes ********************************************************************/ /* Classes ********************************************************************/
// Buffer base class ----------------------------------------------------------- // Buffer base class -----------------------------------------------------------
template<class TData> class CBufferBase template<class TData> class CBufferBase
{ {
public: public:
CBufferBase ( const bool bNIsSim = false ) : CBufferBase ( const bool bNIsSim = false ) :
bIsSimulation ( bNIsSim ), bIsInitialized ( false ) {} bIsSimulation ( bNIsSim ), bIsInitialized ( false ) {}
void SetIsSimulation ( const bool bNIsSim ) { bIsSimulation = bNIsSim; } void SetIsSimulation ( const bool bNIsSim ) { bIsSimulation = bNIsSim; }
virtual void Init ( const int iNewMemSize, virtual void Init ( const int iNewMemSize,
const bool bPreserve = false ) const bool bPreserve = false )
{ {
// in simulation mode the size is not changed during operation -> we do // in simulation mode the size is not changed during operation -> we do
// not have to implement special code for this case // not have to implement special code for this case
// only enter the "preserve" branch, if object was already initialized // only enter the "preserve" branch, if object was already initialized
if ( bPreserve && ( !bIsSimulation ) && bIsInitialized ) if ( bPreserve && ( !bIsSimulation ) && bIsInitialized )
{ {
// copy old data in new vector using get pointer as zero per // copy old data in new vector using get pointer as zero per
// definition // definition
int iCurPos; int iCurPos;
// copy current data in temporary vector // copy current data in temporary vector
CVector<TData> vecTempMemory ( vecMemory ); CVector<TData> vecTempMemory ( vecMemory );
// resize actual buffer memory // resize actual buffer memory
vecMemory.Init ( iNewMemSize ); vecMemory.Init ( iNewMemSize );
// get maximum number of data to be copied // get maximum number of data to be copied
int iCopyLen = GetAvailData(); int iCopyLen = GetAvailData();
if ( iCopyLen > iNewMemSize ) if ( iCopyLen > iNewMemSize )
{ {
iCopyLen = iNewMemSize; iCopyLen = iNewMemSize;
} }
// set correct buffer state // set correct buffer state
if ( iCopyLen >= iNewMemSize ) if ( iCopyLen == iNewMemSize )
{ {
eBufState = CBufferBase<TData>::BS_FULL; eBufState = CBufferBase<TData>::BS_FULL;
} }
else else
{ {
if ( iCopyLen == 0 ) if ( iCopyLen == 0 )
{ {
eBufState = CBufferBase<TData>::BS_EMPTY; eBufState = CBufferBase<TData>::BS_EMPTY;
} }
else else
{ {
eBufState = CBufferBase<TData>::BS_OK; eBufState = CBufferBase<TData>::BS_OK;
} }
} }
if ( iGetPos < iPutPos ) if ( iGetPos < iPutPos )
{ {
// "get" position is before "put" position -> no wrap around // "get" position is before "put" position -> no wrap around
for ( iCurPos = 0; iCurPos < iCopyLen; iCurPos++ ) for ( iCurPos = 0; iCurPos < iCopyLen; iCurPos++ )
{ {
vecMemory[iCurPos] = vecTempMemory[iGetPos + iCurPos]; vecMemory[iCurPos] = vecTempMemory[iGetPos + iCurPos];
} }
}
// update put pointer else
if ( eBufState == CBufferBase<TData>::BS_FULL ) {
{ // "put" position is before "get" position -> wrap around
iPutPos = 0; bool bEnoughSpaceForSecondPart = true;
} int iFirstPartLen = iMemSize - iGetPos;
else
{ // check that first copy length is not larger then new memory
iPutPos -= iGetPos; if ( iFirstPartLen >= iCopyLen )
} {
} iFirstPartLen = iCopyLen;
else bEnoughSpaceForSecondPart = false;
{ }
// "put" position is before "get" position -> wrap around
bool bEnoughSpaceForSecondPart = true; for ( iCurPos = 0; iCurPos < iFirstPartLen; iCurPos++ )
int iFirstPartLen = iMemSize - iGetPos; {
vecMemory[iCurPos] = vecTempMemory[iGetPos + iCurPos];
// check that first copy length is not larger then new memory }
if ( iFirstPartLen > iCopyLen )
{ if ( bEnoughSpaceForSecondPart )
iFirstPartLen = iCopyLen; {
bEnoughSpaceForSecondPart = false; // calculate remaining copy length
} const int iRemainingCopyLen = iCopyLen - iFirstPartLen;
for ( iCurPos = 0; iCurPos < iFirstPartLen; iCurPos++ ) // perform copying of second part
{ for ( iCurPos = 0; iCurPos < iRemainingCopyLen; iCurPos++ )
vecMemory[iCurPos] = vecTempMemory[iGetPos + iCurPos]; {
} vecMemory[iCurPos + iFirstPartLen] =
vecTempMemory[iCurPos];
if ( bEnoughSpaceForSecondPart ) }
{ }
// calculate remaining copy length }
const int iRemainingCopyLen = iCopyLen - iFirstPartLen;
// update put pointer
// perform copying of second part if ( eBufState == CBufferBase<TData>::BS_FULL )
for ( iCurPos = 0; iCurPos < iRemainingCopyLen; iCurPos++ ) {
{ iPutPos = 0;
vecMemory[iCurPos + iFirstPartLen] = }
vecTempMemory[iCurPos]; else
} {
} iPutPos = iCopyLen;
}
// update put pointer
if ( eBufState == CBufferBase<TData>::BS_FULL ) // update get position -> zero per definition
{ iGetPos = 0;
iPutPos = 0; }
} else
else {
{ // allocate memory for actual data buffer
iPutPos += iFirstPartLen; if ( !bIsSimulation )
} {
} vecMemory.Init ( iNewMemSize );
}
// update get position -> zero per definition
iGetPos = 0; // init buffer pointers and buffer state (empty buffer)
} iGetPos = 0;
else iPutPos = 0;
{ eBufState = CBufferBase<TData>::BS_EMPTY;
// allocate memory for actual data buffer }
if ( !bIsSimulation )
{ // store total memory size value
vecMemory.Init ( iNewMemSize ); iMemSize = iNewMemSize;
}
// set initialized flag
// init buffer pointers and buffer state (empty buffer) bIsInitialized = true;
iGetPos = 0; }
iPutPos = 0;
eBufState = CBufferBase<TData>::BS_EMPTY; virtual bool Put ( const CVector<TData>& vecData,
} const int iInSize )
{
// store total memory size value if ( bIsSimulation )
iMemSize = iNewMemSize; {
// in this simulation only the buffer pointers and the buffer state
// set initialized flag // is updated, no actual data is transferred
bIsInitialized = true; iPutPos += iInSize;
} if ( iPutPos >= iMemSize )
{
virtual bool Put ( const CVector<TData>& vecData, iPutPos -= iMemSize;
const int iInSize ) }
{ }
if ( bIsSimulation ) else
{ {
// in this simulation only the buffer pointers and the buffer state // copy new data in internal buffer
// is updated, no actual data is transferred int iCurPos = 0;
iPutPos += iInSize; if ( iPutPos + iInSize > iMemSize )
if ( iPutPos >= iMemSize ) {
{ // remaining space size for second block
iPutPos -= iMemSize; const int iRemSpace = iPutPos + iInSize - iMemSize;
}
} // data must be written in two steps because of wrap around
else while ( iPutPos < iMemSize )
{ {
// copy new data in internal buffer vecMemory[iPutPos++] = vecData[iCurPos++];
int iCurPos = 0; }
if ( iPutPos + iInSize > iMemSize )
{ for ( iPutPos = 0; iPutPos < iRemSpace; iPutPos++ )
// remaining space size for second block {
const int iRemSpace = iPutPos + iInSize - iMemSize; vecMemory[iPutPos] = vecData[iCurPos++];
}
// data must be written in two steps because of wrap around }
while ( iPutPos < iMemSize ) else
{ {
vecMemory[iPutPos++] = vecData[iCurPos++]; // data can be written in one step
} const int iEnd = iPutPos + iInSize;
while ( iPutPos < iEnd )
for ( iPutPos = 0; iPutPos < iRemSpace; iPutPos++ ) {
{ vecMemory[iPutPos++] = vecData[iCurPos++];
vecMemory[iPutPos] = vecData[iCurPos++]; }
} }
} }
else
{ // take care about wrap around of put pointer
// data can be written in one step if ( iPutPos == iMemSize )
const int iEnd = iPutPos + iInSize; {
while ( iPutPos < iEnd ) iPutPos = 0;
{ }
vecMemory[iPutPos++] = vecData[iCurPos++];
} // set buffer state flag
} if ( iPutPos == iGetPos )
} {
eBufState = CBufferBase<TData>::BS_FULL;
// set buffer state flag }
if ( iPutPos == iGetPos ) else
{ {
eBufState = CBufferBase<TData>::BS_FULL; eBufState = CBufferBase<TData>::BS_OK;
} }
else
{ return true; // no error check in base class, alyways return ok
eBufState = CBufferBase<TData>::BS_OK; }
}
virtual bool Get ( CVector<TData>& vecData )
return true; // no error check in base class, alyways return ok {
} // get size of data to be get from the buffer
const int iInSize = vecData.Size();
virtual bool Get ( CVector<TData>& vecData )
{ if ( bIsSimulation )
// get size of data to be get from the buffer {
const int iInSize = vecData.Size(); // in this simulation only the buffer pointers and the buffer state
// is updated, no actual data is transferred
if ( bIsSimulation ) iGetPos += iInSize;
{ if ( iGetPos >= iMemSize )
// in this simulation only the buffer pointers and the buffer state {
// is updated, no actual data is transferred iGetPos -= iMemSize;
iGetPos += iInSize; }
if ( iGetPos >= iMemSize ) }
{ else
iGetPos -= iMemSize; {
} // copy data from internal buffer in output buffer
} int iCurPos = 0;
else if ( iGetPos + iInSize > iMemSize )
{ {
// copy data from internal buffer in output buffer // remaining data size for second block
int iCurPos = 0; const int iRemData = iGetPos + iInSize - iMemSize;
if ( iGetPos + iInSize > iMemSize )
{ // data must be read in two steps because of wrap around
// remaining data size for second block while ( iGetPos < iMemSize )
const int iRemData = iGetPos + iInSize - iMemSize; {
vecData[iCurPos++] = vecMemory[iGetPos++];
// data must be read in two steps because of wrap around }
while ( iGetPos < iMemSize )
{ for ( iGetPos = 0; iGetPos < iRemData; iGetPos++ )
vecData[iCurPos++] = vecMemory[iGetPos++]; {
} vecData[iCurPos++] = vecMemory[iGetPos];
}
for ( iGetPos = 0; iGetPos < iRemData; iGetPos++ ) }
{ else
vecData[iCurPos++] = vecMemory[iGetPos]; {
} // data can be read in one step
} const int iEnd = iGetPos + iInSize;
else while ( iGetPos < iEnd )
{ {
// data can be read in one step vecData[iCurPos++] = vecMemory[iGetPos++];
const int iEnd = iGetPos + iInSize; }
while ( iGetPos < iEnd ) }
{ }
vecData[iCurPos++] = vecMemory[iGetPos++];
} // take care about wrap around of get pointer
} if ( iGetPos == iMemSize )
} {
iGetPos = 0;
// set buffer state flag }
if ( iPutPos == iGetPos )
{ // set buffer state flag
eBufState = CBufferBase<TData>::BS_EMPTY; if ( iPutPos == iGetPos )
} {
else eBufState = CBufferBase<TData>::BS_EMPTY;
{ }
eBufState = CBufferBase<TData>::BS_OK; else
} {
eBufState = CBufferBase<TData>::BS_OK;
return true; // no error check in base class, alyways return ok }
}
return true; // no error check in base class, alyways return ok
virtual int GetAvailSpace() const }
{
// calculate available space in buffer virtual int GetAvailSpace() const
int iAvSpace = iGetPos - iPutPos; {
// calculate available space in buffer
// check for special case and wrap around int iAvSpace = iGetPos - iPutPos;
if ( iAvSpace < 0 )
{ // check for special case and wrap around
iAvSpace += iMemSize; // wrap around if ( iAvSpace < 0 )
} {
else iAvSpace += iMemSize; // wrap around
{ }
if ( ( iAvSpace == 0 ) && ( eBufState == BS_EMPTY ) ) else
{ {
iAvSpace = iMemSize; if ( ( iAvSpace == 0 ) && ( eBufState == BS_EMPTY ) )
} {
} iAvSpace = iMemSize;
}
return iAvSpace; }
}
return iAvSpace;
virtual int GetAvailData() const }
{
// calculate available data in buffer virtual int GetAvailData() const
int iAvData = iPutPos - iGetPos; {
// calculate available data in buffer
// check for special case and wrap around int iAvData = iPutPos - iGetPos;
if ( iAvData < 0 )
{ // check for special case and wrap around
iAvData += iMemSize; // wrap around if ( iAvData < 0 )
} {
else iAvData += iMemSize; // wrap around
{ }
if ( ( iAvData == 0 ) && ( eBufState == BS_FULL ) ) else
{ {
iAvData = iMemSize; if ( ( iAvData == 0 ) && ( eBufState == BS_FULL ) )
} {
} iAvData = iMemSize;
}
return iAvData; }
}
return iAvData;
protected: }
enum EBufState { BS_OK, BS_FULL, BS_EMPTY };
protected:
virtual void Clear() enum EBufState { BS_OK, BS_FULL, BS_EMPTY };
{
// clear memory virtual void Clear()
if ( !bIsSimulation ) {
{ // clear memory
vecMemory.Reset ( 0 ); if ( !bIsSimulation )
} {
vecMemory.Reset ( 0 );
// init buffer pointers and buffer state (empty buffer) }
iGetPos = 0;
iPutPos = 0; // init buffer pointers and buffer state (empty buffer)
eBufState = CBufferBase<TData>::BS_EMPTY; iGetPos = 0;
} iPutPos = 0;
eBufState = CBufferBase<TData>::BS_EMPTY;
CVector<TData> vecMemory; }
int iMemSize;
int iGetPos; CVector<TData> vecMemory;
int iPutPos; int iMemSize;
EBufState eBufState; int iGetPos;
bool bIsSimulation; int iPutPos;
bool bIsInitialized; EBufState eBufState;
}; bool bIsSimulation;
bool bIsInitialized;
};
// Network buffer (jitter buffer) ----------------------------------------------
class CNetBuf : public CBufferBase<uint8_t>
{ // Network buffer (jitter buffer) ----------------------------------------------
public: class CNetBuf : public CBufferBase<uint8_t>
CNetBuf ( const bool bNewIsSim = false ) : {
CBufferBase<uint8_t> ( bNewIsSim ) {} public:
CNetBuf ( const bool bNewIsSim = false ) :
virtual void Init ( const int iNewBlockSize, CBufferBase<uint8_t> ( bNewIsSim ) {}
const int iNewNumBlocks,
const bool bPreserve = false ); virtual void Init ( const int iNewBlockSize,
const int iNewNumBlocks,
int GetSize() { return iMemSize / iBlockSize; } const bool bPreserve = false );
virtual bool Put ( const CVector<uint8_t>& vecbyData, const int iInSize ); int GetSize() { return iMemSize / iBlockSize; }
virtual bool Get ( CVector<uint8_t>& vecbyData );
virtual bool Put ( const CVector<uint8_t>& vecbyData, const int iInSize );
protected: virtual bool Get ( CVector<uint8_t>& vecbyData );
int iBlockSize;
int iNumInvalidElements; protected:
}; int iBlockSize;
int iNumInvalidElements;
};
// Network buffer (jitter buffer) with statistic calculations ------------------
class CNetBufWithStats : public CNetBuf
{ // Network buffer (jitter buffer) with statistic calculations ------------------
public: class CNetBufWithStats : public CNetBuf
CNetBufWithStats(); {
public:
virtual void Init ( const int iNewBlockSize, CNetBufWithStats();
const int iNewNumBlocks,
const bool bPreserve = false ); virtual void Init ( const int iNewBlockSize,
const int iNewNumBlocks,
virtual bool Put ( const CVector<uint8_t>& vecbyData, const int iInSize ); const bool bPreserve = false );
virtual bool Get ( CVector<uint8_t>& vecbyData );
virtual bool Put ( const CVector<uint8_t>& vecbyData, const int iInSize );
int GetAutoSetting() { return iCurAutoBufferSizeSetting; } virtual bool Get ( CVector<uint8_t>& vecbyData );
// TEST int GetAutoSetting() { return iCurAutoBufferSizeSetting; }
void StoreAllSimAverages();
// TEST
protected: void StoreAllSimAverages();
void UpdateAutoSetting();
protected:
// statistic (do not use the vector class since the classes do not have void UpdateAutoSetting();
// appropriate copy constructor/operator)
CErrorRate ErrorRateStatistic[NUM_STAT_SIMULATION_BUFFERS]; // statistic (do not use the vector class since the classes do not have
CNetBuf SimulationBuffer[NUM_STAT_SIMULATION_BUFFERS]; // appropriate copy constructor/operator)
int viBufSizesForSim[NUM_STAT_SIMULATION_BUFFERS]; CErrorRate ErrorRateStatistic[NUM_STAT_SIMULATION_BUFFERS];
CNetBuf SimulationBuffer[NUM_STAT_SIMULATION_BUFFERS];
double dCurIIRFilterResult; int viBufSizesForSim[NUM_STAT_SIMULATION_BUFFERS];
int iCurDecidedResult;
int iInitCounter; double dCurIIRFilterResult;
int iCurAutoBufferSizeSetting; int iCurDecidedResult;
}; int iInitCounter;
int iCurAutoBufferSizeSetting;
};
// Conversion buffer (very simple buffer) --------------------------------------
// For this very simple buffer no wrap around mechanism is implemented. We
// assume here, that the applied buffers are an integer fraction of the total // Conversion buffer (very simple buffer) --------------------------------------
// buffer size. // For this very simple buffer no wrap around mechanism is implemented. We
template<class TData> class CConvBuf // assume here, that the applied buffers are an integer fraction of the total
{ // buffer size.
public: template<class TData> class CConvBuf
CConvBuf() { Init ( 0 ); } {
public:
void Init ( const int iNewMemSize ) CConvBuf() { Init ( 0 ); }
{
// set memory size void Init ( const int iNewMemSize )
iMemSize = iNewMemSize; {
// set memory size
// allocate and clear memory for actual data buffer iMemSize = iNewMemSize;
vecsMemory.Init ( iMemSize );
// allocate and clear memory for actual data buffer
iPutPos = 0; vecsMemory.Init ( iMemSize );
}
iPutPos = 0;
int GetSize() const { return iMemSize; } }
bool Put ( const CVector<TData>& vecsData ) int GetSize() const { return iMemSize; }
{
const int iVecSize = vecsData.Size(); bool Put ( const CVector<TData>& vecsData )
{
// copy new data in internal buffer const int iVecSize = vecsData.Size();
int iCurPos = 0;
const int iEnd = iPutPos + iVecSize; // copy new data in internal buffer
int iCurPos = 0;
// first check for buffer overrun const int iEnd = iPutPos + iVecSize;
if ( iEnd <= iMemSize )
{ // first check for buffer overrun
// actual copy operation if ( iEnd <= iMemSize )
while ( iPutPos < iEnd ) {
{ // actual copy operation
vecsMemory[iPutPos++] = vecsData[iCurPos++]; while ( iPutPos < iEnd )
} {
vecsMemory[iPutPos++] = vecsData[iCurPos++];
// return "buffer is ready for readout" flag }
return ( iEnd == iMemSize );
} // return "buffer is ready for readout" flag
else return ( iEnd == iMemSize );
{ }
// buffer overrun or not initialized, return "not ready" else
return false; {
} // buffer overrun or not initialized, return "not ready"
} return false;
}
CVector<TData> Get() }
{
iPutPos = 0; CVector<TData> Get()
return vecsMemory; {
} iPutPos = 0;
return vecsMemory;
protected: }
CVector<TData> vecsMemory;
int iMemSize; protected:
int iPutPos; CVector<TData> vecsMemory;
}; int iMemSize;
int iPutPos;
#endif /* !defined ( BUFFER_H__3B123453_4344_BB23945IUHF1912__INCLUDED_ ) */ };
#endif /* !defined ( BUFFER_H__3B123453_4344_BB23945IUHF1912__INCLUDED_ ) */

View file

@ -155,8 +155,8 @@ public:
} }
protected: protected:
typename std::vector<TData>::iterator pData; typename std::vector<TData>::iterator pData;
int iVectorSize; int iVectorSize;
}; };
@ -172,7 +172,7 @@ template<class TData> void CVector<TData>::Init ( const int iNewSize )
pData = this->begin(); pData = this->begin();
} }
template<class TData> void CVector<TData>::Init ( const int iNewSize, template<class TData> void CVector<TData>::Init ( const int iNewSize,
const TData tIniVal ) const TData tIniVal )
{ {
// call actual init routine // call actual init routine
@ -271,6 +271,7 @@ public:
inline double GetAverage() inline double GetAverage()
{ {
// make sure we do not divide by zero
if ( this->iNorm == 0 ) if ( this->iNorm == 0 )
{ {
return dNoDataResult; return dNoDataResult;
@ -282,7 +283,17 @@ public:
} }
double InitializationState() const double InitializationState() const
{ return static_cast<double> ( this->iNorm ) / this->iVectorSize; } {
// make sure we do not divide by zero
if ( this->iVectorSize != 0 )
{
return static_cast<double> ( this->iNorm ) / this->iVectorSize;
}
else
{
return 0;
}
}
protected: protected:
int iCurIdx; int iCurIdx;