test implementation for automatic network buffer size setting

This commit is contained in:
Volker Fischer 2009-02-11 18:37:26 +00:00
parent 4e94893aa0
commit d741bc6e30
5 changed files with 133 additions and 31 deletions

View file

@ -35,7 +35,8 @@ CClient::CClient ( const quint16 iPortNumber ) : bRun ( false ),
bReverbOnLeftChan ( false ), bReverbOnLeftChan ( false ),
iNetwBufSizeFactIn ( DEF_NET_BLOCK_SIZE_FACTOR ), iNetwBufSizeFactIn ( DEF_NET_BLOCK_SIZE_FACTOR ),
strIPAddress ( "" ), strName ( "" ), strIPAddress ( "" ), strName ( "" ),
bOpenChatOnNewMessage ( true ) bOpenChatOnNewMessage ( true ),
bDoAutoSockBufSize ( false )
{ {
// connection for protocol // connection for protocol
QObject::connect ( &Channel, QObject::connect ( &Channel,
@ -391,20 +392,9 @@ fflush(pFileDelay);
PostWinMessage ( MS_SOUND_OUT, MUL_COL_LED_GREEN ); PostWinMessage ( MS_SOUND_OUT, MUL_COL_LED_GREEN );
} }
// update response time measurement and socket buffer size
// update response time measurement ------------------------------------ UpdateTimeResponseMeasurement();
// add time difference UpdateSocketBufferSize();
const int CurTime = PreciseTime.elapsed();
// we want to calculate the standard deviation (we assume that the mean
// is correct at the block period time)
const double dCurAddVal =
( (double) ( CurTime - TimeLastBlock ) - MIN_BLOCK_DURATION_MS );
RespTimeMoAvBuf.Add ( dCurAddVal * dCurAddVal ); // add squared value
// store old time value
TimeLastBlock = CurTime;
} }
// disable channel // disable channel
@ -427,3 +417,95 @@ bool CClient::Stop()
// give thread some time to terminate, return status // give thread some time to terminate, return status
return wait ( 5000 ); return wait ( 5000 );
} }
void CClient::UpdateTimeResponseMeasurement()
{
// add time difference
const int CurTime = PreciseTime.elapsed();
// we want to calculate the standard deviation (we assume that the mean
// is correct at the block period time)
const double dCurAddVal =
( (double) ( CurTime - TimeLastBlock ) - MIN_BLOCK_DURATION_MS );
RespTimeMoAvBuf.Add ( dCurAddVal * dCurAddVal ); // add squared value
// store old time value
TimeLastBlock = CurTime;
}
void CClient::UpdateSocketBufferSize()
{
// TEST
static double test = 4;
// just update the socket buffer size if auto setting is enabled, otherwise
// do nothing
//if ( bDoAutoSockBufSize )
{
// we use the time response measurement for the automatic setting
// Assumptions:
// - the network jitter can be neglected compared to the audio
// interface jitter
// - the audio interface jitter is assumed to be Gaussian
// - the buffer size is set to two times the standard deviation of
// the audio interface jitter (~95% of the jitter should be fit in the
// buffer)
// - introduce a hysteresis to avoid switching the buffer sizes all the
// time in case the time response measurement is close to a bound
// - only use time response measurement results if averaging buffer is
// completely filled
const double dHysteresis = 0.3;
//if ( RespTimeMoAvBuf.IsInitialized() )
{
// calculate current buffer setting
// TODO 2* seems not give optimal results, maybe use 3*?
//const double dEstCurBufSet = 2 * GetTimingStdDev();
// TEST
test = test + 0.01 * (2*LlconMath().round ( (double)rand()/RAND_MAX )-1);
if ( test < 0.5 ) test = 0.5;
if ( test > 10 ) test = 10;
const double dEstCurBufSet = test;
// upper/lower hysteresis decision
const int iUpperHystDec = LlconMath().round ( dEstCurBufSet - dHysteresis );
const int iLowerHystDec = LlconMath().round ( dEstCurBufSet + dHysteresis );
// if both decisions are equal than use the result
if ( iUpperHystDec == iLowerHystDec )
{
SetSockBufSize ( iUpperHystDec );
}
else
{
// we are in the middle of the decision region, use
// previous setting for determing the new decision
if ( !( ( GetSockBufSize() == iUpperHystDec ) ||
( GetSockBufSize() == iLowerHystDec ) ) )
{
// the old result is not near the new decision,
// use per definition the upper decision
SetSockBufSize ( iUpperHystDec );
}
}
}
static FILE* pFile = fopen("test.dat", "w");
fprintf(pFile, "%e %d\n",test,GetSockBufSize());
fflush(pFile);
}
}

View file

@ -92,13 +92,18 @@ public:
AudioReverb.Clear(); AudioReverb.Clear();
} }
void SetDoAutoSockBufSize ( const bool bValue )
{ bDoAutoSockBufSize = bValue; }
void SetSockBufSize ( const int iNumBlocks ) void SetSockBufSize ( const int iNumBlocks )
{ {
// set the new socket size if ( Channel.GetSockBufSize() != iNumBlocks )
Channel.SetSockBufSize ( iNumBlocks ); {
// set the new socket size
Channel.SetSockBufSize ( iNumBlocks );
// tell the server that size has changed // tell the server that size has changed
Channel.CreateJitBufMes ( iNumBlocks ); Channel.CreateJitBufMes ( iNumBlocks );
}
} }
int GetSockBufSize() { return Channel.GetSockBufSize(); } int GetSockBufSize() { return Channel.GetSockBufSize(); }
@ -138,10 +143,13 @@ public:
QString strName; QString strName;
protected: protected:
virtual void run(); virtual void run();
void UpdateTimeResponseMeasurement();
void UpdateSocketBufferSize();
// only one channel is needed for client application // only one channel is needed for client application
CChannel Channel; CChannel Channel;
bool bDoAutoSockBufSize;
CSocket Socket; CSocket Socket;
CSound Sound; CSound Sound;

View file

@ -84,8 +84,7 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, QWidget* parent,
// network buffer // network buffer
SliderNetBuf->setRange ( 0, MAX_NET_BUF_SIZE_NUM_BL ); SliderNetBuf->setRange ( 0, MAX_NET_BUF_SIZE_NUM_BL );
const int iCurNumNetBuf = pClient->GetSockBufSize(); const int iCurNumNetBuf = pClient->GetSockBufSize();
SliderNetBuf->setValue ( iCurNumNetBuf ); UpdateNetworkBufSlider ( iCurNumNetBuf );
TextNetBuf->setText ( "Size: " + QString().setNum ( iCurNumNetBuf ) );
// network buffer size factor in // network buffer size factor in
SliderNetBufSiFactIn->setRange ( 1, MAX_NET_BLOCK_SIZE_FACTOR ); SliderNetBufSiFactIn->setRange ( 1, MAX_NET_BLOCK_SIZE_FACTOR );
@ -184,6 +183,12 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, QWidget* parent,
TimerStatus.start ( DISPLAY_UPDATE_TIME ); TimerStatus.start ( DISPLAY_UPDATE_TIME );
} }
void CClientSettingsDlg::UpdateNetworkBufSlider ( const int iCurNumNetBuf )
{
SliderNetBuf->setValue ( iCurNumNetBuf );
TextNetBuf->setText ( "Size: " + QString().setNum ( iCurNumNetBuf ) );
}
void CClientSettingsDlg::UpdateSndBufInSlider ( const int iCurNumInBuf ) void CClientSettingsDlg::UpdateSndBufInSlider ( const int iCurNumInBuf )
{ {
SliderSndBufIn->setValue ( iCurNumInBuf ); SliderSndBufIn->setValue ( iCurNumInBuf );
@ -348,8 +353,9 @@ void CClientSettingsDlg::OnPingTimeResult ( int iPingTime )
void CClientSettingsDlg::UpdateDisplay() void CClientSettingsDlg::UpdateDisplay()
{ {
// update slider controls (settings might have been changed by sound interface) // update slider controls (settings might have been changed by sound interface)
UpdateSndBufInSlider ( pClient->GetSndInterface()->GetInNumBuf() ); UpdateSndBufInSlider ( pClient->GetSndInterface()->GetInNumBuf() );
UpdateSndBufOutSlider ( pClient->GetSndInterface()->GetOutNumBuf() ); UpdateSndBufOutSlider ( pClient->GetSndInterface()->GetOutNumBuf() );
UpdateNetworkBufSlider ( pClient->GetSockBufSize() );
if ( !pClient->IsRunning() ) if ( !pClient->IsRunning() )
{ {

View file

@ -72,8 +72,9 @@ protected:
virtual void showEvent ( QShowEvent* showEvent ); virtual void showEvent ( QShowEvent* showEvent );
virtual void hideEvent ( QHideEvent* hideEvent ); virtual void hideEvent ( QHideEvent* hideEvent );
void UpdateSndBufInSlider ( const int iCurNumInBuf ); void UpdateSndBufInSlider ( const int iCurNumInBuf );
void UpdateSndBufOutSlider ( const int iCurNumOutBuf ); void UpdateSndBufOutSlider ( const int iCurNumOutBuf );
void UpdateNetworkBufSlider ( const int iCurNumNetBuf );
public slots: public slots:
void OnTimerStatus() { UpdateDisplay(); } void OnTimerStatus() { UpdateDisplay(); }

View file

@ -447,15 +447,20 @@ protected:
class LlconMath class LlconMath
{ {
public: public:
static int NextPowerOfTwo ( const int& iSizeIn ) static int NextPowerOfTwo ( const int& x )
{ {
// calculate the next power of 2 of the given size // calculate the next power of 2 of the given size
int iPowerOfTwo = 1; int y = 1;
while ( iPowerOfTwo < iSizeIn ) while ( y < x )
{ {
iPowerOfTwo <<= 1; // multiply by 2 y <<= 1; // multiply by 2
} }
return iPowerOfTwo; return y;
}
static int round ( double x )
{
return (int) ( ( x - floor ( x ) ) >= 0.5 ) ? ceil(x) : floor(x);
} }
}; };