kopia lustrzana https://gitlab.com/eliggett/wfview
Create rx audio packets with timestamp
Lots of other changes but if this works OK, I will update tx audio to use the same system.merge-requests/2/head
rodzic
6d8d1df45e
commit
27eb855adb
148
audiohandler.cpp
148
audiohandler.cpp
|
@ -735,7 +735,7 @@ audioHandler::audioHandler(QObject* parent) :
|
|||
audioOutput(Q_NULLPTR),
|
||||
audioInput(Q_NULLPTR),
|
||||
isUlaw(false),
|
||||
bufferSize(0),
|
||||
latency(0),
|
||||
isInput(0),
|
||||
volume(1.0f)
|
||||
{
|
||||
|
@ -752,7 +752,7 @@ audioHandler::~audioHandler()
|
|||
}
|
||||
}
|
||||
|
||||
bool audioHandler::init(const quint8 bits, const quint8 channels, const quint16 samplerate, const quint16 buffer, const bool ulaw, const bool isinput)
|
||||
bool audioHandler::init(const quint8 bits, const quint8 channels, const quint16 samplerate, const quint16 latency, const bool ulaw, const bool isinput)
|
||||
{
|
||||
if (isInitialized) {
|
||||
return false;
|
||||
|
@ -765,8 +765,8 @@ bool audioHandler::init(const quint8 bits, const quint8 channels, const quint16
|
|||
format.setByteOrder(QAudioFormat::LittleEndian);
|
||||
format.setSampleType(QAudioFormat::SignedInt);
|
||||
|
||||
this->bufferSize = buffer;
|
||||
this->isUlaw = ulaw;
|
||||
this->latency = latency;
|
||||
this->isUlaw = ulaw;
|
||||
this->isInput = isinput;
|
||||
this->radioSampleBits = bits;
|
||||
this->radioSampleRate = samplerate;
|
||||
|
@ -831,7 +831,7 @@ void audioHandler::reinit()
|
|||
if (audioInput != Q_NULLPTR)
|
||||
delete audioInput;
|
||||
audioInput = new QAudioInput(deviceInfo, format, this);
|
||||
//audioInput->setBufferSize(audioBuffer);
|
||||
//audioInput->setLatency(audioBuffer);
|
||||
//audioInput->setNotifyInterval(20);
|
||||
|
||||
connect(audioInput, SIGNAL(notify()), SLOT(notified()));
|
||||
|
@ -844,7 +844,7 @@ void audioHandler::reinit()
|
|||
delete audioOutput;
|
||||
audioOutput = Q_NULLPTR;
|
||||
audioOutput = new QAudioOutput(deviceInfo, format, this);
|
||||
//audioOutput->setBufferSize(audioBuffer);
|
||||
//audioOutput->setLatency(audioBuffer);
|
||||
connect(audioOutput, SIGNAL(notify()), SLOT(notified()));
|
||||
connect(audioOutput, SIGNAL(stateChanged(QAudio::State)), SLOT(stateChanged(QAudio::State)));
|
||||
}
|
||||
|
@ -899,8 +899,8 @@ void audioHandler::stop()
|
|||
// Stop audio output
|
||||
audioOutput->stop();
|
||||
QByteArray ret;
|
||||
|
||||
buffer.clear();
|
||||
audioBuffer.clear();
|
||||
//buffer.clear();
|
||||
this->close();
|
||||
}
|
||||
|
||||
|
@ -915,47 +915,92 @@ void audioHandler::stop()
|
|||
qint64 audioHandler::readData(char* data, qint64 maxlen)
|
||||
{
|
||||
// Calculate output length, always full samples
|
||||
int outlen = 0;
|
||||
if (radioSampleBits == 8)
|
||||
{
|
||||
// Input buffer is 8bit and output buffer is 16bit
|
||||
outlen = qMin(buffer.length(), (int)maxlen / 2);
|
||||
for (int f = 0; f < outlen; f++)
|
||||
{
|
||||
if (isUlaw)
|
||||
qToLittleEndian<qint16>(ulaw_decode[(quint8)buffer.at(f)], data + (f * 2));
|
||||
else
|
||||
qToLittleEndian<qint16>((qint16)(buffer[f] << 8) - 32640, data + (f * 2));
|
||||
}
|
||||
QMutexLocker locker(&mutex);
|
||||
buffer.remove(0, outlen);
|
||||
outlen = outlen * 2;
|
||||
}
|
||||
else if (radioSampleBits == 16) {
|
||||
// Just copy it
|
||||
outlen = qMin(buffer.length(), (int)maxlen);
|
||||
if (outlen % 2 != 0) {
|
||||
outlen += 1; // Not sure if this is necessary as we should always have an even number!
|
||||
}
|
||||
memcpy(data, buffer.data(), outlen);
|
||||
QMutexLocker locker(&mutex);
|
||||
buffer.remove(0, outlen);
|
||||
}
|
||||
else {
|
||||
qDebug(logAudio()) << "Sample bits MUST be 8 or 16 - got: " << radioSampleBits; // Should never happen?
|
||||
}
|
||||
return outlen;
|
||||
int sentlen = 0;
|
||||
|
||||
// Get next packet from buffer.
|
||||
if (!audioBuffer.isEmpty())
|
||||
{
|
||||
|
||||
// Sort the buffer by seq number.
|
||||
std::sort(audioBuffer.begin(), audioBuffer.end(),
|
||||
[](const AUDIOPACKET& a, const AUDIOPACKET& b) -> bool
|
||||
{
|
||||
return a.seq < b.seq;
|
||||
});
|
||||
|
||||
// Output buffer is ALWAYS 16 bit.
|
||||
int divisor = 16 / radioSampleBits;
|
||||
|
||||
auto packet = audioBuffer.begin();
|
||||
while (packet != audioBuffer.end() && sentlen<maxlen)
|
||||
{
|
||||
if (packet->time.msecsTo(QTime::currentTime()) > latency) {
|
||||
qDebug(logAudio()) << "Packet " << hex << packet->seq << "is too late, deleting" << dec << packet->time.msecsTo(QTime::currentTime()) << "ms";
|
||||
QMutexLocker locker(&mutex);
|
||||
packet=audioBuffer.erase(packet); // returns next packet
|
||||
}
|
||||
else
|
||||
{
|
||||
// Will this packet fit in the current buffer?
|
||||
int send = qMin((int)((maxlen/divisor) - (sentlen/divisor)), packet->data.length() - packet->sent);
|
||||
|
||||
if (divisor == 2)
|
||||
{
|
||||
// Input buffer is 8bit and output buffer is 16bit
|
||||
for (int f = 0; f < send; f++)
|
||||
{
|
||||
if (isUlaw)
|
||||
qToLittleEndian<qint16>(ulaw_decode[(quint8)packet->data[f+packet->sent]], data + (f * 2 + sentlen));
|
||||
else
|
||||
qToLittleEndian<qint16>((qint16)(packet->data[f+packet->sent] << 8) - 32640, data + (f * 2 + sentlen));
|
||||
}
|
||||
sentlen = sentlen + (send*divisor);
|
||||
}
|
||||
else if (divisor == 1)
|
||||
{
|
||||
// 16 bit audio so just copy it in place.
|
||||
//qDebug(logAudio()) << "Adding packet to buffer:" << (*packet).seq << ": " << (*packet).data.length()-(*packet).sent;
|
||||
memcpy(data+sentlen, packet->data.constData()+packet->sent, send);
|
||||
sentlen = sentlen + (send*divisor);
|
||||
}
|
||||
else
|
||||
{
|
||||
//qDebug(logAudio()) << "Invalid number of bits in audio " << radioSampleBits;
|
||||
break;
|
||||
}
|
||||
|
||||
if (send == packet->data.length())
|
||||
{
|
||||
QMutexLocker locker(&mutex);
|
||||
packet = audioBuffer.erase(packet); // returns next packet
|
||||
if (maxlen - sentlen == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (send == 0)
|
||||
{
|
||||
// We have no more space or no packets so just break.
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We ended-up with a partial packet left so add it to the buffer and store where we left off.
|
||||
packet->sent = send;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//qDebug(logAudio()) << "Returning: " << sentlen << " max: " << maxlen;
|
||||
|
||||
return sentlen;
|
||||
}
|
||||
|
||||
qint64 audioHandler::writeData(const char* data, qint64 len)
|
||||
{
|
||||
|
||||
QMutexLocker locker(&mutex);
|
||||
if (buffer.length() > bufferSize * 4)
|
||||
{
|
||||
qWarning() << "writeData() Buffer overflow";
|
||||
buffer.clear(); // Will cause a click!
|
||||
}
|
||||
|
||||
if (isUlaw) {
|
||||
for (int f = 0; f < len / 2; f++)
|
||||
|
@ -1000,8 +1045,6 @@ void audioHandler::notified()
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void audioHandler::stateChanged(QAudio::State state)
|
||||
{
|
||||
if (state == QAudio::IdleState && audioOutput->error() == QAudio::UnderrunError) {
|
||||
|
@ -1016,12 +1059,11 @@ void audioHandler::stateChanged(QAudio::State state)
|
|||
|
||||
|
||||
|
||||
void audioHandler::incomingAudio(const QByteArray& data)
|
||||
void audioHandler::incomingAudio(const AUDIOPACKET data)
|
||||
{
|
||||
//qDebug(logAudio()) << "Got " << data.length() << " samples";
|
||||
if (audioOutput != Q_NULLPTR && audioOutput->state() != QAudio::StoppedState) {
|
||||
QMutexLocker locker(&mutex);
|
||||
buffer.append(data);
|
||||
audioBuffer.push_back(data);
|
||||
// Restart playback
|
||||
if (audioOutput->state() == QAudio::SuspendedState)
|
||||
{
|
||||
|
@ -1031,15 +1073,15 @@ void audioHandler::incomingAudio(const QByteArray& data)
|
|||
}
|
||||
}
|
||||
|
||||
void audioHandler::changeBufferSize(const quint16 newSize)
|
||||
void audioHandler::changeLatency(const quint16 newSize)
|
||||
{
|
||||
qDebug(logAudio()) << this->metaObject()->className() << ": Changing buffer size to: " << newSize << " from " << bufferSize;
|
||||
bufferSize = newSize;
|
||||
qDebug(logAudio()) << this->metaObject()->className() << ": Changing latency to: " << newSize << " from " << latency;
|
||||
latency = newSize;
|
||||
}
|
||||
|
||||
void audioHandler::getBufferSize()
|
||||
void audioHandler::getLatency()
|
||||
{
|
||||
emit sendBufferSize(audioOutput->bufferSize());
|
||||
emit sendLatency(latency);
|
||||
}
|
||||
|
||||
bool audioHandler::isChunkAvailable()
|
||||
|
|
|
@ -14,20 +14,31 @@
|
|||
#include <QIODevice>
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
#include <QTime>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
//#define BUFFER_SIZE (32*1024)
|
||||
|
||||
|
||||
struct AUDIOPACKET {
|
||||
quint16 seq;
|
||||
QTime time;
|
||||
quint16 sent;
|
||||
QByteArray data;
|
||||
};
|
||||
|
||||
|
||||
class audioHandler : public QIODevice
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
public:
|
||||
audioHandler(QObject* parent = 0);
|
||||
~audioHandler();
|
||||
|
||||
void getBufferSize();
|
||||
void getLatency();
|
||||
|
||||
bool setDevice(QAudioDeviceInfo deviceInfo);
|
||||
|
||||
|
@ -43,9 +54,9 @@ public:
|
|||
void getNextAudioChunk(QByteArray &data);
|
||||
bool isChunkAvailable();
|
||||
public slots:
|
||||
bool init(const quint8 bits, const quint8 channels, const quint16 samplerate, const quint16 bufferSize, const bool isulaw, const bool isinput);
|
||||
void incomingAudio(const QByteArray& data);
|
||||
void changeBufferSize(const quint16 newSize);
|
||||
bool init(const quint8 bits, const quint8 channels, const quint16 samplerate, const quint16 latency, const bool isulaw, const bool isinput);
|
||||
void incomingAudio(const AUDIOPACKET data);
|
||||
void changeLatency(const quint16 newSize);
|
||||
|
||||
private slots:
|
||||
void notified();
|
||||
|
@ -53,7 +64,7 @@ private slots:
|
|||
|
||||
signals:
|
||||
void audioMessage(QString message);
|
||||
void sendBufferSize(quint16 newSize);
|
||||
void sendLatency(quint16 newSize);
|
||||
void haveAudioData(const QByteArray& data);
|
||||
|
||||
|
||||
|
@ -67,7 +78,7 @@ private:
|
|||
QAudioOutput* audioOutput;
|
||||
QAudioInput* audioInput;
|
||||
bool isUlaw;
|
||||
int bufferSize;
|
||||
quint16 latency;
|
||||
bool isInput; // Used to determine whether input or output audio
|
||||
float volume;
|
||||
|
||||
|
@ -76,8 +87,7 @@ private:
|
|||
QAudioDeviceInfo deviceInfo;
|
||||
quint16 radioSampleRate;
|
||||
quint8 radioSampleBits;
|
||||
|
||||
|
||||
QVector<AUDIOPACKET> audioBuffer;
|
||||
};
|
||||
|
||||
#endif // AUDIOHANDLER_H
|
||||
|
|
|
@ -64,7 +64,7 @@ void rigCommander::commSetup(unsigned char rigCivAddr, QString rigSerialPort, qu
|
|||
}
|
||||
|
||||
void rigCommander::commSetup(unsigned char rigCivAddr, QString ip, quint16 cport, quint16 sport, quint16 aport,
|
||||
QString username, QString password, quint16 buffer, quint16 rxsample, quint8 rxcodec, quint16 txsample, quint8 txcodec)
|
||||
QString username, QString password, quint16 rxlatency, quint16 txlatency, quint16 rxsample, quint8 rxcodec, quint16 txsample, quint8 txcodec)
|
||||
{
|
||||
// construct
|
||||
// TODO: Bring this parameter and the comm port from the UI.
|
||||
|
@ -88,7 +88,7 @@ void rigCommander::commSetup(unsigned char rigCivAddr, QString ip, quint16 cport
|
|||
*/
|
||||
if (udp == Q_NULLPTR) {
|
||||
|
||||
udp = new udpHandler(ip, cport, sport, aport, username, password, buffer, rxsample, rxcodec, txsample, txcodec);
|
||||
udp = new udpHandler(ip, cport, sport, aport, username, password, rxlatency, txlatency, rxsample, rxcodec, txsample, txcodec);
|
||||
|
||||
udpHandlerThread = new QThread(this);
|
||||
|
||||
|
@ -107,7 +107,7 @@ void rigCommander::commSetup(unsigned char rigCivAddr, QString ip, quint16 cport
|
|||
|
||||
// data from the program to the comm port:
|
||||
connect(this, SIGNAL(dataForComm(QByteArray)), udp, SLOT(receiveDataFromUserToRig(QByteArray)));
|
||||
connect(this, SIGNAL(haveChangeBufferSize(quint16)), udp, SLOT(changeBufferSize(quint16)));
|
||||
connect(this, SIGNAL(haveChangeLatency(quint16)), udp, SLOT(changeLatency(quint16)));
|
||||
|
||||
// Connect for errors/alerts
|
||||
connect(udp, SIGNAL(haveNetworkError(QString, QString)), this, SLOT(handleSerialPortError(QString, QString)));
|
||||
|
@ -2480,9 +2480,9 @@ void rigCommander::getRigID()
|
|||
prepDataAndSend(payload);
|
||||
}
|
||||
|
||||
void rigCommander::changeBufferSize(const quint16 value)
|
||||
void rigCommander::changeLatency(const quint16 value)
|
||||
{
|
||||
emit haveChangeBufferSize(value);
|
||||
emit haveChangeLatency(value);
|
||||
}
|
||||
|
||||
void rigCommander::sayAll()
|
||||
|
|
|
@ -48,7 +48,7 @@ public slots:
|
|||
void process();
|
||||
void commSetup(unsigned char rigCivAddr, QString rigSerialPort, quint32 rigBaudRate);
|
||||
void commSetup(unsigned char rigCivAddr, QString ip, quint16 cport, quint16 sport, quint16 aport,
|
||||
QString username, QString password, quint16 buffer, quint16 rxsample, quint8 rxcodec,quint16 txsample, quint8 txcodec);
|
||||
QString username, QString password, quint16 rxlatency,quint16 txlatency, quint16 rxsample, quint8 rxcodec,quint16 txsample, quint8 txcodec);
|
||||
void closeComm();
|
||||
|
||||
void enableSpectOutput();
|
||||
|
@ -139,7 +139,7 @@ public slots:
|
|||
void handleNewData(const QByteArray &data);
|
||||
void handleSerialPortError(const QString port, const QString errorText);
|
||||
void handleStatusUpdate(const QString text);
|
||||
void changeBufferSize(const quint16 value);
|
||||
void changeLatency(const quint16 value);
|
||||
void sayFrequency();
|
||||
void sayMode();
|
||||
void sayAll();
|
||||
|
@ -197,7 +197,7 @@ signals:
|
|||
void finished();
|
||||
void havePTTStatus(bool pttOn);
|
||||
void haveATUStatus(unsigned char status);
|
||||
void haveChangeBufferSize(quint16 value);
|
||||
void haveChangeLatency(quint16 value);
|
||||
void haveDataForServer(QByteArray outData);
|
||||
void initUdpHandler();
|
||||
|
||||
|
|
247
udphandler.cpp
247
udphandler.cpp
|
@ -4,7 +4,7 @@
|
|||
#include "udphandler.h"
|
||||
#include "logcategories.h"
|
||||
udpHandler::udpHandler(QString ip, quint16 controlPort, quint16 civPort, quint16 audioPort, QString username, QString password,
|
||||
quint16 buffer, quint16 rxsample, quint8 rxcodec, quint16 txsample, quint8 txcodec) :
|
||||
quint16 rxlatency, quint16 txlatency, quint16 rxsample, quint8 rxcodec, quint16 txsample, quint8 txcodec) :
|
||||
controlPort(controlPort),
|
||||
civPort(civPort),
|
||||
audioPort(audioPort)
|
||||
|
@ -13,13 +13,14 @@ udpHandler::udpHandler(QString ip, quint16 controlPort, quint16 civPort, quint16
|
|||
this->port = this->controlPort;
|
||||
this->username = username;
|
||||
this->password = password;
|
||||
this->rxBufferSize = buffer;
|
||||
this->rxLatency = rxlatency;
|
||||
this->txLatency = txlatency;
|
||||
this->rxSampleRate = rxsample;
|
||||
this->txSampleRate = txsample;
|
||||
this->rxCodec = rxcodec;
|
||||
this->txCodec = txcodec;
|
||||
|
||||
qDebug(logUdp()) << "Starting udpHandler user:" << username << " buffer:" << buffer << " rx sample rate: " << rxsample <<
|
||||
qDebug(logUdp()) << "Starting udpHandler user:" << username << " rx latency:" << rxLatency << " tx latency:" << txLatency << " rx sample rate: " << rxsample <<
|
||||
" rx codec: " << rxcodec << " tx sample rate: " << txsample << " tx codec: " << txcodec;
|
||||
|
||||
// Try to set the IP address, if it is a hostname then perform a DNS lookup.
|
||||
|
@ -110,9 +111,9 @@ udpHandler::~udpHandler()
|
|||
}
|
||||
|
||||
|
||||
void udpHandler::changeBufferSize(quint16 value)
|
||||
void udpHandler::changeLatency(quint16 value)
|
||||
{
|
||||
emit haveChangeBufferSize(value);
|
||||
emit haveChangeLatency(value);
|
||||
}
|
||||
|
||||
void udpHandler::receiveFromCivStream(QByteArray data)
|
||||
|
@ -291,10 +292,10 @@ void udpHandler::dataReceived()
|
|||
}
|
||||
else {
|
||||
civ = new udpCivData(localIP, radioIP, civPort);
|
||||
audio = new udpAudio(localIP, radioIP, audioPort, rxBufferSize, rxSampleRate, rxCodec, txSampleRate, txCodec);
|
||||
audio = new udpAudio(localIP, radioIP, audioPort, rxLatency, txLatency, rxSampleRate, rxCodec, txSampleRate, txCodec);
|
||||
|
||||
QObject::connect(civ, SIGNAL(receive(QByteArray)), this, SLOT(receiveFromCivStream(QByteArray)));
|
||||
QObject::connect(this, SIGNAL(haveChangeBufferSize(quint16)), audio, SLOT(changeBufferSize(quint16)));
|
||||
QObject::connect(this, SIGNAL(haveChangeLatency(quint16)), audio, SLOT(changeLatency(quint16)));
|
||||
|
||||
|
||||
streamOpened = true;
|
||||
|
@ -360,7 +361,6 @@ void udpHandler::sendRequestStream()
|
|||
|
||||
QByteArray usernameEncoded;
|
||||
passcode(username, usernameEncoded);
|
||||
int txSeqBufLengthMs = 300;
|
||||
|
||||
conninfo_packet p;
|
||||
memset(p.packet, 0x0, sizeof(p)); // We can't be sure it is initialized with 0x00!
|
||||
|
@ -385,7 +385,7 @@ void udpHandler::sendRequestStream()
|
|||
p.txsample = qToBigEndian((quint32)txSampleRate);
|
||||
p.civport = qToBigEndian((quint32)civPort);
|
||||
p.audioport = qToBigEndian((quint32)audioPort);
|
||||
p.txbuffer = qToBigEndian((quint32)txSeqBufLengthMs);
|
||||
p.txbuffer = qToBigEndian((quint32)txLatency);
|
||||
|
||||
authInnerSendSeq++;
|
||||
|
||||
|
@ -631,13 +631,14 @@ void udpCivData::dataReceived()
|
|||
|
||||
|
||||
// Audio stream
|
||||
udpAudio::udpAudio(QHostAddress local, QHostAddress ip, quint16 audioPort, quint16 buffer, quint16 rxsample, quint8 rxcodec, quint16 txsample, quint8 txcodec)
|
||||
udpAudio::udpAudio(QHostAddress local, QHostAddress ip, quint16 audioPort, quint16 rxlatency, quint16 txlatency, quint16 rxsample, quint8 rxcodec, quint16 txsample, quint8 txcodec)
|
||||
{
|
||||
qDebug(logUdp()) << "Starting udpAudio";
|
||||
this->localIP = local;
|
||||
this->port = audioPort;
|
||||
this->radioIP = ip;
|
||||
this->bufferSize = buffer;
|
||||
this->rxLatency = rxlatency;
|
||||
this->txLatency = txlatency;
|
||||
this->rxSampleRate = rxsample;
|
||||
this->txSampleRate = txsample;
|
||||
this->rxCodec = rxcodec;
|
||||
|
@ -674,9 +675,10 @@ udpAudio::udpAudio(QHostAddress local, QHostAddress ip, quint16 audioPort, quint
|
|||
rxaudio->moveToThread(rxAudioThread);
|
||||
|
||||
connect(this, SIGNAL(setupRxAudio(quint8, quint8, quint16, quint16, bool, bool)), rxaudio, SLOT(init(quint8, quint8, quint16, quint16, bool, bool)));
|
||||
connect(this, SIGNAL(haveAudioData(QByteArray)), rxaudio, SLOT(incomingAudio(QByteArray)));
|
||||
connect(this, SIGNAL(haveChangeBufferSize(quint16)), rxaudio, SLOT(changeBufferSize(quint16)));
|
||||
connect(this, SIGNAL(haveChangeBufferSize(quint16)), rxaudio, SLOT(changeBufferSize(quint16)));
|
||||
|
||||
qRegisterMetaType<AUDIOPACKET>();
|
||||
connect(this, SIGNAL(haveAudioData(AUDIOPACKET)), rxaudio, SLOT(incomingAudio(AUDIOPACKET)));
|
||||
connect(this, SIGNAL(haveChangeLatency(quint16)), rxaudio, SLOT(changeLatency(quint16)));
|
||||
connect(rxAudioThread, SIGNAL(finished()), rxaudio, SLOT(deleteLater()));
|
||||
|
||||
if (txCodec == 0x01)
|
||||
|
@ -692,7 +694,6 @@ udpAudio::udpAudio(QHostAddress local, QHostAddress ip, quint16 audioPort, quint
|
|||
txaudio->moveToThread(txAudioThread);
|
||||
|
||||
connect(this, SIGNAL(setupTxAudio(quint8, quint8, quint16, quint16, bool, bool)), txaudio, SLOT(init(quint8, quint8, quint16, quint16, bool, bool)));
|
||||
//connect(txaudio, SIGNAL(haveAudioData(QByteArray)), this, SLOT(sendTxAudio(QByteArray)));
|
||||
connect(txAudioThread, SIGNAL(finished()), txaudio, SLOT(deleteLater()));
|
||||
|
||||
rxAudioThread->start();
|
||||
|
@ -705,8 +706,8 @@ udpAudio::udpAudio(QHostAddress local, QHostAddress ip, quint16 audioPort, quint
|
|||
connect(pingTimer, &QTimer::timeout, this, &udpBase::sendPing);
|
||||
pingTimer->start(PING_PERIOD); // send ping packets every 100ms
|
||||
|
||||
emit setupTxAudio(txNumSamples, txChannelCount, txSampleRate, bufferSize, txIsUlawCodec, true);
|
||||
emit setupRxAudio(rxNumSamples, rxChannelCount, rxSampleRate, bufferSize, rxIsUlawCodec, false);
|
||||
emit setupTxAudio(txNumSamples, txChannelCount, txSampleRate, txLatency, txIsUlawCodec, true);
|
||||
emit setupRxAudio(rxNumSamples, rxChannelCount, rxSampleRate, txLatency, rxIsUlawCodec, false);
|
||||
|
||||
watchdogTimer = new QTimer();
|
||||
connect(watchdogTimer, &QTimer::timeout, this, &udpAudio::watchdog);
|
||||
|
@ -719,9 +720,6 @@ udpAudio::udpAudio(QHostAddress local, QHostAddress ip, quint16 audioPort, quint
|
|||
areYouThereTimer = new QTimer();
|
||||
connect(areYouThereTimer, &QTimer::timeout, this, std::bind(&udpBase::sendControl, this, false, 0x03, 0));
|
||||
areYouThereTimer->start(AREYOUTHERE_PERIOD);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
udpAudio::~udpAudio()
|
||||
|
@ -793,9 +791,9 @@ void udpAudio::sendTxAudio()
|
|||
}
|
||||
}
|
||||
|
||||
void udpAudio::changeBufferSize(quint16 value)
|
||||
void udpAudio::changeLatency(quint16 value)
|
||||
{
|
||||
emit haveChangeBufferSize(value);
|
||||
emit haveChangeLatency(value);
|
||||
}
|
||||
|
||||
|
||||
|
@ -836,14 +834,20 @@ void udpAudio::dataReceived()
|
|||
r.mid(0, 2) == QByteArrayLiteral("\x70\x04"))
|
||||
{
|
||||
lastReceived = QTime::currentTime();
|
||||
emit haveAudioData(r.mid(24));
|
||||
AUDIOPACKET tempAudio;
|
||||
tempAudio.seq = in->seq;
|
||||
tempAudio.time = lastReceived;
|
||||
tempAudio.sent = 0;
|
||||
tempAudio.data = r.mid(24);
|
||||
emit haveAudioData(tempAudio);
|
||||
//rxaudio->incomingAudio(tempAudio);
|
||||
//rxaudio->incomingAudio(r.mid(24));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
udpBase::dataReceived(r); // Call parent function to process the rest.
|
||||
r.clear();
|
||||
datagram.clear();
|
||||
|
@ -861,6 +865,11 @@ void udpBase::init()
|
|||
qDebug(logUdp()) << "UDP Stream bound to local port:" << localPort << " remote port:" << port;
|
||||
uint32_t addr = localIP.toIPv4Address();
|
||||
myId = (addr >> 8 & 0xff) << 24 | (addr & 0xff) << 16 | (localPort & 0xffff);
|
||||
|
||||
retransmitTimer = new QTimer();
|
||||
connect(retransmitTimer, &QTimer::timeout, this, &udpBase::sendRetransmitRequest);
|
||||
retransmitTimer->start(RETRANSMIT_PERIOD);
|
||||
|
||||
}
|
||||
|
||||
udpBase::~udpBase()
|
||||
|
@ -887,10 +896,16 @@ udpBase::~udpBase()
|
|||
idleTimer->stop();
|
||||
delete idleTimer;
|
||||
}
|
||||
if (retransmitTimer != Q_NULLPTR)
|
||||
{
|
||||
retransmitTimer->stop();
|
||||
delete retransmitTimer;
|
||||
}
|
||||
|
||||
pingTimer = Q_NULLPTR;
|
||||
idleTimer = Q_NULLPTR;
|
||||
areYouThereTimer = Q_NULLPTR;
|
||||
retransmitTimer = Q_NULLPTR;
|
||||
|
||||
}
|
||||
|
||||
|
@ -1023,13 +1038,13 @@ void udpBase::dataReceived(QByteArray r)
|
|||
packetsLost++;
|
||||
}
|
||||
}
|
||||
} else
|
||||
if (in->len != PING_SIZE && in->type == 0x00 && in->seq != 0x00)
|
||||
}
|
||||
else if (in->len != PING_SIZE && in->type == 0x00 && in->seq != 0x00)
|
||||
{
|
||||
if (rxSeqBuf.isEmpty()) {
|
||||
rxSeqBuf.append(in->seq);
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
std::sort(rxSeqBuf.begin(), rxSeqBuf.end());
|
||||
if (in->seq < rxSeqBuf.front())
|
||||
|
@ -1038,11 +1053,12 @@ void udpBase::dataReceived(QByteArray r)
|
|||
|
||||
// Looks like it has rolled over so clear buffer and start again.
|
||||
rxSeqBuf.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rxSeqBuf.contains(in->seq))
|
||||
{
|
||||
// Add incoming packet to the received buffer and if it is in the mising buffer, remove it.
|
||||
// Add incoming packet to the received buffer and if it is in the missing buffer, remove it.
|
||||
rxSeqBuf.append(in->seq);
|
||||
// Check whether this is one of our missing ones!
|
||||
auto s = std::find_if(rxMissing.begin(), rxMissing.end(), [&cs = in->seq](SEQBUFENTRY& s) { return s.seqNum == cs; });
|
||||
|
@ -1051,95 +1067,104 @@ void udpBase::dataReceived(QByteArray r)
|
|||
qDebug(logUdp()) << this->metaObject()->className() << ": Missing SEQ has been received! " << hex << in->seq;
|
||||
s = rxMissing.erase(s);
|
||||
}
|
||||
std::sort(rxSeqBuf.begin(), rxSeqBuf.end());
|
||||
}
|
||||
|
||||
// Find all gaps in received packets
|
||||
|
||||
QByteArray missingSeqs;
|
||||
|
||||
auto i = std::adjacent_find(rxSeqBuf.begin(), rxSeqBuf.end(), [](quint16 l, quint16 r) {return l + 1 < r; });
|
||||
while (i != rxSeqBuf.end())
|
||||
{
|
||||
if (i + 1 != rxSeqBuf.end())
|
||||
{
|
||||
if (*(i + 1) - *i < 30)
|
||||
{
|
||||
for (quint16 j = *i + 1; j < *(i + 1); j++)
|
||||
{
|
||||
//qDebug(logUdp()) << this->metaObject()->className() << ": Found missing seq between " << *i << " : " << *(i + 1) << " (" << j << ")";
|
||||
auto s = std::find_if(rxMissing.begin(), rxMissing.end(), [&cs = j](SEQBUFENTRY& s) { return s.seqNum == cs; });
|
||||
if (s == rxMissing.end())
|
||||
{
|
||||
// We haven't seen this missing packet before
|
||||
//qDebug(logUdp()) << this->metaObject()->className() << ": Adding to missing buffer (len="<< rxMissing.length() << "): " << j;
|
||||
SEQBUFENTRY b;
|
||||
b.seqNum = j;
|
||||
b.retransmitCount = 0;
|
||||
b.timeSent = QTime::currentTime();
|
||||
rxMissing.append(b);
|
||||
packetsLost++;
|
||||
}
|
||||
else {
|
||||
if (s->retransmitCount == 10)
|
||||
{
|
||||
// We have tried 10 times to request this packet, time to give up!
|
||||
s = rxMissing.erase(s);
|
||||
rxSeqBuf.append(j); // Final thing is to add to received buffer!
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
qDebug(logUdp()) << this->metaObject()->className() << ": Too many missing, flushing buffers";
|
||||
rxSeqBuf.clear();
|
||||
missingSeqs.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
for (auto it = rxMissing.begin(); it != rxMissing.end(); ++it)
|
||||
{
|
||||
if (it->retransmitCount < 10)
|
||||
{
|
||||
missingSeqs.append(it->seqNum & 0xff);
|
||||
missingSeqs.append(it->seqNum >> 8 & 0xff);
|
||||
missingSeqs.append(it->seqNum & 0xff);
|
||||
missingSeqs.append(it->seqNum >> 8 & 0xff);
|
||||
it->retransmitCount++;
|
||||
}
|
||||
}
|
||||
if (missingSeqs.length() != 0)
|
||||
{
|
||||
control_packet p;
|
||||
memset(p.packet, 0x0, sizeof(p)); // We can't be sure it is initialized with 0x00!
|
||||
p.type = 0x01;
|
||||
p.seq = 0x0000;
|
||||
p.sentid = myId;
|
||||
p.rcvdid = remoteId;
|
||||
if (missingSeqs.length() == 4) // This is just a single missing packet so send using a control.
|
||||
{
|
||||
p.seq = (missingSeqs[0] &0xff) |(quint16)(missingSeqs[1] << 8) ;
|
||||
qDebug(logUdp()) << this->metaObject()->className() << ": sending request for missing packet : " << hex << p.seq;
|
||||
QMutexLocker locker(&mutex);
|
||||
udp->writeDatagram(QByteArray::fromRawData((const char*)p.packet, sizeof(p)), radioIP, port);
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug(logUdp()) << this->metaObject()->className() << ": sending request for multiple missing packets : " <<missingSeqs.toHex();
|
||||
missingSeqs.insert(0, p.packet, sizeof(p.packet));
|
||||
QMutexLocker locker(&mutex);
|
||||
udp->writeDatagram(missingSeqs, radioIP, port);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void udpBase::sendRetransmitRequest()
|
||||
{
|
||||
// Find all gaps in received packets and then send requests for them.
|
||||
// This will run every 100ms so out-of-sequence packets will not trigger a retransmit request.
|
||||
|
||||
QByteArray missingSeqs;
|
||||
|
||||
auto i = std::adjacent_find(rxSeqBuf.begin(), rxSeqBuf.end(), [](quint16 l, quint16 r) {return l + 1 < r; });
|
||||
while (i != rxSeqBuf.end())
|
||||
{
|
||||
if (i + 1 != rxSeqBuf.end())
|
||||
{
|
||||
if (*(i + 1) - *i < 30)
|
||||
{
|
||||
for (quint16 j = *i + 1; j < *(i + 1); j++)
|
||||
{
|
||||
//qDebug(logUdp()) << this->metaObject()->className() << ": Found missing seq between " << *i << " : " << *(i + 1) << " (" << j << ")";
|
||||
auto s = std::find_if(rxMissing.begin(), rxMissing.end(), [&cs = j](SEQBUFENTRY& s) { return s.seqNum == cs; });
|
||||
if (s == rxMissing.end())
|
||||
{
|
||||
// We haven't seen this missing packet before
|
||||
//qDebug(logUdp()) << this->metaObject()->className() << ": Adding to missing buffer (len="<< rxMissing.length() << "): " << j;
|
||||
SEQBUFENTRY b;
|
||||
b.seqNum = j;
|
||||
b.retransmitCount = 0;
|
||||
b.timeSent = QTime::currentTime();
|
||||
rxMissing.append(b);
|
||||
packetsLost++;
|
||||
}
|
||||
else {
|
||||
if (s->retransmitCount == 4)
|
||||
{
|
||||
// We have tried 4 times to request this packet, time to give up!
|
||||
s = rxMissing.erase(s);
|
||||
rxSeqBuf.append(j); // Final thing is to add to received buffer!
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
qDebug(logUdp()) << this->metaObject()->className() << ": Too many missing, flushing buffers";
|
||||
rxSeqBuf.clear();
|
||||
missingSeqs.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
for (auto it = rxMissing.begin(); it != rxMissing.end(); ++it)
|
||||
{
|
||||
if (it->retransmitCount < 10)
|
||||
{
|
||||
missingSeqs.append(it->seqNum & 0xff);
|
||||
missingSeqs.append(it->seqNum >> 8 & 0xff);
|
||||
missingSeqs.append(it->seqNum & 0xff);
|
||||
missingSeqs.append(it->seqNum >> 8 & 0xff);
|
||||
it->retransmitCount++;
|
||||
}
|
||||
}
|
||||
if (missingSeqs.length() != 0)
|
||||
{
|
||||
control_packet p;
|
||||
memset(p.packet, 0x0, sizeof(p)); // We can't be sure it is initialized with 0x00!
|
||||
p.type = 0x01;
|
||||
p.seq = 0x0000;
|
||||
p.sentid = myId;
|
||||
p.rcvdid = remoteId;
|
||||
if (missingSeqs.length() == 4) // This is just a single missing packet so send using a control.
|
||||
{
|
||||
p.seq = (missingSeqs[0] & 0xff) | (quint16)(missingSeqs[1] << 8);
|
||||
qDebug(logUdp()) << this->metaObject()->className() << ": sending request for missing packet : " << hex << p.seq;
|
||||
QMutexLocker locker(&mutex);
|
||||
udp->writeDatagram(QByteArray::fromRawData((const char*)p.packet, sizeof(p)), radioIP, port);
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug(logUdp()) << this->metaObject()->className() << ": sending request for multiple missing packets : " << missingSeqs.toHex();
|
||||
missingSeqs.insert(0, p.packet, sizeof(p.packet));
|
||||
QMutexLocker locker(&mutex);
|
||||
udp->writeDatagram(missingSeqs, radioIP, port);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Used to send idle and other "control" style messages
|
||||
void udpBase::sendControl(bool tracked=true, quint8 type=0, quint16 seq=0)
|
||||
{
|
||||
|
|
31
udphandler.h
31
udphandler.h
|
@ -31,7 +31,9 @@
|
|||
#define TXAUDIO_PERIOD 10
|
||||
#define AREYOUTHERE_PERIOD 500
|
||||
#define WATCHDOG_PERIOD 500
|
||||
#define RETRANSMIT_PERIOD 100
|
||||
|
||||
Q_DECLARE_METATYPE(AUDIOPACKET)
|
||||
|
||||
void passcode(QString in, QByteArray& out);
|
||||
QByteArray parseNullTerminatedString(QByteArray c, int s);
|
||||
|
@ -40,6 +42,7 @@ QByteArray parseNullTerminatedString(QByteArray c, int s);
|
|||
class udpBase : public QObject
|
||||
{
|
||||
|
||||
|
||||
public:
|
||||
~udpBase();
|
||||
|
||||
|
@ -98,6 +101,7 @@ public:
|
|||
QTimer* idleTimer = Q_NULLPTR; // Start watchdog once we are connected.
|
||||
|
||||
QTimer* watchdogTimer = Q_NULLPTR;
|
||||
QTimer* retransmitTimer = Q_NULLPTR;
|
||||
|
||||
QDateTime lastPingSentTime;
|
||||
uint16_t pingSendSeq = 0;
|
||||
|
@ -107,6 +111,9 @@ public:
|
|||
quint32 packetsSent=0;
|
||||
quint32 packetsLost=0;
|
||||
|
||||
private:
|
||||
void sendRetransmitRequest();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -142,19 +149,19 @@ class udpAudio : public udpBase
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
udpAudio(QHostAddress local, QHostAddress ip, quint16 aport, quint16 buffer, quint16 rxsample, quint8 rxcodec, quint16 txsample, quint8 txcodec);
|
||||
udpAudio(QHostAddress local, QHostAddress ip, quint16 aport, quint16 rxlatency, quint16 txlatency, quint16 rxsample, quint8 rxcodec, quint16 txsample, quint8 txcodec);
|
||||
~udpAudio();
|
||||
|
||||
signals:
|
||||
void haveAudioData(QByteArray data);
|
||||
void haveAudioData(AUDIOPACKET data);
|
||||
|
||||
void setupTxAudio(const quint8 samples, const quint8 channels, const quint16 samplerate, const quint16 bufferSize, const bool isUlaw, const bool isInput);
|
||||
void setupRxAudio(const quint8 samples, const quint8 channels, const quint16 samplerate, const quint16 bufferSize, const bool isUlaw, const bool isInput);
|
||||
void setupTxAudio(const quint8 samples, const quint8 channels, const quint16 samplerate, const quint16 latency, const bool isUlaw, const bool isInput);
|
||||
void setupRxAudio(const quint8 samples, const quint8 channels, const quint16 samplerate, const quint16 latency, const bool isUlaw, const bool isInput);
|
||||
|
||||
void haveChangeBufferSize(quint16 value);
|
||||
void haveChangeLatency(quint16 value);
|
||||
|
||||
public slots:
|
||||
void changeBufferSize(quint16 value);
|
||||
void changeLatency(quint16 value);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -163,7 +170,8 @@ private:
|
|||
void watchdog();
|
||||
|
||||
QAudioFormat format;
|
||||
quint16 bufferSize;
|
||||
quint16 rxLatency;
|
||||
quint16 txLatency;
|
||||
quint16 rxSampleRate;
|
||||
quint16 txSampleRate;
|
||||
quint8 rxCodec;
|
||||
|
@ -197,7 +205,7 @@ class udpHandler: public udpBase
|
|||
|
||||
public:
|
||||
udpHandler(QString ip, quint16 cport, quint16 sport, quint16 aport, QString username, QString password,
|
||||
quint16 buffer, quint16 rxsample, quint8 rxcodec, quint16 txsample, quint8 txcodec);
|
||||
quint16 rxlatency, quint16 txlatency, quint16 rxsample, quint8 rxcodec, quint16 txsample, quint8 txcodec);
|
||||
~udpHandler();
|
||||
|
||||
bool streamOpened = false;
|
||||
|
@ -209,14 +217,14 @@ public:
|
|||
public slots:
|
||||
void receiveDataFromUserToRig(QByteArray); // This slot will send data on to
|
||||
void receiveFromCivStream(QByteArray);
|
||||
void changeBufferSize(quint16 value);
|
||||
void changeLatency(quint16 value);
|
||||
void init();
|
||||
|
||||
signals:
|
||||
void haveDataFromPort(QByteArray data); // emit this when we have data, connect to rigcommander
|
||||
void haveNetworkError(QString, QString);
|
||||
void haveNetworkStatus(QString);
|
||||
void haveChangeBufferSize(quint16 value);
|
||||
void haveChangeLatency(quint16 value);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -243,7 +251,8 @@ private:
|
|||
|
||||
quint16 rxSampleRate;
|
||||
quint16 txSampleRate;
|
||||
quint16 rxBufferSize;
|
||||
quint16 rxLatency;
|
||||
quint16 txLatency;
|
||||
quint8 rxCodec;
|
||||
quint8 txCodec;
|
||||
|
||||
|
|
40
wfmain.cpp
40
wfmain.cpp
|
@ -533,11 +533,11 @@ void wfmain::openRig()
|
|||
connect(rig, SIGNAL(haveSerialPortError(QString, QString)), this, SLOT(receiveSerialPortError(QString, QString)));
|
||||
connect(rig, SIGNAL(haveStatusUpdate(QString)), this, SLOT(receiveStatusUpdate(QString)));
|
||||
|
||||
connect(this, SIGNAL(sendCommSetup(unsigned char, QString, quint16, quint16, quint16, QString, QString,quint16,quint16,quint8,quint16,quint8)), rig, SLOT(commSetup(unsigned char, QString, quint16, quint16, quint16, QString, QString,quint16,quint16,quint8,quint16,quint8)));
|
||||
connect(this, SIGNAL(sendCommSetup(unsigned char, QString, quint16, quint16, quint16, QString, QString,quint16,quint16,quint16,quint8,quint16,quint8)), rig, SLOT(commSetup(unsigned char, QString, quint16, quint16, quint16, QString, QString,quint16,quint16,quint16,quint8,quint16,quint8)));
|
||||
connect(this, SIGNAL(sendCommSetup(unsigned char, QString, quint32)), rig, SLOT(commSetup(unsigned char, QString, quint32)));
|
||||
|
||||
connect(this, SIGNAL(sendCloseComm()), rig, SLOT(closeComm()));
|
||||
connect(this, SIGNAL(sendChangeBufferSize(quint16)), rig, SLOT(changeBufferSize(quint16)));
|
||||
connect(this, SIGNAL(sendChangeLatency(quint16)), rig, SLOT(changeLatency(quint16)));
|
||||
connect(this, SIGNAL(getRigCIV()), rig, SLOT(findRigs()));
|
||||
connect(rig, SIGNAL(discoveredRigID(rigCapabilities)), this, SLOT(receiveFoundRigID(rigCapabilities)));
|
||||
connect(rig, SIGNAL(commReady()), this, SLOT(receiveCommReady()));
|
||||
|
@ -546,7 +546,7 @@ void wfmain::openRig()
|
|||
if (prefs.enableLAN)
|
||||
{
|
||||
emit sendCommSetup(prefs.radioCIVAddr, prefs.ipAddress, prefs.controlLANPort,
|
||||
prefs.serialLANPort, prefs.audioLANPort, prefs.username, prefs.password,prefs.audioRXBufferSize,prefs.audioRXSampleRate,prefs.audioRXCodec,prefs.audioTXSampleRate,prefs.audioTXCodec);
|
||||
prefs.serialLANPort, prefs.audioLANPort, prefs.username, prefs.password,prefs.audioRXLatency,prefs.audioTXLatency,prefs.audioRXSampleRate,prefs.audioRXCodec,prefs.audioTXSampleRate,prefs.audioTXCodec);
|
||||
} else {
|
||||
|
||||
if( (prefs.serialPortRadio == QString("auto")) && (serialPortCL.isEmpty()))
|
||||
|
@ -699,7 +699,8 @@ void wfmain::setDefPrefs()
|
|||
defPrefs.password = QString("");
|
||||
defPrefs.audioOutput = QAudioDeviceInfo::defaultOutputDevice().deviceName();
|
||||
defPrefs.audioInput = QAudioDeviceInfo::defaultInputDevice().deviceName();
|
||||
defPrefs.audioRXBufferSize = 12000;
|
||||
defPrefs.audioRXLatency = 150;
|
||||
defPrefs.audioTXLatency = 150;
|
||||
defPrefs.audioRXSampleRate = 48000;
|
||||
defPrefs.audioRXCodec = 4;
|
||||
defPrefs.audioTXSampleRate = 48000;
|
||||
|
@ -769,10 +770,15 @@ void wfmain::loadSettings()
|
|||
ui->passwordTxt->setEnabled(ui->lanEnableChk->isChecked());
|
||||
ui->passwordTxt->setText(QString("%1").arg(prefs.password));
|
||||
|
||||
prefs.audioRXBufferSize = settings.value("AudioRXBufferSize", defPrefs.audioRXBufferSize).toInt();
|
||||
ui->audioBufferSizeSlider->setEnabled(ui->lanEnableChk->isChecked());
|
||||
ui->audioBufferSizeSlider->setValue(prefs.audioRXBufferSize);
|
||||
ui->audioBufferSizeSlider->setTracking(false); // Stop it sending value on every change.
|
||||
prefs.audioRXLatency = settings.value("AudioRXLatency", defPrefs.audioRXLatency).toInt();
|
||||
ui->rxLatencySlider->setEnabled(ui->lanEnableChk->isChecked());
|
||||
ui->txLatencySlider->setValue(prefs.audioRXLatency);
|
||||
ui->rxLatencySlider->setTracking(false); // Stop it sending value on every change.
|
||||
|
||||
prefs.audioTXLatency = settings.value("AudioTXLatency", defPrefs.audioTXLatency).toInt();
|
||||
ui->rxLatencySlider->setEnabled(ui->lanEnableChk->isChecked());
|
||||
ui->rxLatencySlider->setValue(prefs.audioTXLatency);
|
||||
ui->rxLatencySlider->setTracking(false); // Stop it sending value on every change.
|
||||
|
||||
prefs.audioRXSampleRate = settings.value("AudioRXSampleRate", defPrefs.audioRXSampleRate).toInt();
|
||||
prefs.audioTXSampleRate = settings.value("AudioTXSampleRate", defPrefs.audioTXSampleRate).toInt();
|
||||
|
@ -917,10 +923,10 @@ void wfmain::saveSettings()
|
|||
settings.setValue("AudioLANPort", prefs.audioLANPort);
|
||||
settings.setValue("Username", prefs.username);
|
||||
settings.setValue("Password", prefs.password);
|
||||
settings.setValue("AudioRXBufferSize", prefs.audioRXBufferSize);
|
||||
settings.setValue("AudioRXLatency", prefs.audioRXLatency);
|
||||
settings.setValue("AudioTXLatency", prefs.audioTXLatency);
|
||||
settings.setValue("AudioRXSampleRate", prefs.audioRXSampleRate);
|
||||
settings.setValue("AudioRXCodec", prefs.audioRXCodec);
|
||||
settings.setValue("AudioTXBufferSize", prefs.audioRXBufferSize);
|
||||
settings.setValue("AudioTXSampleRate", prefs.audioRXSampleRate);
|
||||
settings.setValue("AudioTXCodec", prefs.audioTXCodec);
|
||||
settings.setValue("AudioOutput", prefs.audioOutput);
|
||||
|
@ -2866,11 +2872,17 @@ void wfmain::on_audioTXCodecCombo_currentIndexChanged(int value)
|
|||
prefs.audioTXCodec = ui->audioTXCodecCombo->itemData(value).toInt();
|
||||
}
|
||||
|
||||
void wfmain::on_audioBufferSizeSlider_valueChanged(int value)
|
||||
void wfmain::on_rxLatencySlider_valueChanged(int value)
|
||||
{
|
||||
prefs.audioRXBufferSize = value;
|
||||
ui->bufferValue->setText(QString::number(value));
|
||||
emit sendChangeBufferSize(value);
|
||||
prefs.audioRXLatency = value;
|
||||
ui->rxLatencyValue->setText(QString::number(value));
|
||||
emit sendChangeLatency(value);
|
||||
}
|
||||
|
||||
void wfmain::on_txLatencySlider_valueChanged(int value)
|
||||
{
|
||||
prefs.audioTXLatency = value;
|
||||
ui->txLatencyValue->setText(QString::number(value));
|
||||
}
|
||||
|
||||
void wfmain::on_toFixedBtn_clicked()
|
||||
|
|
11
wfmain.h
11
wfmain.h
|
@ -108,9 +108,9 @@ signals:
|
|||
void sayAll();
|
||||
void sendCommSetup(unsigned char rigCivAddr, QString rigSerialPort, quint32 rigBaudRate);
|
||||
void sendCommSetup(unsigned char rigCivAddr, QString ip, quint16 cport, quint16 sport, quint16 aport,
|
||||
QString username, QString password, quint16 buffer, quint16 rxsample, quint8 rxcodec, quint16 txsample, quint8 txcodec);
|
||||
QString username, QString password, quint16 rxlatency, quint16 txlatency, quint16 rxsample, quint8 rxcodec, quint16 txsample, quint8 txcodec);
|
||||
void sendCloseComm();
|
||||
void sendChangeBufferSize(quint16 value);
|
||||
void sendChangeLatency(quint16 latency);
|
||||
void initServer();
|
||||
void sendServerConfig(SERVERCONFIG conf);
|
||||
|
||||
|
@ -329,7 +329,9 @@ private slots:
|
|||
|
||||
void on_connectBtn_clicked();
|
||||
|
||||
void on_audioBufferSizeSlider_valueChanged(int value);
|
||||
void on_rxLatencySlider_valueChanged(int value);
|
||||
|
||||
void on_txLatencySlider_valueChanged(int value);
|
||||
|
||||
void on_audioRXCodecCombo_currentIndexChanged(int value);
|
||||
|
||||
|
@ -527,7 +529,8 @@ private:
|
|||
QString password;
|
||||
QString audioOutput;
|
||||
QString audioInput;
|
||||
quint16 audioRXBufferSize;
|
||||
quint16 audioRXLatency;
|
||||
quint16 audioTXLatency;
|
||||
quint16 audioRXSampleRate;
|
||||
quint8 audioRXCodec;
|
||||
quint16 audioTXSampleRate;
|
||||
|
|
42
wfmain.ui
42
wfmain.ui
|
@ -18,7 +18,7 @@
|
|||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
<number>3</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="mainTab">
|
||||
<attribute name="title">
|
||||
|
@ -1765,20 +1765,23 @@
|
|||
<item>
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="text">
|
||||
<string>RX Audio Buffer Size</string>
|
||||
<string>RX Latency (ms)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="audioBufferSizeSlider">
|
||||
<widget class="QSlider" name="rxLatencySlider">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>65536</number>
|
||||
<number>500</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
|
@ -1786,7 +1789,34 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="bufferValue">
|
||||
<widget class="QLabel" name="rxLatencyValue">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_24">
|
||||
<property name="text">
|
||||
<string>TX Latency (ms)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="txLatencySlider">
|
||||
<property name="minimum">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>500</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="txLatencyValue">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
|
@ -1948,7 +1978,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>810</width>
|
||||
<height>22</height>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
|
|
Ładowanie…
Reference in New Issue