kopia lustrzana https://gitlab.com/eliggett/wfview
Add some more debugging when audio is delayed
rodzic
2525641e76
commit
bb6c615b4c
|
@ -212,9 +212,18 @@ void audioHandler::start()
|
||||||
audioTimer->start(setup.blockSize);
|
audioTimer->start(setup.blockSize);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Buffer size must be set before audio is started.
|
/* OK I don't understand what is happening here?
|
||||||
audioOutput->setBufferSize(getAudioSize(setup.latency, format));
|
On Windows, I set the buffer size and when the stream is started, the buffer size is multiplied by 10?
|
||||||
|
this doesn't happen on Linux/
|
||||||
|
We want the buffer sizes to be slightly more than the setup.latency value
|
||||||
|
*/
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
audioOutput->setBufferSize(format.bytesForDuration(setup.latency * 100));
|
||||||
|
#else
|
||||||
|
audioOutput->setBufferSize(format.bytesForDuration(setup.latency * 1000));
|
||||||
|
#endif
|
||||||
audioDevice = audioOutput->start();
|
audioDevice = audioOutput->start();
|
||||||
|
qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "bufferSize needed" << format.bytesForDuration((quint32)setup.latency * 1000) << "got" << audioOutput->bufferSize();
|
||||||
connect(audioOutput, &QAudioOutput::destroyed, audioDevice, &QIODevice::deleteLater, Qt::UniqueConnection);
|
connect(audioOutput, &QAudioOutput::destroyed, audioDevice, &QIODevice::deleteLater, Qt::UniqueConnection);
|
||||||
}
|
}
|
||||||
if (!audioDevice) {
|
if (!audioDevice) {
|
||||||
|
@ -244,6 +253,13 @@ void audioHandler::stop()
|
||||||
|
|
||||||
void audioHandler::setVolume(unsigned char volume)
|
void audioHandler::setVolume(unsigned char volume)
|
||||||
{
|
{
|
||||||
|
/*float volumeLevelLinear = float(0.5); //cut amplitude in half
|
||||||
|
float volumeLevelDb = float(10 * (qLn(double(volumeLevelLinear)) / qLn(10)));
|
||||||
|
float volumeLinear = (volume / float(100));
|
||||||
|
this->volume = volumeLinear * float(qPow(10, (qreal(volumeLevelDb)) / 20));
|
||||||
|
|
||||||
|
this->volume = qMin(this->volume, float(1));
|
||||||
|
*/
|
||||||
this->volume = audiopot[volume];
|
this->volume = audiopot[volume];
|
||||||
qDebug(logAudio()) << (setup.isinput ? "Input" : "Output") << "setVolume: " << volume << "(" << this->volume << ")";
|
qDebug(logAudio()) << (setup.isinput ? "Input" : "Output") << "setVolume: " << volume << "(" << this->volume << ")";
|
||||||
}
|
}
|
||||||
|
@ -252,6 +268,11 @@ void audioHandler::setVolume(unsigned char volume)
|
||||||
void audioHandler::incomingAudio(audioPacket inPacket)
|
void audioHandler::incomingAudio(audioPacket inPacket)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
if (lastReceived.msecsTo(QTime::currentTime()) > 30) {
|
||||||
|
qDebug(logAudio()) << (setup.isinput ? "Input" : "Output") << "Time since last audio packet" << lastReceived.msecsTo(QTime::currentTime()) << "Expected around" << setup.blockSize;
|
||||||
|
}
|
||||||
|
lastReceived = QTime::currentTime();
|
||||||
audioPacket livePacket = inPacket;
|
audioPacket livePacket = inPacket;
|
||||||
// Process uLaw.
|
// Process uLaw.
|
||||||
if (setup.ulaw)
|
if (setup.ulaw)
|
||||||
|
@ -427,7 +448,6 @@ void audioHandler::incomingAudio(audioPacket inPacket)
|
||||||
qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Unsupported Sample Type:" << format.sampleType();
|
qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Unsupported Sample Type:" << format.sampleType();
|
||||||
}
|
}
|
||||||
|
|
||||||
currentLatency = livePacket.time.msecsTo(QTime::currentTime()) + getAudioDuration(audioOutput->bufferSize()-audioOutput->bytesFree(),format);
|
|
||||||
if (audioDevice != Q_NULLPTR) {
|
if (audioDevice != Q_NULLPTR) {
|
||||||
audioDevice->write(livePacket.data);
|
audioDevice->write(livePacket.data);
|
||||||
}
|
}
|
||||||
|
@ -437,8 +457,12 @@ void audioHandler::incomingAudio(audioPacket inPacket)
|
||||||
incomingAudio(inPacket); // Call myself again to run the packet a second time (FEC)
|
incomingAudio(inPacket); // Call myself again to run the packet a second time (FEC)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
currentLatency = livePacket.time.msecsTo(QTime::currentTime()) + (format.durationForBytes(audioOutput->bufferSize() - audioOutput->bytesFree()) / 1000);
|
||||||
lastSentSeq = inPacket.seq;
|
lastSentSeq = inPacket.seq;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
qDebug(logAudio()) << (setup.isinput ? "Input" : "Output") << "Received audio packet is empty?";
|
||||||
|
}
|
||||||
|
|
||||||
emit haveLevels(getAmplitude(), setup.latency, currentLatency,isUnderrun);
|
emit haveLevels(getAmplitude(), setup.latency, currentLatency,isUnderrun);
|
||||||
|
|
||||||
|
@ -454,14 +478,18 @@ void audioHandler::getNextAudioChunk()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
audioPacket livePacket;
|
audioPacket livePacket;
|
||||||
livePacket.time= QTime::currentTime();
|
livePacket.time= QTime::currentTime();
|
||||||
livePacket.sent = 0;
|
livePacket.sent = 0;
|
||||||
memcpy(&livePacket.guid, setup.guid, GUIDLEN);
|
memcpy(&livePacket.guid, setup.guid, GUIDLEN);
|
||||||
while (tempBuf.data.length() > format.bytesForDuration(setup.blockSize * 1000)) {
|
while (tempBuf.data.length() > format.bytesForDuration(setup.blockSize * 1000)) {
|
||||||
|
QTime startProcessing = QTime::currentTime();
|
||||||
livePacket.data.clear();
|
livePacket.data.clear();
|
||||||
livePacket.data = tempBuf.data.mid(0, format.bytesForDuration(setup.blockSize * 1000));
|
livePacket.data = tempBuf.data.mid(0, format.bytesForDuration(setup.blockSize * 1000));
|
||||||
tempBuf.data.remove(0, format.bytesForDuration(setup.blockSize * 1000));
|
tempBuf.data.remove(0, format.bytesForDuration(setup.blockSize * 1000));
|
||||||
|
//qDebug(logAudio()) << "Got bytes " << format.bytesForDuration(setup.blockSize * 1000);
|
||||||
|
|
||||||
if (livePacket.data.length() > 0)
|
if (livePacket.data.length() > 0)
|
||||||
{
|
{
|
||||||
Eigen::VectorXf samplesF;
|
Eigen::VectorXf samplesF;
|
||||||
|
@ -618,6 +646,11 @@ void audioHandler::getNextAudioChunk()
|
||||||
livePacket.data = outPacket; // Copy output packet back to input buffer.
|
livePacket.data = outPacket; // Copy output packet back to input buffer.
|
||||||
}
|
}
|
||||||
emit haveAudioData(livePacket);
|
emit haveAudioData(livePacket);
|
||||||
|
if (lastReceived.msecsTo(QTime::currentTime()) > 30) {
|
||||||
|
qDebug(logAudio()) << (setup.isinput ? "Input" : "Output") << "Time since last audio packet" << lastReceived.msecsTo(QTime::currentTime()) << "Expected around" << setup.blockSize << "Processing time" <<startProcessing.msecsTo(QTime::currentTime());
|
||||||
|
}
|
||||||
|
lastReceived = QTime::currentTime();
|
||||||
|
|
||||||
//ret = livePacket.data;
|
//ret = livePacket.data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -637,7 +670,7 @@ void audioHandler::changeLatency(const quint16 newSize)
|
||||||
stop();
|
stop();
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
qDebug(logAudio()) << (setup.isinput ? "Input" : "Output") << "Configured latency: " << setup.latency << "Buffer Duration:" << getAudioDuration(audioOutput->bufferSize(), format) << "ms";
|
qDebug(logAudio()) << (setup.isinput ? "Input" : "Output") << "Configured latency: " << setup.latency << "Buffer Duration:" << format.durationForBytes(audioOutput->bufferSize()/1000) << "ms";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -662,18 +695,22 @@ void audioHandler::stateChanged(QAudio::State state)
|
||||||
{
|
{
|
||||||
case QAudio::IdleState:
|
case QAudio::IdleState:
|
||||||
{
|
{
|
||||||
isUnderrun = true;
|
if (!setup.isinput)
|
||||||
if (underTimer->isActive()) {
|
{
|
||||||
underTimer->stop();
|
qDebug(logAudio()) << "Output Underrun detected" << "Buffer size" << audioOutput->bufferSize() << "Bytes free" << audioOutput->bytesFree();
|
||||||
|
if (isUnderrun && audioOutput->bytesFree() > audioOutput->bufferSize()/2) {
|
||||||
|
audioOutput->suspend();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
isUnderrun = true;
|
||||||
|
if (!underTimer->isActive()) {
|
||||||
|
underTimer->start(setup.latency/2);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case QAudio::ActiveState:
|
case QAudio::ActiveState:
|
||||||
{
|
{
|
||||||
//qDebug(logAudio()) << (setup.isinput ? "Input" : "Output") << "Audio started!";
|
|
||||||
if (!underTimer->isActive()) {
|
|
||||||
underTimer->start(500);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case QAudio::SuspendedState:
|
case QAudio::SuspendedState:
|
||||||
|
@ -694,4 +731,8 @@ void audioHandler::clearUnderrun()
|
||||||
{
|
{
|
||||||
isUnderrun = false;
|
isUnderrun = false;
|
||||||
underTimer->stop();
|
underTimer->stop();
|
||||||
|
if (!setup.isinput) {
|
||||||
|
qDebug(logAudio()) << "clearUnderrun() " << "Buffer size" << audioOutput->bufferSize() << "Bytes free" << audioOutput->bytesFree();
|
||||||
|
audioOutput->resume();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -12,6 +12,7 @@
|
||||||
#include <QTime>
|
#include <QTime>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
/* QT Audio Headers */
|
/* QT Audio Headers */
|
||||||
#include <QAudioOutput>
|
#include <QAudioOutput>
|
||||||
|
@ -111,7 +112,7 @@ private:
|
||||||
bool isInitialized=false;
|
bool isInitialized=false;
|
||||||
bool isReady = false;
|
bool isReady = false;
|
||||||
bool audioBuffered = false;
|
bool audioBuffered = false;
|
||||||
|
QTime lastReceived;
|
||||||
QAudioOutput* audioOutput=Q_NULLPTR;
|
QAudioOutput* audioOutput=Q_NULLPTR;
|
||||||
QAudioInput* audioInput=Q_NULLPTR;
|
QAudioInput* audioInput=Q_NULLPTR;
|
||||||
QIODevice* audioDevice=Q_NULLPTR;
|
QIODevice* audioDevice=Q_NULLPTR;
|
||||||
|
@ -137,7 +138,7 @@ private:
|
||||||
audioPacket tempBuf;
|
audioPacket tempBuf;
|
||||||
quint16 currentLatency;
|
quint16 currentLatency;
|
||||||
float amplitude;
|
float amplitude;
|
||||||
qreal volume=1.0;
|
float volume=1.0;
|
||||||
|
|
||||||
audioSetup setup;
|
audioSetup setup;
|
||||||
|
|
||||||
|
@ -149,6 +150,12 @@ private:
|
||||||
|
|
||||||
// Various audio handling functions declared inline
|
// Various audio handling functions declared inline
|
||||||
|
|
||||||
|
typedef Eigen::Matrix<quint8, Eigen::Dynamic, 1> VectorXuint8;
|
||||||
|
typedef Eigen::Matrix<qint8, Eigen::Dynamic, 1> VectorXint8;
|
||||||
|
typedef Eigen::Matrix<qint16, Eigen::Dynamic, 1> VectorXint16;
|
||||||
|
typedef Eigen::Matrix<qint32, Eigen::Dynamic, 1> VectorXint32;
|
||||||
|
|
||||||
|
/*
|
||||||
static inline qint64 getAudioSize(qint64 timeInMs, const QAudioFormat& format)
|
static inline qint64 getAudioSize(qint64 timeInMs, const QAudioFormat& format)
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
|
@ -169,11 +176,6 @@ static inline qint64 getAudioDuration(qint64 bytes, const QAudioFormat& format)
|
||||||
return qint64(qFloor(bytes / (format.channelCount() * (format.sampleSize() / 8) * format.sampleRate() / qreal(1000))));
|
return qint64(qFloor(bytes / (format.channelCount() * (format.sampleSize() / 8) * format.sampleRate() / qreal(1000))));
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef Eigen::Matrix<quint8, Eigen::Dynamic, 1> VectorXuint8;
|
|
||||||
typedef Eigen::Matrix<qint8, Eigen::Dynamic, 1> VectorXint8;
|
|
||||||
typedef Eigen::Matrix<qint16, Eigen::Dynamic, 1> VectorXint16;
|
|
||||||
typedef Eigen::Matrix<qint32, Eigen::Dynamic, 1> VectorXint32;
|
|
||||||
|
|
||||||
static inline QByteArray samplesToInt(const QByteArray& data, const QAudioFormat& supported_format)
|
static inline QByteArray samplesToInt(const QByteArray& data, const QAudioFormat& supported_format)
|
||||||
{
|
{
|
||||||
QByteArray input = data;
|
QByteArray input = data;
|
||||||
|
@ -347,4 +349,5 @@ static inline QByteArray samplesToFloat(const QByteArray& data, const QAudioForm
|
||||||
|
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
#endif // AUDIOHANDLER_H
|
#endif // AUDIOHANDLER_H
|
||||||
|
|
|
@ -202,7 +202,7 @@ void udpHandler::dataReceived()
|
||||||
}
|
}
|
||||||
|
|
||||||
QString tempLatency;
|
QString tempLatency;
|
||||||
if (status.rxLatency > status.rxCurrentLatency && !status.rxUnderrun)
|
if (status.rxLatency * 1.3 > (status.rxCurrentLatency) && !status.rxUnderrun)
|
||||||
{
|
{
|
||||||
tempLatency = QString("%1 ms").arg(status.rxCurrentLatency,3);
|
tempLatency = QString("%1 ms").arg(status.rxCurrentLatency,3);
|
||||||
}
|
}
|
||||||
|
|
Ładowanie…
Reference in New Issue