support correct auto jitter buffer settings for 64 and 128 samples frame size

This commit is contained in:
Volker Fischer 2020-04-09 21:26:40 +02:00
parent 16ecb72ecd
commit 32e8eb7e94
4 changed files with 76 additions and 44 deletions

View file

@ -91,7 +91,13 @@ bool CNetBuf::Get ( CVector<uint8_t>& vecbyData,
/* Network buffer with statistic calculations implementation ******************/
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,
// must be NUM_STAT_SIMULATION_BUFFERS elements!
@ -143,13 +149,31 @@ void CNetBufWithStats::Init ( const int iNewBlockSize,
// inits for statistics calculation
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++ )
{
// init simulation buffers with the correct size
SimulationBuffer[i].Init ( iNewBlockSize, viBufSizesForSim[i] );
// init statistics
ErrorRateStatistic[i].Init ( MAX_STATISTIC_COUNT, true );
ErrorRateStatistic[i].Init ( iMaxStatisticCount, true );
}
// 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
// initialization value (initialization phase should be as short as
// possible)
iInitCounter = MAX_STATISTIC_COUNT / 4;
iInitCounter = iMaxStatisticCount / 4;
}
bool CNetBufWithStats::Put ( const CVector<uint8_t>& vecbyData,
@ -276,8 +300,7 @@ void CNetBufWithStats::UpdateAutoSetting()
// the current jitter buffer size significantly.
// For the initialization phase, use lower weight values to get faster
// adaptation.
double dWeightUp = IIR_WEIGTH_UP_NORMAL;
double dWeightDown = IIR_WEIGTH_DOWN_NORMAL;
double dWeightUp, dWeightDown;
const double dHysteresisValue = FILTER_DECISION_HYSTERESIS;
bool bUseFastAdaptation = false;
@ -301,9 +324,13 @@ void CNetBufWithStats::UpdateAutoSetting()
if ( bUseFastAdaptation )
{
// overwrite weigth values with lower values
dWeightUp = IIR_WEIGTH_UP_FAST;
dWeightDown = IIR_WEIGTH_DOWN_FAST;
dWeightUp = dAutoFilt_WightUpFast;
dWeightDown = dAutoFilt_WightDownFast;
}
else
{
dWeightUp = dAutoFilt_WightUpNormal;
dWeightDown = dAutoFilt_WightDownNormal;
}
// apply non-linear IIR filter
@ -338,7 +365,7 @@ else
// Initialization phase check and correction -------------------------------
// sometimes in the very first period after a connection we get a bad error
// 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
if ( ErrorRateStatistic[NUM_STAT_SIMULATION_BUFFERS - 1].

View file

@ -31,43 +31,41 @@
/* Definitions ****************************************************************/
// number of simulation network jitter buffers for evaluating the statistic
// NOTE If you want to change this number, the code has to modified, too!
#define NUM_STAT_SIMULATION_BUFFERS 10
#define NUM_STAT_SIMULATION_BUFFERS 10
// hysteresis for buffer size decision to avoid fast changes if close to the bound
#define FILTER_DECISION_HYSTERESIS 0.1
#define FILTER_DECISION_HYSTERESIS 0.1
// definition of the upper error bound of the jitter buffers
#define ERROR_RATE_BOUND 0.001
#define ERROR_RATE_BOUND 0.001
// definition of the upper jitter buffer error bound, if that one is reached we
// have to speed up the filtering to quickly get out of a incorrect buffer
// 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
// 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
# 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
// and https://octave-online.net:
// 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_DOWN_NORMAL 0.99994999875
# define IIR_WEIGTH_UP_FAST 0.9997499687422
# 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
#define IIR_WEIGTH_UP_NORMAL 0.9999975
#define IIR_WEIGTH_DOWN_NORMAL 0.99994999875
#define IIR_WEIGTH_UP_FAST 0.9997499687422
#define IIR_WEIGTH_DOWN_FAST 0.999499875
/* Classes ********************************************************************/
@ -90,7 +88,6 @@ public:
{
// copy old data in new vector using get pointer as zero per
// definition
int iCurPos;
// copy current data in temporary vector
@ -158,8 +155,7 @@ public:
// perform copying of second part
for ( iCurPos = 0; iCurPos < iRemainingCopyLen; iCurPos++ )
{
vecMemory[iCurPos + iFirstPartLen] =
vecTempMemory[iCurPos];
vecMemory[iCurPos + iFirstPartLen] = vecTempMemory[iCurPos];
}
}
}
@ -428,10 +424,12 @@ class CNetBufWithStats : public CNetBuf
public:
CNetBufWithStats();
void Init ( const int iNewBlockSize,
const int iNewNumBlocks,
void Init ( const int iNewBlockSize,
const int iNewNumBlocks,
const bool bPreserve = false );
void SetUseDoubleSystemFrameSize ( const bool bNDSFSize ) { bUseDoubleSystemFrameSize = bNDSFSize; }
virtual bool Put ( const CVector<uint8_t>& vecbyData, const int iInSize );
virtual bool Get ( CVector<uint8_t>& vecbyData, const int iOutSize );
@ -454,6 +452,13 @@ protected:
int iCurDecidedResult;
int iInitCounter;
int iCurAutoBufferSizeSetting;
int iMaxStatisticCount;
bool bUseDoubleSystemFrameSize;
double dAutoFilt_WightUpNormal;
double dAutoFilt_WightDownNormal;
double dAutoFilt_WightUpFast;
double dAutoFilt_WightDownFast;
};

View file

@ -140,14 +140,13 @@ void CChannel::SetEnable ( const bool bNEnStat )
}
void CChannel::SetAudioStreamProperties ( const EAudComprType eNewAudComprType,
const int iNewNetwFrameSize,
const int iNewNetwFrameSizeFact,
const int iNewNumAudioChannels )
const int iNewNetwFrameSize,
const int iNewNetwFrameSizeFact,
const int iNewNumAudioChannels )
{
/*
this function is intended for the client (not the server)
*/
CNetworkTransportProps NetworkTransportProps;
Mutex.lock();
@ -161,6 +160,7 @@ void CChannel::SetAudioStreamProperties ( const EAudComprType eNewAudComprType,
MutexSocketBuf.lock();
{
// init socket buffer
SockBuf.SetUseDoubleSystemFrameSize ( eAudioCompressionType == CT_OPUS ); // NOTE must be set BEFORE the init()
SockBuf.Init ( iNetwFrameSize, iCurSockBufNumFrames );
}
MutexSocketBuf.unlock();
@ -173,8 +173,7 @@ void CChannel::SetAudioStreamProperties ( const EAudComprType eNewAudComprType,
MutexConvBuf.unlock();
// fill network transport properties struct
NetworkTransportProps =
GetNetworkTransportPropsFromCurrentSettings();
NetworkTransportProps = GetNetworkTransportPropsFromCurrentSettings();
}
Mutex.unlock();
@ -369,7 +368,8 @@ void CChannel::OnNetTranspPropsReceived ( CNetworkTransportProps NetworkTranspor
MutexSocketBuf.lock();
{
// 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 );
}
MutexSocketBuf.unlock();

View file

@ -730,7 +730,7 @@
<tabstop>cbxAudioQuality</tabstop>
<tabstop>edtNewClientLevel</tabstop>
<tabstop>chbGUIDesignFancy</tabstop>
<tabstop>chbDisplayChannelFaders</tabstop>
<tabstop>chbDisplayChannelLevels</tabstop>
<tabstop>chbDefaultCentralServer</tabstop>
<tabstop>edtCentralServerAddress</tabstop>
</tabstops>