Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Jamulus.pro
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,8 @@ HEADERS += src/buffer.h \
src/recorder/jamrecorder.h \
src/recorder/creaperproject.h \
src/recorder/cwavestream.h \
src/signalhandler.h
src/signalhandler.h \
src/jitterbuffer.h

HEADERS_GUI = src/audiomixerboard.h \
src/chatdlg.h \
Expand Down Expand Up @@ -465,7 +466,8 @@ SOURCES += src/buffer.cpp \
src/util.cpp \
src/recorder/jamrecorder.cpp \
src/recorder/creaperproject.cpp \
src/recorder/cwavestream.cpp
src/recorder/cwavestream.cpp \
src/jitterbuffer.cpp

SOURCES_GUI = src/audiomixerboard.cpp \
src/chatdlg.cpp \
Expand Down
138 changes: 63 additions & 75 deletions src/analyzerconsole.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ CAnalyzerConsole::CAnalyzerConsole ( CClient* pNCliP,
pTabErrRateLayout->addWidget ( pGraphErrRate );

pMainTabWidget->addTab ( pTabWidgetBufErrRate,
tr ( "Error Rate of Each Buffer Size" ) );
tr ( "Jitter statistics" ) );


// Connections -------------------------------------------------------------
Expand Down Expand Up @@ -121,103 +121,91 @@ void CAnalyzerConsole::DrawFrame()

void CAnalyzerConsole::DrawErrorRateTrace()
{
float fStats[JITTER_MAX_FRAME_COUNT];
float fMax;
float fClockDrift;
float fPacketDrops;
float fPeerAdjust;
float fLocalAdjust;
int height = GraphGridFrame.height();
int width = GraphGridFrame.width();
int fsize = ( height + 31 ) / 32;
int xmax;

// make room for text
height -= 2 * fsize;

// create painter
QPainter GraphPainter ( &GraphImage );

// get the network buffer error rates to be displayed
CVector<double> vecButErrorRates;
double dLimit;
double dMaxUpLimit;

pClient->GetBufErrorRates ( vecButErrorRates, dLimit, dMaxUpLimit );

// get the number of data elements
const int iNumBuffers = vecButErrorRates.Size();

// convert the limits in the log domain
const double dLogLimit = log10 ( dLimit );
const double dLogMaxUpLimit = log10 ( dMaxUpLimit );

// use fixed y-axis scale where the limit line is in the middle of the graph
const double dMax = 0;
const double dMin = dLogLimit * 2;

// calculate space between points on the x-axis
const double dXSpace =
static_cast<double> ( GraphGridFrame.width() ) / ( iNumBuffers - 1 );

// plot the limit line as dashed line
const double dYValLimitInGraph = CalcYPosInGraph ( dMin, dMax, dLogLimit );
// set font size
QFont font ( GraphPainter.font() );
font.setPixelSize ( fsize );
GraphPainter.setFont ( font );

GraphPainter.setPen ( QPen ( QBrush ( LineLimitColor ),
iLineWidth,
Qt::DashLine ) );
// set font pen
GraphPainter.setPen ( QPen ( QBrush ( GraphFrameColor ), 1 ) );

GraphPainter.drawLine ( QPoint ( GraphGridFrame.x(), dYValLimitInGraph ),
QPoint ( GraphGridFrame.x() +
GraphGridFrame.width(), dYValLimitInGraph ) );
// get jitter statistics
pClient->GetJitterStatistics ( fStats, fClockDrift, fPacketDrops, fPeerAdjust, fLocalAdjust );

// plot the maximum upper limit line as a dashed line
const double dYValMaxUpLimitInGraph = CalcYPosInGraph ( dMin, dMax, dLogMaxUpLimit );
// draw information about clock drift
GraphPainter.drawText ( QPoint ( GraphGridFrame.x(), GraphGridFrame.y() + fsize ),
QString("PeerClkDrift = %1 RxDrops = %2 PeerAdj = %3 LocalAdj = %4")
.arg ( fClockDrift, 0, 'f', 5 )
.arg ( fPacketDrops, 0, 'f', 5 )
.arg ( fPeerAdjust, 0, 'f', 5 )
.arg ( fLocalAdjust, 0, 'f', 5 ) );

GraphPainter.setPen ( QPen ( QBrush ( LineMaxUpLimitColor ),
iLineWidth,
Qt::DashLine ) );

GraphPainter.drawLine ( QPoint ( GraphGridFrame.x(), dYValMaxUpLimitInGraph ),
QPoint ( GraphGridFrame.x() +
GraphGridFrame.width(), dYValMaxUpLimitInGraph ) );

// plot the data
for ( int i = 0; i < iNumBuffers; i++ )
for ( unsigned i = xmax = 0; i != JITTER_MAX_FRAME_COUNT; i++ )
{
// data convert in log domain
// check for special case if error rate is 0 (which would lead to -Inf
// after the log operation)
if ( vecButErrorRates[i] > 0 )
if ( fStats[xmax] < fStats[i] )
{
vecButErrorRates[i] = log10 ( vecButErrorRates[i] );
xmax = i;
}
else
}
fMax = fStats[xmax];

if ( fMax > 1.0f )
{
for ( unsigned i = 0; i != JITTER_MAX_FRAME_COUNT; i++ )
{
// definition: set it to lowest possible axis value
vecButErrorRates[i] = dMin;
fStats[i] /= fMax;
}
}
else
{
memset(fStats, 0, sizeof(fStats));
}

float dX = (float) width / (float) JITTER_MAX_FRAME_COUNT;

QPoint lastPoint;

// plot the first data
for ( unsigned i = 0; i != JITTER_MAX_FRAME_COUNT; i++ )
{
// calculate the actual point in the graph (in pixels)
const QPoint curPoint (
GraphGridFrame.x() + static_cast<int> ( dXSpace * i ),
CalcYPosInGraph ( dMin, dMax, vecButErrorRates[i] ) );
const QPoint nextPoint (
GraphGridFrame.x() + static_cast<int> ( dX * i + dX / 2.0f ),
GraphGridFrame.y() + 2 * fsize + height - 1 - static_cast<int> ( fStats[i] * ( height - 1 ) ) );

if (i == 0)
lastPoint = nextPoint;

// draw a marker and a solid line which goes from the bottom to the
// marker (similar to Matlab stem() function)
GraphPainter.setPen ( QPen ( QBrush ( LineColor ),
GraphPainter.setPen ( QPen ( QBrush ( LineColor ) ,
iMarkerSize,
Qt::SolidLine,
Qt::RoundCap ) );

GraphPainter.drawPoint ( curPoint );
GraphPainter.drawPoint ( nextPoint );

GraphPainter.setPen ( QPen ( QBrush ( LineColor ), iLineWidth ) );

GraphPainter.drawLine ( QPoint ( curPoint.x(),
GraphGridFrame.y() +
GraphGridFrame.height() ),
curPoint );
}
}

int CAnalyzerConsole::CalcYPosInGraph ( const double dAxisMin,
const double dAxisMax,
const double dValue ) const
{
// calculate value range
const double dValRange = dAxisMax - dAxisMin;

// calculate current normalized y-axis value
const double dYValNorm = ( dValue - dAxisMin ) / dValRange;
GraphPainter.drawLine ( lastPoint, nextPoint );

// consider the graph grid size to calculate the final y-axis value
return GraphGridFrame.y() + static_cast<int> (
static_cast<double> ( GraphGridFrame.height() ) * ( 1 - dYValNorm ) );
lastPoint = nextPoint;
}
}
Loading