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 ******************/ /* 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].

View file

@ -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;
}; };

View file

@ -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();

View file

@ -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>