fixes for the client audio standard deviation measurement, added code for asio interface for using power of two size blocks (not enabled right now)

This commit is contained in:
Volker Fischer 2009-02-08 22:44:18 +00:00
parent c206f84308
commit e42c3afb81
6 changed files with 77 additions and 82 deletions

View file

@ -200,7 +200,7 @@ void CClient::Init()
RespTimeMoAvBuf.Init ( LEN_MOV_AV_RESPONSE ); RespTimeMoAvBuf.Init ( LEN_MOV_AV_RESPONSE );
// init time for response time evaluation // init time for response time evaluation
TimeLastBlock = QTime::currentTime(); TimeLastBlock = PreciseTime.elapsed();
AudioReverb.Clear(); AudioReverb.Clear();
} }
@ -338,56 +338,8 @@ void CClient::run()
PostWinMessage ( MS_JIT_BUF_GET, MUL_COL_LED_RED ); 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<short> 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); // fid=fopen('v.dat','r');x=fread(fid,'int16');fclose(fid);
static FILE* pFileDelay = fopen("v.dat", "wb"); static FILE* pFileDelay = fopen("v.dat", "wb");
short sData[2]; short sData[2];
@ -399,7 +351,6 @@ for (i = 0; i < iBlockSizeSam; i++)
fflush(pFileDelay); fflush(pFileDelay);
*/ */
// check if channel is connected // check if channel is connected
if ( Channel.IsConnected() ) if ( Channel.IsConnected() )
{ {
@ -443,12 +394,12 @@ fflush(pFileDelay);
// update response time measurement ------------------------------------ // update response time measurement ------------------------------------
// add time difference // 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 // we want to calculate the standard deviation (we assume that the mean
// is correct at the block period time) // is correct at the block period time)
const double dCurAddVal = 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 RespTimeMoAvBuf.Add ( dCurAddVal * dCurAddVal ); // add squared value

View file

@ -178,12 +178,12 @@ protected:
CAudioResample ResampleObjUpL; // left channel CAudioResample ResampleObjUpL; // left channel
CAudioResample ResampleObjUpR; // right channel CAudioResample ResampleObjUpR; // right channel
// for ping measurement // for ping measurement and standard deviation of audio interface
CPreciseTime PreciseTime; CPreciseTime PreciseTime;
// debugging, evaluating // debugging, evaluating
CMovingAv<double> RespTimeMoAvBuf; CMovingAv<double> RespTimeMoAvBuf;
QTime TimeLastBlock; int TimeLastBlock;
public slots: public slots:
void OnSendProtMessage ( CVector<uint8_t> vecMessage ); void OnSendProtMessage ( CVector<uint8_t> vecMessage );

View file

@ -357,6 +357,11 @@ void CLlconClientDlg::UpdateDisplay()
{ {
TextLabelStatus->setText ( tr ( "disconnected" ) ); TextLabelStatus->setText ( tr ( "disconnected" ) );
} }
// TEST
//TextLabelStatus->setText ( QString( "Std dev: %1" ).arg ( pClient->GetTimingStdDev() ) );
} }
void CLlconClientDlg::customEvent ( QEvent* Event ) void CLlconClientDlg::customEvent ( QEvent* Event )

View file

@ -107,6 +107,7 @@ void CServer::Start()
// init time for response time evaluation // init time for response time evaluation
TimeLastBlock = QTime::currentTime(); TimeLastBlock = QTime::currentTime();
RespTimeMoAvBuf.Reset();
} }
} }
@ -158,9 +159,19 @@ void CServer::OnTimer()
ChannelSet.PrepSendPacket ( vecChanID[i], vecsSendData ), ChannelSet.PrepSendPacket ( vecChanID[i], vecsSendData ),
ChannelSet.GetAddress ( vecChanID[i] ) ); ChannelSet.GetAddress ( vecChanID[i] ) );
} }
}
else
{
// Disable server if no clients are connected. In this case the server
// does not consume any significant CPU when no client is connected.
#ifndef _WIN32
// event handling of custom events seems not to work under Windows in this
// class, do not use automatic start/stop of server in Windows version
Stop();
#endif
}
// update response time measurement ----------------------------------------
// update response time measurement ------------------------------------
// add time difference // add time difference
const QTime CurTime = QTime::currentTime(); const QTime CurTime = QTime::currentTime();
@ -174,17 +185,6 @@ void CServer::OnTimer()
// store old time value // store old time value
TimeLastBlock = CurTime; TimeLastBlock = CurTime;
} }
else
{
// Disable server if no clients are connected. In this case the server
// does not consume any significant CPU when no client is connected.
#ifndef _WIN32
// event handling of custom events seems not to work under Windows in this
// class, do not use automatic start/stop of server in Windows version
Stop();
#endif
}
}
CVector<short> CServer::ProcessData ( CVector<CVector<double> >& vecvecdData, CVector<short> CServer::ProcessData ( CVector<CVector<double> >& vecvecdData,
CVector<double>& vecdGains ) CVector<double>& vecdGains )

View file

@ -269,6 +269,7 @@ public:
virtual void Init ( const int iNewSize ); virtual void Init ( const int iNewSize );
void InitVec ( const int iNewSize, const int iNewVecSize ); void InitVec ( const int iNewSize, const int iNewVecSize );
void Reset();
protected: protected:
int iCurIdx; int iCurIdx;
@ -284,6 +285,14 @@ template<class TData> void CMovingAv<TData>::Init ( const int iNewSize )
CVector<TData>::Init ( iNewSize ); CVector<TData>::Init ( iNewSize );
} }
template<class TData> void CMovingAv<TData>::Reset()
{
iNorm = 0;
iCurIdx = 0;
tCurAvResult = TData ( 0 ); // only for scalars!
CVector<TData>::Reset ( TData ( 0 ) );
}
template<class TData> void CMovingAv<TData>::Add ( const TData tNewD ) template<class TData> void CMovingAv<TData>::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 ---------------------------------------------------------------- // Precise time ----------------------------------------------------------------
// needed for ping measurement // needed for ping measurement
class CPreciseTime class CPreciseTime

View file

@ -407,6 +407,7 @@ bool CSound::LoadAndInitializeFirstValidDriver()
std::string CSound::PrepareDriver() std::string CSound::PrepareDriver()
{ {
int i; int i;
int iDesiredBufferSizeMono;
// check the number of available channels // check the number of available channels
long lNumInChan; long lNumInChan;
@ -442,15 +443,31 @@ std::string CSound::PrepareDriver()
&HWBufferInfo.lPreferredSize, &HWBufferInfo.lPreferredSize,
&HWBufferInfo.lGranularity ); &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 // calculate "nearest" buffer size and set internal parameter accordingly
// first check minimum and maximum values // first check minimum and maximum values
if ( iBufferSizeMono < HWBufferInfo.lMinSize ) if ( iDesiredBufferSizeMono < HWBufferInfo.lMinSize )
{ {
iASIOBufferSizeMono = HWBufferInfo.lMinSize; iASIOBufferSizeMono = HWBufferInfo.lMinSize;
} }
else else
{ {
if ( iBufferSizeMono > HWBufferInfo.lMaxSize ) if ( iDesiredBufferSizeMono > HWBufferInfo.lMaxSize )
{ {
iASIOBufferSizeMono = HWBufferInfo.lMaxSize; iASIOBufferSizeMono = HWBufferInfo.lMaxSize;
} }
@ -464,18 +481,14 @@ std::string CSound::PrepareDriver()
// test loop // test loop
while ( ( iTrialBufSize <= HWBufferInfo.lMaxSize ) && ( !bSizeFound ) ) while ( ( iTrialBufSize <= HWBufferInfo.lMaxSize ) && ( !bSizeFound ) )
{ {
if ( iTrialBufSize >= iBufferSizeMono ) if ( iTrialBufSize >= iDesiredBufferSizeMono )
{ {
// test which buffer size fits better: the old one or the // test which buffer size fits better: the old one or the
// current one // current one
if ( ( iTrialBufSize - iBufferSizeMono ) < if ( ( iTrialBufSize - iDesiredBufferSizeMono ) >
( iBufferSizeMono - iLastTrialBufSize ) ) ( iDesiredBufferSizeMono - iLastTrialBufSize ) )
{ {
iBufferSizeMono = iTrialBufSize; iTrialBufSize = iLastTrialBufSize;
}
else
{
iBufferSizeMono = iLastTrialBufSize;
} }
// exit while loop // exit while loop