From e42c3afb815c7346a1df0dd7c1e59cc27a200961 Mon Sep 17 00:00:00 2001 From: Volker Fischer Date: Sun, 8 Feb 2009 22:44:18 +0000 Subject: [PATCH] fixes for the client audio standard deviation measurement, added code for asio interface for using power of two size blocks (not enabled right now) --- src/client.cpp | 57 +++--------------------------------------- src/client.h | 4 +-- src/llconclientdlg.cpp | 5 ++++ src/server.cpp | 30 +++++++++++----------- src/util.h | 30 ++++++++++++++++++++-- windows/sound.cpp | 33 ++++++++++++++++-------- 6 files changed, 77 insertions(+), 82 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index cb5a4a49..99d53060 100755 --- a/src/client.cpp +++ b/src/client.cpp @@ -200,7 +200,7 @@ void CClient::Init() RespTimeMoAvBuf.Init ( LEN_MOV_AV_RESPONSE ); // init time for response time evaluation - TimeLastBlock = QTime::currentTime(); + TimeLastBlock = PreciseTime.elapsed(); AudioReverb.Clear(); } @@ -338,56 +338,8 @@ void CClient::run() PostWinMessage ( MS_JIT_BUF_GET, MUL_COL_LED_RED ); } -#ifdef _DEBUG_ -#if 0 -#if 0 -/* Determine network delay. We can do this very simple if only this client is - connected to the server. In this case, exactly the same audio material is - coming back and we can simply compare the samples */ -/* store send data instatic buffer (may delay is 100 ms) */ -const int iMaxDelaySamples = (int) ((float) 0.3 /*0.1*/ * SYSTEM_SAMPLE_RATE); -static CVector vecsOutBuf(iMaxDelaySamples); - -/* update buffer */ -const int iBufDiff = iMaxDelaySamples - iBlockSizeSam; -for (i = 0; i < iBufDiff; i++) - vecsOutBuf[i + iBlockSizeSam] = vecsOutBuf[i]; -for (i = 0; i < iBlockSizeSam; i++) - vecsOutBuf[i] = vecsNetwork[i]; - -/* now search for equal samples */ -int iDelaySamples = 0; -for (i = 0; i < iMaxDelaySamples - 1; i++) -{ - /* compare two successive samples */ - if ((vecsOutBuf[i] == (short) vecdNetwData[0]) && - (vecsOutBuf[i + 1] == (short) vecdNetwData[1])) - { - iDelaySamples = i; - } -} - -static FILE* pFileDelay = fopen("delay.dat", "w"); -fprintf(pFileDelay, "%d\n", iDelaySamples); -fflush(pFileDelay); -#else -/* just store both, input and output, streams */ -// fid=fopen('v.dat','r');x=fread(fid,'int16');fclose(fid); -static FILE* pFileDelay = fopen("v.dat", "wb"); -short sData[2]; -for (i = 0; i < iBlockSizeSam; i++) -{ - sData[0] = vecsNetwork[i]; - sData[1] = (short) vecdNetwData[i]; - fwrite(&sData, size_t(2), size_t(2), pFileDelay); -} -fflush(pFileDelay); -#endif -#endif -#endif - - /* +// TEST // fid=fopen('v.dat','r');x=fread(fid,'int16');fclose(fid); static FILE* pFileDelay = fopen("v.dat", "wb"); short sData[2]; @@ -399,7 +351,6 @@ for (i = 0; i < iBlockSizeSam; i++) fflush(pFileDelay); */ - // check if channel is connected if ( Channel.IsConnected() ) { @@ -443,12 +394,12 @@ fflush(pFileDelay); // update response time measurement ------------------------------------ // add time difference - const QTime CurTime = QTime::currentTime(); + 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) TimeLastBlock.msecsTo ( CurTime ) - MIN_BLOCK_DURATION_MS ); + ( (double) ( CurTime - TimeLastBlock ) - MIN_BLOCK_DURATION_MS ); RespTimeMoAvBuf.Add ( dCurAddVal * dCurAddVal ); // add squared value diff --git a/src/client.h b/src/client.h index c27810bc..1429bf00 100755 --- a/src/client.h +++ b/src/client.h @@ -178,12 +178,12 @@ protected: CAudioResample ResampleObjUpL; // left channel CAudioResample ResampleObjUpR; // right channel - // for ping measurement + // for ping measurement and standard deviation of audio interface CPreciseTime PreciseTime; // debugging, evaluating CMovingAv RespTimeMoAvBuf; - QTime TimeLastBlock; + int TimeLastBlock; public slots: void OnSendProtMessage ( CVector vecMessage ); diff --git a/src/llconclientdlg.cpp b/src/llconclientdlg.cpp index c44ed4bc..f221d5cd 100755 --- a/src/llconclientdlg.cpp +++ b/src/llconclientdlg.cpp @@ -357,6 +357,11 @@ void CLlconClientDlg::UpdateDisplay() { TextLabelStatus->setText ( tr ( "disconnected" ) ); } + +// TEST +//TextLabelStatus->setText ( QString( "Std dev: %1" ).arg ( pClient->GetTimingStdDev() ) ); + + } void CLlconClientDlg::customEvent ( QEvent* Event ) diff --git a/src/server.cpp b/src/server.cpp index c74aab67..a53c83ae 100755 --- a/src/server.cpp +++ b/src/server.cpp @@ -107,6 +107,7 @@ void CServer::Start() // init time for response time evaluation TimeLastBlock = QTime::currentTime(); + RespTimeMoAvBuf.Reset(); } } @@ -158,21 +159,6 @@ void CServer::OnTimer() ChannelSet.PrepSendPacket ( vecChanID[i], vecsSendData ), ChannelSet.GetAddress ( vecChanID[i] ) ); } - - - // update response time measurement ------------------------------------ - // add time difference - const QTime CurTime = QTime::currentTime (); - - // we want to calculate the standard deviation (we assume that the mean - // is correct at the block period time) - const double dCurAddVal = ( (double) TimeLastBlock.msecsTo ( CurTime ) - - MIN_BLOCK_DURATION_MS ); - - RespTimeMoAvBuf.Add ( dCurAddVal * dCurAddVal ); // add squared value - - // store old time value - TimeLastBlock = CurTime; } else { @@ -184,6 +170,20 @@ void CServer::OnTimer() Stop(); #endif } + + // update response time measurement ---------------------------------------- + // add time difference + const QTime CurTime = QTime::currentTime(); + + // we want to calculate the standard deviation (we assume that the mean + // is correct at the block period time) + const double dCurAddVal = ( (double) TimeLastBlock.msecsTo ( CurTime ) - + MIN_BLOCK_DURATION_MS ); + + RespTimeMoAvBuf.Add ( dCurAddVal * dCurAddVal ); // add squared value + + // store old time value + TimeLastBlock = CurTime; } CVector CServer::ProcessData ( CVector >& vecvecdData, diff --git a/src/util.h b/src/util.h index 8d660fca..c19029d9 100755 --- a/src/util.h +++ b/src/util.h @@ -269,6 +269,7 @@ public: virtual void Init ( const int iNewSize ); void InitVec ( const int iNewSize, const int iNewVecSize ); + void Reset(); protected: int iCurIdx; @@ -284,6 +285,14 @@ template void CMovingAv::Init ( const int iNewSize ) CVector::Init ( iNewSize ); } +template void CMovingAv::Reset() +{ + iNorm = 0; + iCurIdx = 0; + tCurAvResult = TData ( 0 ); // only for scalars! + CVector::Reset ( TData ( 0 ) ); +} + template void CMovingAv::Add ( const TData tNewD ) { /* @@ -433,6 +442,23 @@ protected: }; +// Mathematics utilities ------------------------------------------------------- +class LlconMath +{ +public: + static int NextPowerOfTwo ( const int& iSizeIn ) + { + // calculate the next power of 2 of the given size + int iPowerOfTwo = 1; + while ( iPowerOfTwo < iSizeIn ) + { + iPowerOfTwo <<= 1; // multiply by 2 + } + return iPowerOfTwo; + } +}; + + // Precise time ---------------------------------------------------------------- // needed for ping measurement class CPreciseTime @@ -441,8 +467,8 @@ public: #ifdef _WIN32 // for the Windows version we have to define a minimum timer precision // -> set it to 1 ms - CPreciseTime() { timeBeginPeriod(1); } - virtual ~CPreciseTime() { timeEndPeriod(1); } + CPreciseTime() { timeBeginPeriod ( 1 ); } + virtual ~CPreciseTime() { timeEndPeriod ( 1 ); } #endif // precise time (on Windows the QTime is not precise enough) diff --git a/windows/sound.cpp b/windows/sound.cpp index 4ddde792..c0467c15 100755 --- a/windows/sound.cpp +++ b/windows/sound.cpp @@ -407,6 +407,7 @@ bool CSound::LoadAndInitializeFirstValidDriver() std::string CSound::PrepareDriver() { int i; + int iDesiredBufferSizeMono; // check the number of available channels long lNumInChan; @@ -442,15 +443,31 @@ std::string CSound::PrepareDriver() &HWBufferInfo.lPreferredSize, &HWBufferInfo.lGranularity ); + // calculate the desired mono buffer size + +// TEST -> put this in the GUI and implement the code for the Linux driver, too +// setting this variable to false sets the previous behaviour +const bool bPreferPowerOfTwoAudioBufferSize = false; + + if ( bPreferPowerOfTwoAudioBufferSize ) + { + // use next power of 2 for desired block size mono + iDesiredBufferSizeMono = LlconMath().NextPowerOfTwo ( iBufferSizeMono ); + } + else + { + iDesiredBufferSizeMono = iBufferSizeMono; + } + // calculate "nearest" buffer size and set internal parameter accordingly // first check minimum and maximum values - if ( iBufferSizeMono < HWBufferInfo.lMinSize ) + if ( iDesiredBufferSizeMono < HWBufferInfo.lMinSize ) { iASIOBufferSizeMono = HWBufferInfo.lMinSize; } else { - if ( iBufferSizeMono > HWBufferInfo.lMaxSize ) + if ( iDesiredBufferSizeMono > HWBufferInfo.lMaxSize ) { iASIOBufferSizeMono = HWBufferInfo.lMaxSize; } @@ -464,18 +481,14 @@ std::string CSound::PrepareDriver() // test loop while ( ( iTrialBufSize <= HWBufferInfo.lMaxSize ) && ( !bSizeFound ) ) { - if ( iTrialBufSize >= iBufferSizeMono ) + if ( iTrialBufSize >= iDesiredBufferSizeMono ) { // test which buffer size fits better: the old one or the // current one - if ( ( iTrialBufSize - iBufferSizeMono ) < - ( iBufferSizeMono - iLastTrialBufSize ) ) + if ( ( iTrialBufSize - iDesiredBufferSizeMono ) > + ( iDesiredBufferSizeMono - iLastTrialBufSize ) ) { - iBufferSizeMono = iTrialBufSize; - } - else - { - iBufferSizeMono = iLastTrialBufSize; + iTrialBufSize = iLastTrialBufSize; } // exit while loop