Merge branch 'wfserver' of https://gitlab.com/eliggett/wfview into wfserver

merge-requests/9/merge
Phil Taylor 2022-05-08 18:45:35 +01:00
commit 066c1b58ac
3 zmienionych plików z 234 dodań i 223 usunięć

Wyświetl plik

@ -82,224 +82,225 @@ audioConverter::~audioConverter()
bool audioConverter::convert(audioPacket audio) bool audioConverter::convert(audioPacket audio)
{ {
if (audio.data.size() == 0) // If inFormat and outFormat are identical, just emit the data back.
if (audio.data.size() != 0 && inFormat != outFormat)
{ {
return false;
}
if (inFormat.codec() == "audio/opus") if (inFormat.codec() == "audio/opus")
{ {
unsigned char* in = (unsigned char*)audio.data.data(); unsigned char* in = (unsigned char*)audio.data.data();
//Decode the frame. //Decode the frame.
int nSamples = opus_packet_get_nb_samples(in, audio.data.size(), inFormat.sampleRate()); int nSamples = opus_packet_get_nb_samples(in, audio.data.size(), inFormat.sampleRate());
if (nSamples == -1) { if (nSamples == -1) {
// No opus data yet? // No opus data yet?
return false; return false;
} }
QByteArray outPacket(nSamples * sizeof(float) * inFormat.channelCount(), (char)0xff); // Preset the output buffer size. QByteArray outPacket(nSamples * sizeof(float) * inFormat.channelCount(), (char)0xff); // Preset the output buffer size.
float* out = (float*)outPacket.data(); float* out = (float*)outPacket.data();
//if (audio.seq > lastAudioSequence + 1) { //if (audio.seq > lastAudioSequence + 1) {
// nSamples = opus_decode_float(opusDecoder, Q_NULLPTR, 0, out, nSamples, 1); // nSamples = opus_decode_float(opusDecoder, Q_NULLPTR, 0, out, nSamples, 1);
//} //}
//else { //else {
nSamples = opus_decode_float(opusDecoder, in, audio.data.size(), out, nSamples, 0); nSamples = opus_decode_float(opusDecoder, in, audio.data.size(), out, nSamples, 0);
//} //}
//lastAudioSequence = audio.seq; //lastAudioSequence = audio.seq;
audio.data.clear(); audio.data.clear();
audio.data = outPacket; // Replace incoming data with converted. audio.data = outPacket; // Replace incoming data with converted.
} }
else if (inFormat.codec() == "audio/PCMU") else if (inFormat.codec() == "audio/PCMU")
{ {
// Current packet is "technically" 8bit so need to create a new buffer that is 16bit // Current packet is "technically" 8bit so need to create a new buffer that is 16bit
QByteArray outPacket((int)audio.data.length() * 2, (char)0xff); QByteArray outPacket((int)audio.data.length() * 2, (char)0xff);
qint16* out = (qint16*)outPacket.data(); qint16* out = (qint16*)outPacket.data();
for (int f = 0; f < audio.data.length(); f++) for (int f = 0; f < audio.data.length(); f++)
{ {
*out++ = ulaw_decode[(quint8)audio.data[f]]; *out++ = ulaw_decode[(quint8)audio.data[f]];
} }
audio.data.clear(); audio.data.clear();
audio.data = outPacket; // Replace incoming data with converted. audio.data = outPacket; // Replace incoming data with converted.
// Make sure that sample size/type is set correctly // Make sure that sample size/type is set correctly
} }
Eigen::VectorXf samplesF;
if (inFormat.sampleType() == QAudioFormat::SignedInt && inFormat.sampleSize() == 32) Eigen::VectorXf samplesF;
{
Eigen::Ref<VectorXint32> samplesI = Eigen::Map<VectorXint32>(reinterpret_cast<qint32*>(audio.data.data()), audio.data.size() / int(sizeof(qint32))); if (inFormat.sampleType() == QAudioFormat::SignedInt && inFormat.sampleSize() == 32)
samplesF = samplesI.cast<float>() / float(std::numeric_limits<qint32>::max()); {
} Eigen::Ref<VectorXint32> samplesI = Eigen::Map<VectorXint32>(reinterpret_cast<qint32*>(audio.data.data()), audio.data.size() / int(sizeof(qint32)));
else if (inFormat.sampleType() == QAudioFormat::SignedInt && inFormat.sampleSize() == 16) samplesF = samplesI.cast<float>() / float(std::numeric_limits<qint32>::max());
{ }
Eigen::Ref<VectorXint16> samplesI = Eigen::Map<VectorXint16>(reinterpret_cast<qint16*>(audio.data.data()), audio.data.size() / int(sizeof(qint16))); else if (inFormat.sampleType() == QAudioFormat::SignedInt && inFormat.sampleSize() == 16)
samplesF = samplesI.cast<float>() / float(std::numeric_limits<qint16>::max()); {
} Eigen::Ref<VectorXint16> samplesI = Eigen::Map<VectorXint16>(reinterpret_cast<qint16*>(audio.data.data()), audio.data.size() / int(sizeof(qint16)));
else if (inFormat.sampleType() == QAudioFormat::SignedInt && inFormat.sampleSize() == 8) samplesF = samplesI.cast<float>() / float(std::numeric_limits<qint16>::max());
{ }
Eigen::Ref<VectorXint8> samplesI = Eigen::Map<VectorXint8>(reinterpret_cast<qint8*>(audio.data.data()), audio.data.size() / int(sizeof(qint8))); else if (inFormat.sampleType() == QAudioFormat::SignedInt && inFormat.sampleSize() == 8)
samplesF = samplesI.cast<float>() / float(std::numeric_limits<qint8>::max());; {
} Eigen::Ref<VectorXint8> samplesI = Eigen::Map<VectorXint8>(reinterpret_cast<qint8*>(audio.data.data()), audio.data.size() / int(sizeof(qint8)));
else if (inFormat.sampleType() == QAudioFormat::UnSignedInt && inFormat.sampleSize() == 8) samplesF = samplesI.cast<float>() / float(std::numeric_limits<qint8>::max());;
{ }
Eigen::Ref<VectorXuint8> samplesI = Eigen::Map<VectorXuint8>(reinterpret_cast<quint8*>(audio.data.data()), audio.data.size() / int(sizeof(quint8))); else if (inFormat.sampleType() == QAudioFormat::UnSignedInt && inFormat.sampleSize() == 8)
samplesF = samplesI.cast<float>() / float(std::numeric_limits<quint8>::max());; {
} Eigen::Ref<VectorXuint8> samplesI = Eigen::Map<VectorXuint8>(reinterpret_cast<quint8*>(audio.data.data()), audio.data.size() / int(sizeof(quint8)));
else if (inFormat.sampleType() == QAudioFormat::Float) { samplesF = samplesI.cast<float>() / float(std::numeric_limits<quint8>::max());;
samplesF = Eigen::Map<Eigen::VectorXf>(reinterpret_cast<float*>(audio.data.data()), audio.data.size() / int(sizeof(float))); }
} else if (inFormat.sampleType() == QAudioFormat::Float) {
else samplesF = Eigen::Map<Eigen::VectorXf>(reinterpret_cast<float*>(audio.data.data()), audio.data.size() / int(sizeof(float)));
{ }
qInfo(logAudio()) << "Unsupported Sample Type:" << inFormat.sampleType() << "Size:" << inFormat.sampleSize(); else
} {
qInfo(logAudio()) << "Unsupported Sample Type:" << inFormat.sampleType() << "Size:" << inFormat.sampleSize();
}
audio.amplitude = samplesF.array().abs().maxCoeff(); audio.amplitude = samplesF.array().abs().maxCoeff();
// Set the volume // Set the volume
samplesF *= audio.volume; samplesF *= audio.volume;
/* /*
samplesF is now an Eigen Vector of the current samples in float format samplesF is now an Eigen Vector of the current samples in float format
The next step is to convert to the correct number of channels in outFormat.channelCount() The next step is to convert to the correct number of channels in outFormat.channelCount()
*/ */
if (inFormat.channelCount() == 2 && outFormat.channelCount() == 1) { if (inFormat.channelCount() == 2 && outFormat.channelCount() == 1) {
// If we need to drop one of the audio channels, do it now // If we need to drop one of the audio channels, do it now
Eigen::VectorXf samplesTemp(samplesF.size() / 2); Eigen::VectorXf samplesTemp(samplesF.size() / 2);
samplesTemp = Eigen::Map<Eigen::VectorXf, 0, Eigen::InnerStride<2> >(samplesF.data(), samplesF.size() / 2); samplesTemp = Eigen::Map<Eigen::VectorXf, 0, Eigen::InnerStride<2> >(samplesF.data(), samplesF.size() / 2);
samplesF = samplesTemp; samplesF = samplesTemp;
} }
else if (inFormat.channelCount() == 1 && outFormat.channelCount() == 2) { else if (inFormat.channelCount() == 1 && outFormat.channelCount() == 2) {
// Convert mono to stereo if required // Convert mono to stereo if required
Eigen::VectorXf samplesTemp(samplesF.size() * 2); Eigen::VectorXf samplesTemp(samplesF.size() * 2);
Eigen::Map<Eigen::VectorXf, 0, Eigen::InnerStride<2> >(samplesTemp.data(), samplesF.size()) = samplesF; Eigen::Map<Eigen::VectorXf, 0, Eigen::InnerStride<2> >(samplesTemp.data(), samplesF.size()) = samplesF;
Eigen::Map<Eigen::VectorXf, 0, Eigen::InnerStride<2> >(samplesTemp.data() + 1, samplesF.size()) = samplesF; Eigen::Map<Eigen::VectorXf, 0, Eigen::InnerStride<2> >(samplesTemp.data() + 1, samplesF.size()) = samplesF;
samplesF = samplesTemp; samplesF = samplesTemp;
} }
/* /*
Next step is to resample (if needed) Next step is to resample (if needed)
*/ */
if (resampler != Q_NULLPTR && resampleRatio != 1.0) if (resampler != Q_NULLPTR && resampleRatio != 1.0)
{ {
quint32 outFrames = ((samplesF.size() / outFormat.channelCount()) * resampleRatio); quint32 outFrames = ((samplesF.size() / outFormat.channelCount()) * resampleRatio);
quint32 inFrames = (samplesF.size() / outFormat.channelCount()); quint32 inFrames = (samplesF.size() / outFormat.channelCount());
QByteArray outPacket(outFrames * outFormat.channelCount() * sizeof(float), (char)0xff); // Preset the output buffer size. QByteArray outPacket(outFrames * outFormat.channelCount() * sizeof(float), (char)0xff); // Preset the output buffer size.
const float* in = (float*)samplesF.data(); const float* in = (float*)samplesF.data();
float* out = (float*)outPacket.data(); float* out = (float*)outPacket.data();
int err = 0; int err = 0;
if (outFormat.channelCount() == 1) { if (outFormat.channelCount() == 1) {
err = wf_resampler_process_float(resampler, 0, in, &inFrames, out, &outFrames); err = wf_resampler_process_float(resampler, 0, in, &inFrames, out, &outFrames);
} }
else { else {
err = wf_resampler_process_interleaved_float(resampler, in, &inFrames, out, &outFrames); err = wf_resampler_process_interleaved_float(resampler, in, &inFrames, out, &outFrames);
} }
if (err) { if (err) {
qInfo(logAudioConverter()) << "Resampler error " << err << " inFrames:" << inFrames << " outFrames:" << outFrames; qInfo(logAudioConverter()) << "Resampler error " << err << " inFrames:" << inFrames << " outFrames:" << outFrames;
} }
samplesF = Eigen::Map<Eigen::VectorXf>(reinterpret_cast<float*>(outPacket.data()), outPacket.size() / int(sizeof(float))); samplesF = Eigen::Map<Eigen::VectorXf>(reinterpret_cast<float*>(outPacket.data()), outPacket.size() / int(sizeof(float)));
} }
/* /*
If output is Opus so encode it now, don't do any more conversion on the output of Opus. If output is Opus so encode it now, don't do any more conversion on the output of Opus.
*/ */
if (outFormat.codec() == "audio/opus") if (outFormat.codec() == "audio/opus")
{ {
float* in = (float*)samplesF.data(); float* in = (float*)samplesF.data();
QByteArray outPacket(1275, (char)0xff); // Preset the output buffer size to MAXIMUM possible Opus frame size QByteArray outPacket(1275, (char)0xff); // Preset the output buffer size to MAXIMUM possible Opus frame size
unsigned char* out = (unsigned char*)outPacket.data(); unsigned char* out = (unsigned char*)outPacket.data();
int nbBytes = opus_encode_float(opusEncoder, in, (samplesF.size() / outFormat.channelCount()), out, outPacket.length()); int nbBytes = opus_encode_float(opusEncoder, in, (samplesF.size() / outFormat.channelCount()), out, outPacket.length());
if (nbBytes < 0) if (nbBytes < 0)
{ {
qInfo(logAudioConverter()) << "Opus encode failed:" << opus_strerror(nbBytes) << "Num Samples:" << samplesF.size(); qInfo(logAudioConverter()) << "Opus encode failed:" << opus_strerror(nbBytes) << "Num Samples:" << samplesF.size();
return false; return false;
} }
else { else {
outPacket.resize(nbBytes); outPacket.resize(nbBytes);
audio.data.clear(); audio.data.clear();
audio.data = outPacket; // Copy output packet back to input buffer. audio.data = outPacket; // Copy output packet back to input buffer.
//samplesF = Eigen::Map<Eigen::VectorXf>(reinterpret_cast<float*>(outPacket.data()), outPacket.size() / int(sizeof(float))); //samplesF = Eigen::Map<Eigen::VectorXf>(reinterpret_cast<float*>(outPacket.data()), outPacket.size() / int(sizeof(float)));
} }
} }
else { else {
/* /*
Now convert back into the output format required Now convert back into the output format required
*/ */
audio.data.clear(); audio.data.clear();
if (outFormat.sampleType() == QAudioFormat::UnSignedInt && outFormat.sampleSize() == 8) if (outFormat.sampleType() == QAudioFormat::UnSignedInt && outFormat.sampleSize() == 8)
{ {
Eigen::VectorXf samplesITemp = samplesF * float(std::numeric_limits<quint8>::max()); Eigen::VectorXf samplesITemp = samplesF * float(std::numeric_limits<quint8>::max());
VectorXuint8 samplesI = samplesITemp.cast<quint8>(); VectorXuint8 samplesI = samplesITemp.cast<quint8>();
audio.data = QByteArray(reinterpret_cast<char*>(samplesI.data()), int(samplesI.size()) * int(sizeof(quint8))); audio.data = QByteArray(reinterpret_cast<char*>(samplesI.data()), int(samplesI.size()) * int(sizeof(quint8)));
} }
if (outFormat.sampleType() == QAudioFormat::SignedInt && outFormat.sampleSize() == 8) if (outFormat.sampleType() == QAudioFormat::SignedInt && outFormat.sampleSize() == 8)
{ {
Eigen::VectorXf samplesITemp = samplesF * float(std::numeric_limits<qint8>::max()); Eigen::VectorXf samplesITemp = samplesF * float(std::numeric_limits<qint8>::max());
VectorXint8 samplesI = samplesITemp.cast<qint8>(); VectorXint8 samplesI = samplesITemp.cast<qint8>();
audio.data = QByteArray(reinterpret_cast<char*>(samplesI.data()), int(samplesI.size()) * int(sizeof(qint8))); audio.data = QByteArray(reinterpret_cast<char*>(samplesI.data()), int(samplesI.size()) * int(sizeof(qint8)));
} }
if (outFormat.sampleType() == QAudioFormat::SignedInt && outFormat.sampleSize() == 16) if (outFormat.sampleType() == QAudioFormat::SignedInt && outFormat.sampleSize() == 16)
{ {
Eigen::VectorXf samplesITemp = samplesF * float(std::numeric_limits<qint16>::max()); Eigen::VectorXf samplesITemp = samplesF * float(std::numeric_limits<qint16>::max());
VectorXint16 samplesI = samplesITemp.cast<qint16>(); VectorXint16 samplesI = samplesITemp.cast<qint16>();
audio.data = QByteArray(reinterpret_cast<char*>(samplesI.data()), int(samplesI.size()) * int(sizeof(qint16))); audio.data = QByteArray(reinterpret_cast<char*>(samplesI.data()), int(samplesI.size()) * int(sizeof(qint16)));
} }
else if (outFormat.sampleType() == QAudioFormat::SignedInt && outFormat.sampleSize() == 32) else if (outFormat.sampleType() == QAudioFormat::SignedInt && outFormat.sampleSize() == 32)
{ {
Eigen::VectorXf samplesITemp = samplesF * float(std::numeric_limits<qint32>::max()); Eigen::VectorXf samplesITemp = samplesF * float(std::numeric_limits<qint32>::max());
VectorXint32 samplesI = samplesITemp.cast<qint32>(); VectorXint32 samplesI = samplesITemp.cast<qint32>();
audio.data = QByteArray(reinterpret_cast<char*>(samplesI.data()), int(samplesI.size()) * int(sizeof(qint32))); audio.data = QByteArray(reinterpret_cast<char*>(samplesI.data()), int(samplesI.size()) * int(sizeof(qint32)));
} }
else if (outFormat.sampleType() == QAudioFormat::Float) else if (outFormat.sampleType() == QAudioFormat::Float)
{ {
audio.data = QByteArray(reinterpret_cast<char*>(samplesF.data()), int(samplesF.size()) * int(sizeof(float))); audio.data = QByteArray(reinterpret_cast<char*>(samplesF.data()), int(samplesF.size()) * int(sizeof(float)));
} }
else { else {
qInfo(logAudio()) << "Unsupported Sample Type:" << outFormat.sampleType(); qInfo(logAudio()) << "Unsupported Sample Type:" << outFormat.sampleType();
} }
/* /*
As we currently don't have a float based uLaw encoder, this must be done As we currently don't have a float based uLaw encoder, this must be done
after all other conversion has taken place. after all other conversion has taken place.
*/ */
if (outFormat.codec() == "audio/PCMU") if (outFormat.codec() == "audio/PCMU")
{ {
QByteArray outPacket((int)audio.data.length() / 2, (char)0xff); QByteArray outPacket((int)audio.data.length() / 2, (char)0xff);
qint16* in = (qint16*)audio.data.data(); qint16* in = (qint16*)audio.data.data();
for (int f = 0; f < outPacket.length(); f++) for (int f = 0; f < outPacket.length(); f++)
{ {
qint16 sample = *in++; qint16 sample = *in++;
int sign = (sample >> 8) & 0x80; int sign = (sample >> 8) & 0x80;
if (sign) if (sign)
sample = (short)-sample; sample = (short)-sample;
if (sample > cClip) if (sample > cClip)
sample = cClip; sample = cClip;
sample = (short)(sample + cBias); sample = (short)(sample + cBias);
int exponent = (int)MuLawCompressTable[(sample >> 7) & 0xFF]; int exponent = (int)MuLawCompressTable[(sample >> 7) & 0xFF];
int mantissa = (sample >> (exponent + 3)) & 0x0F; int mantissa = (sample >> (exponent + 3)) & 0x0F;
int compressedByte = ~(sign | (exponent << 4) | mantissa); int compressedByte = ~(sign | (exponent << 4) | mantissa);
outPacket[f] = (quint8)compressedByte; outPacket[f] = (quint8)compressedByte;
} }
audio.data.clear(); audio.data.clear();
audio.data = outPacket; // Copy output packet back to input buffer. audio.data = outPacket; // Copy output packet back to input buffer.
}
}
}
}
}
emit converted(audio); emit converted(audio);
return true; return true;
} }

Wyświetl plik

@ -85,6 +85,7 @@ static inline QAudioFormat toQAudioFormat(quint8 codec, quint32 sampleRate)
format.setSampleType(QAudioFormat::UnSignedInt); format.setSampleType(QAudioFormat::UnSignedInt);
format.setByteOrder(QAudioFormat::LittleEndian); format.setByteOrder(QAudioFormat::LittleEndian);
format.setCodec("audio/pcm"); format.setCodec("audio/pcm");
format.setSampleRate(sampleRate);
if (codec == 0x01 || codec == 0x20) { if (codec == 0x01 || codec == 0x20) {
/* Set sample to be what is expected by the encoder and the output of the decoder */ /* Set sample to be what is expected by the encoder and the output of the decoder */
@ -108,8 +109,7 @@ static inline QAudioFormat toQAudioFormat(quint8 codec, quint32 sampleRate)
format.setCodec("audio/opus"); format.setCodec("audio/opus");
} }
format.setSampleRate(sampleRate);
return format; return format;
} }
#endif #endif

Wyświetl plik

@ -209,8 +209,8 @@ void audioHandler::setVolume(unsigned char volume)
void audioHandler::incomingAudio(audioPacket packet) void audioHandler::incomingAudio(audioPacket packet)
{ {
//QTime startProcessing = QTime::currentTime();
if (audioDevice != Q_NULLPTR) { if (audioDevice != Q_NULLPTR && packet.data.size() > 0) {
packet.volume = volume; packet.volume = volume;
emit sendToConverter(packet); emit sendToConverter(packet);
@ -221,32 +221,35 @@ void audioHandler::incomingAudio(audioPacket packet)
void audioHandler::convertedOutput(audioPacket packet) { void audioHandler::convertedOutput(audioPacket packet) {
currentLatency = packet.time.msecsTo(QTime::currentTime()) + (outFormat.durationForBytes(audioOutput->bufferSize() - audioOutput->bytesFree()) / 1000); if (packet.data.size() > 0 ) {
if (audioDevice != Q_NULLPTR) {
audioDevice->write(packet.data);
if (lastReceived.msecsTo(QTime::currentTime()) > 100) {
qDebug(logAudio()) << (setup.isinput ? "Input" : "Output") << "Time since last audio packet" << lastReceived.msecsTo(QTime::currentTime()) << "Expected around" << setup.blockSize;
}
lastReceived = QTime::currentTime();
}
/*if ((packet.seq > lastSentSeq + 1) && (setup.codec == 0x40 || setup.codec == 0x80)) {
qDebug(logAudio()) << (setup.isinput ? "Input" : "Output") << "Attempting FEC on packet" << packet.seq << "as last is" << lastSentSeq;
lastSentSeq = packet.seq;
incomingAudio(packet); // Call myself again to run the packet a second time (FEC)
}
*/
lastSentSeq = packet.seq;
emit haveLevels(getAmplitude(), setup.latency, currentLatency, isUnderrun);
amplitude = packet.amplitude; currentLatency = packet.time.msecsTo(QTime::currentTime()) + (outFormat.durationForBytes(audioOutput->bufferSize() - audioOutput->bytesFree()) / 1000);
if (audioDevice != Q_NULLPTR) {
audioDevice->write(packet.data);
if (lastReceived.msecsTo(QTime::currentTime()) > 100) {
qDebug(logAudio()) << (setup.isinput ? "Input" : "Output") << "Time since last audio packet" << lastReceived.msecsTo(QTime::currentTime()) << "Expected around" << setup.blockSize;
}
lastReceived = QTime::currentTime();
}
/*if ((packet.seq > lastSentSeq + 1) && (setup.codec == 0x40 || setup.codec == 0x80)) {
qDebug(logAudio()) << (setup.isinput ? "Input" : "Output") << "Attempting FEC on packet" << packet.seq << "as last is" << lastSentSeq;
lastSentSeq = packet.seq;
incomingAudio(packet); // Call myself again to run the packet a second time (FEC)
}
*/
lastSentSeq = packet.seq;
emit haveLevels(getAmplitude(), setup.latency, currentLatency, isUnderrun);
amplitude = packet.amplitude;
}
} }
void audioHandler::getNextAudioChunk() void audioHandler::getNextAudioChunk()
{ {
tempBuf.data.append(audioDevice->readAll()); if (audioDevice) {
tempBuf.data.append(audioDevice->readAll());
while (tempBuf.data.length() >= outFormat.bytesForDuration(setup.blockSize * 1000)) { }
if (tempBuf.data.length() >= outFormat.bytesForDuration(setup.blockSize * 1000)) {
audioPacket packet; audioPacket packet;
packet.time = QTime::currentTime(); packet.time = QTime::currentTime();
packet.sent = 0; packet.sent = 0;
@ -259,20 +262,27 @@ void audioHandler::getNextAudioChunk()
emit sendToConverter(packet); emit sendToConverter(packet);
} }
return;
/* If there is still enough data in the buffer, call myself again in 20ms */
if (tempBuf.data.length() >= outFormat.bytesForDuration(setup.blockSize * 1000)) {
QTimer::singleShot(setup.blockSize, this, &audioHandler::getNextAudioChunk);
}
return;
} }
void audioHandler::convertedInput(audioPacket audio) void audioHandler::convertedInput(audioPacket audio)
{ {
emit haveAudioData(audio); if (audio.data.size() > 0) {
if (lastReceived.msecsTo(QTime::currentTime()) > 100) { emit haveAudioData(audio);
qDebug(logAudio()) << (setup.isinput ? "Input" : "Output") << "Time since last audio packet" << lastReceived.msecsTo(QTime::currentTime()) << "Expected around" << setup.blockSize ; if (lastReceived.msecsTo(QTime::currentTime()) > 100) {
} qDebug(logAudio()) << (setup.isinput ? "Input" : "Output") << "Time since last audio packet" << lastReceived.msecsTo(QTime::currentTime()) << "Expected around" << setup.blockSize ;
lastReceived = QTime::currentTime(); }
amplitude = audio.amplitude; lastReceived = QTime::currentTime();
emit haveLevels(getAmplitude(), setup.latency, currentLatency, isUnderrun); amplitude = audio.amplitude;
emit haveLevels(getAmplitude(), setup.latency, currentLatency, isUnderrun);
}
} }
void audioHandler::changeLatency(const quint16 newSize) void audioHandler::changeLatency(const quint16 newSize)