From 32e8eb7e94fb4b163934699aa36c3c1277de749b Mon Sep 17 00:00:00 2001 From: Volker Fischer Date: Thu, 9 Apr 2020 21:26:40 +0200 Subject: [PATCH] support correct auto jitter buffer settings for 64 and 128 samples frame size --- src/buffer.cpp | 45 +++++++++++++++++++++------ src/buffer.h | 59 +++++++++++++++++++----------------- src/channel.cpp | 14 ++++----- src/clientsettingsdlgbase.ui | 2 +- 4 files changed, 76 insertions(+), 44 deletions(-) diff --git a/src/buffer.cpp b/src/buffer.cpp index dd0dcdff..a067d7b6 100755 --- a/src/buffer.cpp +++ b/src/buffer.cpp @@ -91,7 +91,13 @@ bool CNetBuf::Get ( CVector& 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& 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]. diff --git a/src/buffer.h b/src/buffer.h index 44050d6e..b92413fe 100755 --- a/src/buffer.h +++ b/src/buffer.h @@ -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& vecbyData, const int iInSize ); virtual bool Get ( CVector& 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; }; diff --git a/src/channel.cpp b/src/channel.cpp index 284d1cc0..d406b364 100755 --- a/src/channel.cpp +++ b/src/channel.cpp @@ -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(); diff --git a/src/clientsettingsdlgbase.ui b/src/clientsettingsdlgbase.ui index d53654a7..65cc3650 100755 --- a/src/clientsettingsdlgbase.ui +++ b/src/clientsettingsdlgbase.ui @@ -730,7 +730,7 @@ cbxAudioQuality edtNewClientLevel chbGUIDesignFancy - chbDisplayChannelFaders + chbDisplayChannelLevels chbDefaultCentralServer edtCentralServerAddress