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 ),
iNetwBufSizeFactIn ( DEF_NET_BLOCK_SIZE_FACTOR ),
strIPAddress ( "" ), strName ( "" ),
bOpenChatOnNewMessage ( true )
bOpenChatOnNewMessage ( true ),
bDoAutoSockBufSize ( false )
{
// connection for protocol
QObject::connect ( &Channel,
@ -391,20 +392,9 @@ fflush(pFileDelay);
PostWinMessage ( MS_SOUND_OUT, MUL_COL_LED_GREEN );
}
// update response time measurement ------------------------------------
// 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;
// update response time measurement and socket buffer size
UpdateTimeResponseMeasurement();
UpdateSocketBufferSize();
}
// disable channel
@ -427,3 +417,95 @@ bool CClient::Stop()
// give thread some time to terminate, return status
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();
}
void SetDoAutoSockBufSize ( const bool bValue )
{ bDoAutoSockBufSize = bValue; }
void SetSockBufSize ( const int iNumBlocks )
{
// set the new socket size
Channel.SetSockBufSize ( iNumBlocks );
if ( Channel.GetSockBufSize() != iNumBlocks )
{
// set the new socket size
Channel.SetSockBufSize ( iNumBlocks );
// tell the server that size has changed
Channel.CreateJitBufMes ( iNumBlocks );
// tell the server that size has changed
Channel.CreateJitBufMes ( iNumBlocks );
}
}
int GetSockBufSize() { return Channel.GetSockBufSize(); }
@ -138,10 +143,13 @@ public:
QString strName;
protected:
virtual void run();
virtual void run();
void UpdateTimeResponseMeasurement();
void UpdateSocketBufferSize();
// only one channel is needed for client application
CChannel Channel;
bool bDoAutoSockBufSize;
CSocket Socket;
CSound Sound;

View File

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

View File

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

View File

@ -447,15 +447,20 @@ protected:
class LlconMath
{
public:
static int NextPowerOfTwo ( const int& iSizeIn )
static int NextPowerOfTwo ( const int& x )
{
// calculate the next power of 2 of the given size
int iPowerOfTwo = 1;
while ( iPowerOfTwo < iSizeIn )
int y = 1;
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);
}
};