support correct auto jitter buffer settings for 64 and 128 samples frame size
This commit is contained in:
parent
16ecb72ecd
commit
32e8eb7e94
4 changed files with 76 additions and 44 deletions
|
@ -91,7 +91,13 @@ bool CNetBuf::Get ( CVector<uint8_t>& vecbyData,
|
||||||
|
|
||||||
/* Network buffer with statistic calculations implementation ******************/
|
/* Network buffer with statistic calculations implementation ******************/
|
||||||
CNetBufWithStats::CNetBufWithStats() :
|
CNetBufWithStats::CNetBufWithStats() :
|
||||||
CNetBuf ( false ) // base class init: no simulation mode
|
CNetBuf ( false ), // base class init: no simulation mode
|
||||||
|
iMaxStatisticCount ( MAX_STATISTIC_COUNT ),
|
||||||
|
bUseDoubleSystemFrameSize ( false ),
|
||||||
|
dAutoFilt_WightUpNormal ( IIR_WEIGTH_UP_NORMAL ),
|
||||||
|
dAutoFilt_WightDownNormal ( IIR_WEIGTH_DOWN_NORMAL ),
|
||||||
|
dAutoFilt_WightUpFast ( IIR_WEIGTH_UP_FAST ),
|
||||||
|
dAutoFilt_WightDownFast ( IIR_WEIGTH_DOWN_FAST )
|
||||||
{
|
{
|
||||||
// Define the sizes of the simulation buffers,
|
// Define the sizes of the simulation buffers,
|
||||||
// must be NUM_STAT_SIMULATION_BUFFERS elements!
|
// must be NUM_STAT_SIMULATION_BUFFERS elements!
|
||||||
|
@ -143,13 +149,31 @@ void CNetBufWithStats::Init ( const int iNewBlockSize,
|
||||||
// inits for statistics calculation
|
// inits for statistics calculation
|
||||||
if ( !bPreserve )
|
if ( !bPreserve )
|
||||||
{
|
{
|
||||||
|
// set the auto filter weights and max statistic count
|
||||||
|
if ( bUseDoubleSystemFrameSize )
|
||||||
|
{
|
||||||
|
dAutoFilt_WightUpNormal = IIR_WEIGTH_UP_NORMAL_DOUBLE_FRAME_SIZE;
|
||||||
|
dAutoFilt_WightDownNormal = IIR_WEIGTH_DOWN_NORMAL_DOUBLE_FRAME_SIZE;
|
||||||
|
dAutoFilt_WightUpFast = IIR_WEIGTH_UP_FAST_DOUBLE_FRAME_SIZE;
|
||||||
|
dAutoFilt_WightDownFast = IIR_WEIGTH_DOWN_FAST_DOUBLE_FRAME_SIZE;
|
||||||
|
iMaxStatisticCount = MAX_STATISTIC_COUNT_DOUBLE_FRAME_SIZE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dAutoFilt_WightUpNormal = IIR_WEIGTH_UP_NORMAL;
|
||||||
|
dAutoFilt_WightDownNormal = IIR_WEIGTH_DOWN_NORMAL;
|
||||||
|
dAutoFilt_WightUpFast = IIR_WEIGTH_UP_FAST;
|
||||||
|
dAutoFilt_WightDownFast = IIR_WEIGTH_DOWN_FAST;
|
||||||
|
iMaxStatisticCount = MAX_STATISTIC_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
for ( int i = 0; i < NUM_STAT_SIMULATION_BUFFERS; i++ )
|
for ( int i = 0; i < NUM_STAT_SIMULATION_BUFFERS; i++ )
|
||||||
{
|
{
|
||||||
// init simulation buffers with the correct size
|
// init simulation buffers with the correct size
|
||||||
SimulationBuffer[i].Init ( iNewBlockSize, viBufSizesForSim[i] );
|
SimulationBuffer[i].Init ( iNewBlockSize, viBufSizesForSim[i] );
|
||||||
|
|
||||||
// init statistics
|
// init statistics
|
||||||
ErrorRateStatistic[i].Init ( MAX_STATISTIC_COUNT, true );
|
ErrorRateStatistic[i].Init ( iMaxStatisticCount, true );
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset the initialization counter which controls the initialization
|
// reset the initialization counter which controls the initialization
|
||||||
|
@ -170,7 +194,7 @@ void CNetBufWithStats::ResetInitCounter()
|
||||||
// of the error rate statistic buffers which should be ok for a good
|
// of the error rate statistic buffers which should be ok for a good
|
||||||
// initialization value (initialization phase should be as short as
|
// initialization value (initialization phase should be as short as
|
||||||
// possible)
|
// possible)
|
||||||
iInitCounter = MAX_STATISTIC_COUNT / 4;
|
iInitCounter = iMaxStatisticCount / 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CNetBufWithStats::Put ( const CVector<uint8_t>& vecbyData,
|
bool CNetBufWithStats::Put ( const CVector<uint8_t>& vecbyData,
|
||||||
|
@ -276,8 +300,7 @@ void CNetBufWithStats::UpdateAutoSetting()
|
||||||
// the current jitter buffer size significantly.
|
// the current jitter buffer size significantly.
|
||||||
// For the initialization phase, use lower weight values to get faster
|
// For the initialization phase, use lower weight values to get faster
|
||||||
// adaptation.
|
// adaptation.
|
||||||
double dWeightUp = IIR_WEIGTH_UP_NORMAL;
|
double dWeightUp, dWeightDown;
|
||||||
double dWeightDown = IIR_WEIGTH_DOWN_NORMAL;
|
|
||||||
const double dHysteresisValue = FILTER_DECISION_HYSTERESIS;
|
const double dHysteresisValue = FILTER_DECISION_HYSTERESIS;
|
||||||
bool bUseFastAdaptation = false;
|
bool bUseFastAdaptation = false;
|
||||||
|
|
||||||
|
@ -301,9 +324,13 @@ void CNetBufWithStats::UpdateAutoSetting()
|
||||||
|
|
||||||
if ( bUseFastAdaptation )
|
if ( bUseFastAdaptation )
|
||||||
{
|
{
|
||||||
// overwrite weigth values with lower values
|
dWeightUp = dAutoFilt_WightUpFast;
|
||||||
dWeightUp = IIR_WEIGTH_UP_FAST;
|
dWeightDown = dAutoFilt_WightDownFast;
|
||||||
dWeightDown = IIR_WEIGTH_DOWN_FAST;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dWeightUp = dAutoFilt_WightUpNormal;
|
||||||
|
dWeightDown = dAutoFilt_WightDownNormal;
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply non-linear IIR filter
|
// apply non-linear IIR filter
|
||||||
|
@ -338,7 +365,7 @@ else
|
||||||
// Initialization phase check and correction -------------------------------
|
// Initialization phase check and correction -------------------------------
|
||||||
// sometimes in the very first period after a connection we get a bad error
|
// sometimes in the very first period after a connection we get a bad error
|
||||||
// rate result -> delete this from the initialization phase
|
// rate result -> delete this from the initialization phase
|
||||||
if ( iInitCounter == MAX_STATISTIC_COUNT / 8 )
|
if ( iInitCounter == iMaxStatisticCount / 8 )
|
||||||
{
|
{
|
||||||
// check error rate of the largest buffer as the indicator
|
// check error rate of the largest buffer as the indicator
|
||||||
if ( ErrorRateStatistic[NUM_STAT_SIMULATION_BUFFERS - 1].
|
if ( ErrorRateStatistic[NUM_STAT_SIMULATION_BUFFERS - 1].
|
||||||
|
|
47
src/buffer.h
47
src/buffer.h
|
@ -44,30 +44,28 @@
|
||||||
// size state
|
// size state
|
||||||
#define UP_MAX_ERROR_BOUND 0.01
|
#define UP_MAX_ERROR_BOUND 0.01
|
||||||
|
|
||||||
#if ( SYSTEM_FRAME_SIZE_SAMPLES == 64 )
|
|
||||||
// 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
|
||||||
|
#define MAX_STATISTIC_COUNT_DOUBLE_FRAME_SIZE 11000
|
||||||
|
|
||||||
|
// Note that the following definitions of the weigh constants assume a block
|
||||||
|
// size of 128 samples at a sampling rate of 48 kHz.
|
||||||
|
#define IIR_WEIGTH_UP_NORMAL_DOUBLE_FRAME_SIZE 0.999995
|
||||||
|
#define IIR_WEIGTH_DOWN_NORMAL_DOUBLE_FRAME_SIZE 0.9999
|
||||||
|
#define IIR_WEIGTH_UP_FAST_DOUBLE_FRAME_SIZE 0.9995
|
||||||
|
#define IIR_WEIGTH_DOWN_FAST_DOUBLE_FRAME_SIZE 0.999
|
||||||
|
|
||||||
|
// each regular buffer access lead to a count for put and get, assuming 1.33 ms
|
||||||
// blocks we have 15 s / 1.33 ms * 2 = approx. 22500
|
// blocks we have 15 s / 1.33 ms * 2 = approx. 22500
|
||||||
# define MAX_STATISTIC_COUNT 22500
|
#define MAX_STATISTIC_COUNT 22500
|
||||||
|
|
||||||
// convert numbers from 128 samples case using http://www.tsdconseil.fr/tutos/tuto-iir1-en.pdf
|
// convert numbers from 128 samples case using http://www.tsdconseil.fr/tutos/tuto-iir1-en.pdf
|
||||||
// and https://octave-online.net:
|
// and https://octave-online.net:
|
||||||
// gamma = exp(-Ts/tau), after some calculations we get: x=0.999995;exp(64/128*log(x))
|
// gamma = exp(-Ts/tau), after some calculations we get: x=0.999995;exp(64/128*log(x))
|
||||||
# define IIR_WEIGTH_UP_NORMAL 0.9999975
|
#define IIR_WEIGTH_UP_NORMAL 0.9999975
|
||||||
# define IIR_WEIGTH_DOWN_NORMAL 0.99994999875
|
#define IIR_WEIGTH_DOWN_NORMAL 0.99994999875
|
||||||
# define IIR_WEIGTH_UP_FAST 0.9997499687422
|
#define IIR_WEIGTH_UP_FAST 0.9997499687422
|
||||||
# define IIR_WEIGTH_DOWN_FAST 0.999499875
|
#define IIR_WEIGTH_DOWN_FAST 0.999499875
|
||||||
#else
|
|
||||||
// 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
|
|
||||||
# define MAX_STATISTIC_COUNT 11000
|
|
||||||
|
|
||||||
// Note that the following definitions of the weigh constants assume a block
|
|
||||||
// size of 128 samples at a sampling rate of 48 kHz.
|
|
||||||
# define IIR_WEIGTH_UP_NORMAL 0.999995
|
|
||||||
# define IIR_WEIGTH_DOWN_NORMAL 0.9999
|
|
||||||
# define IIR_WEIGTH_UP_FAST 0.9995
|
|
||||||
# define IIR_WEIGTH_DOWN_FAST 0.999
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Classes ********************************************************************/
|
/* Classes ********************************************************************/
|
||||||
|
@ -90,7 +88,6 @@ public:
|
||||||
{
|
{
|
||||||
// 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
|
||||||
|
@ -158,8 +155,7 @@ public:
|
||||||
// perform copying of second part
|
// perform copying of second part
|
||||||
for ( iCurPos = 0; iCurPos < iRemainingCopyLen; iCurPos++ )
|
for ( iCurPos = 0; iCurPos < iRemainingCopyLen; iCurPos++ )
|
||||||
{
|
{
|
||||||
vecMemory[iCurPos + iFirstPartLen] =
|
vecMemory[iCurPos + iFirstPartLen] = vecTempMemory[iCurPos];
|
||||||
vecTempMemory[iCurPos];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -432,6 +428,8 @@ public:
|
||||||
const int iNewNumBlocks,
|
const int iNewNumBlocks,
|
||||||
const bool bPreserve = false );
|
const bool bPreserve = false );
|
||||||
|
|
||||||
|
void SetUseDoubleSystemFrameSize ( const bool bNDSFSize ) { bUseDoubleSystemFrameSize = bNDSFSize; }
|
||||||
|
|
||||||
virtual bool Put ( const CVector<uint8_t>& vecbyData, const int iInSize );
|
virtual bool Put ( const CVector<uint8_t>& vecbyData, const int iInSize );
|
||||||
virtual bool Get ( CVector<uint8_t>& vecbyData, const int iOutSize );
|
virtual bool Get ( CVector<uint8_t>& vecbyData, const int iOutSize );
|
||||||
|
|
||||||
|
@ -454,6 +452,13 @@ protected:
|
||||||
int iCurDecidedResult;
|
int iCurDecidedResult;
|
||||||
int iInitCounter;
|
int iInitCounter;
|
||||||
int iCurAutoBufferSizeSetting;
|
int iCurAutoBufferSizeSetting;
|
||||||
|
int iMaxStatisticCount;
|
||||||
|
|
||||||
|
bool bUseDoubleSystemFrameSize;
|
||||||
|
double dAutoFilt_WightUpNormal;
|
||||||
|
double dAutoFilt_WightDownNormal;
|
||||||
|
double dAutoFilt_WightUpFast;
|
||||||
|
double dAutoFilt_WightDownFast;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -147,7 +147,6 @@ void CChannel::SetAudioStreamProperties ( const EAudComprType eNewAudComprType,
|
||||||
/*
|
/*
|
||||||
this function is intended for the client (not the server)
|
this function is intended for the client (not the server)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CNetworkTransportProps NetworkTransportProps;
|
CNetworkTransportProps NetworkTransportProps;
|
||||||
|
|
||||||
Mutex.lock();
|
Mutex.lock();
|
||||||
|
@ -161,6 +160,7 @@ void CChannel::SetAudioStreamProperties ( const EAudComprType eNewAudComprType,
|
||||||
MutexSocketBuf.lock();
|
MutexSocketBuf.lock();
|
||||||
{
|
{
|
||||||
// init socket buffer
|
// init socket buffer
|
||||||
|
SockBuf.SetUseDoubleSystemFrameSize ( eAudioCompressionType == CT_OPUS ); // NOTE must be set BEFORE the init()
|
||||||
SockBuf.Init ( iNetwFrameSize, iCurSockBufNumFrames );
|
SockBuf.Init ( iNetwFrameSize, iCurSockBufNumFrames );
|
||||||
}
|
}
|
||||||
MutexSocketBuf.unlock();
|
MutexSocketBuf.unlock();
|
||||||
|
@ -173,8 +173,7 @@ void CChannel::SetAudioStreamProperties ( const EAudComprType eNewAudComprType,
|
||||||
MutexConvBuf.unlock();
|
MutexConvBuf.unlock();
|
||||||
|
|
||||||
// fill network transport properties struct
|
// fill network transport properties struct
|
||||||
NetworkTransportProps =
|
NetworkTransportProps = GetNetworkTransportPropsFromCurrentSettings();
|
||||||
GetNetworkTransportPropsFromCurrentSettings();
|
|
||||||
}
|
}
|
||||||
Mutex.unlock();
|
Mutex.unlock();
|
||||||
|
|
||||||
|
@ -369,7 +368,8 @@ void CChannel::OnNetTranspPropsReceived ( CNetworkTransportProps NetworkTranspor
|
||||||
MutexSocketBuf.lock();
|
MutexSocketBuf.lock();
|
||||||
{
|
{
|
||||||
// update socket buffer (the network block size is a multiple of the
|
// update socket buffer (the network block size is a multiple of the
|
||||||
// minimum network frame size
|
// minimum network frame size)
|
||||||
|
SockBuf.SetUseDoubleSystemFrameSize ( eAudioCompressionType == CT_OPUS ); // NOTE must be set BEFORE the init()
|
||||||
SockBuf.Init ( iNetwFrameSize, iCurSockBufNumFrames );
|
SockBuf.Init ( iNetwFrameSize, iCurSockBufNumFrames );
|
||||||
}
|
}
|
||||||
MutexSocketBuf.unlock();
|
MutexSocketBuf.unlock();
|
||||||
|
|
|
@ -730,7 +730,7 @@
|
||||||
<tabstop>cbxAudioQuality</tabstop>
|
<tabstop>cbxAudioQuality</tabstop>
|
||||||
<tabstop>edtNewClientLevel</tabstop>
|
<tabstop>edtNewClientLevel</tabstop>
|
||||||
<tabstop>chbGUIDesignFancy</tabstop>
|
<tabstop>chbGUIDesignFancy</tabstop>
|
||||||
<tabstop>chbDisplayChannelFaders</tabstop>
|
<tabstop>chbDisplayChannelLevels</tabstop>
|
||||||
<tabstop>chbDefaultCentralServer</tabstop>
|
<tabstop>chbDefaultCentralServer</tabstop>
|
||||||
<tabstop>edtCentralServerAddress</tabstop>
|
<tabstop>edtCentralServerAddress</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
|
|
Loading…
Reference in a new issue