Audio metering initial. Very messy but you can select TxRxAudio as the

meter type and wfview will show you TX or RX audio depending upon if you
are transmitting or not. You can also select only TxAudio or RxAudio.
This is nice for looking at Tx audio levels prior to transmitting, for
example, or metering the radio's "monitor" audio while transmitting.
monitor
Elliott Liggett 2022-08-23 22:24:05 -07:00
rodzic 105675a128
commit 9fb74ed6e1
13 zmienionych plików z 123 dodań i 12 usunięć

Wyświetl plik

@ -157,7 +157,9 @@ bool audioConverter::convert(audioPacket audio)
if (samplesF.size() > 0)
{
audio.amplitude = samplesF.array().abs().maxCoeff();
audio.amplitudePeak = samplesF.array().abs().maxCoeff();
audio.amplitudeRMS = samplesF.squaredNorm();
// Set the volume
samplesF *= audio.volume;

Wyświetl plik

@ -29,7 +29,8 @@ struct audioPacket {
quint16 sent;
QByteArray data;
quint8 guid[GUIDLEN];
float amplitude;
float amplitudePeak;
float amplitudeRMS;
qreal volume = 1.0;
};

Wyświetl plik

@ -270,12 +270,18 @@ void audioHandler::convertedOutput(audioPacket packet) {
}
*/
lastSentSeq = packet.seq;
amplitude = packet.amplitudePeak;
computeLevels();
emit haveLevels(getAmplitude(), setup.latency, currentLatency, isUnderrun, isOverrun);
amplitude = packet.amplitude;
}
}
void audioHandler::computeLevels()
{
if(levelMean)
levelMean[(levelPosition++)%levelSize] = amplitude * 255;
}
void audioHandler::getNextAudioChunk()
{
if (audioDevice) {
@ -312,7 +318,7 @@ void audioHandler::convertedInput(audioPacket audio)
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;
amplitude = audio.amplitudePeak;
emit haveLevels(getAmplitude(), setup.latency, currentLatency, isUnderrun, isOverrun);
}
}

Wyświetl plik

@ -116,6 +116,12 @@ private:
float amplitude=0.0;
qreal volume = 1.0;
unsigned char *levelMean = Q_NULLPTR;
unsigned char *levelPeak = Q_NULLPTR;
unsigned char levelSize = 50;
unsigned char levelPosition = 0;
void computeLevels();
audioSetup setup;
OpusEncoder* encoder = Q_NULLPTR;

Wyświetl plik

@ -278,7 +278,7 @@ void paHandler::convertedOutput(audioPacket packet) {
currentLatency = packet.time.msecsTo(QTime::currentTime()) + (info->outputLatency * 1000);
}
amplitude = packet.amplitude;
amplitude = packet.amplitudePeak;
emit haveLevels(getAmplitude(), setup.latency, currentLatency, isUnderrun, isOverrun);
}
}
@ -289,7 +289,7 @@ void paHandler::convertedInput(audioPacket packet)
{
if (packet.data.size() > 0) {
emit haveAudioData(packet);
amplitude = packet.amplitude;
amplitude = packet.amplitudePeak;
const PaStreamInfo* info = Pa_GetStreamInfo(audio);
currentLatency = packet.time.msecsTo(QTime::currentTime()) + (info->inputLatency * 1000);
emit haveLevels(getAmplitude(), setup.latency, currentLatency, isUnderrun, isOverrun);

Wyświetl plik

@ -166,6 +166,8 @@ void rigCommander::commSetup(unsigned char rigCivAddr, udpPreferences prefs, aud
// Connect for errors/alerts
connect(udp, SIGNAL(haveNetworkError(QString, QString)), this, SLOT(handleSerialPortError(QString, QString)));
connect(udp, SIGNAL(haveNetworkStatus(networkStatus)), this, SLOT(handleStatusUpdate(networkStatus)));
connect(udp, SIGNAL(haveNetworkAudioLevels(networkAudioLevels)), this, SLOT(handleNetworkAudioLevels(networkAudioLevels)));
connect(ptty, SIGNAL(haveSerialPortError(QString, QString)), this, SLOT(handleSerialPortError(QString, QString)));
connect(this, SIGNAL(getMoreDebug()), ptty, SLOT(debugThis()));
@ -245,6 +247,11 @@ void rigCommander::handleStatusUpdate(const networkStatus status)
emit haveStatusUpdate(status);
}
void rigCommander::handleNetworkAudioLevels(networkAudioLevels l)
{
emit haveNetworkAudioLevels(l);
}
bool rigCommander::usingLAN()
{
return usingNativeLAN;

Wyświetl plik

@ -36,6 +36,7 @@ enum meterKind {
meterRxdB,
meterTxMod,
meterRxAudio,
meterAudio,
meterLatency
};
@ -277,6 +278,7 @@ public slots:
// Housekeeping:
void handleStatusUpdate(const networkStatus status);
void handleNetworkAudioLevels(networkAudioLevels);
void radioSelection(QList<radio_cap_packet> radios);
void radioUsage(quint8 radio, quint8 busy, QString name, QString ip);
void setCurrentRadio(quint8 radio);
@ -288,6 +290,7 @@ signals:
void commReady();
void haveSerialPortError(const QString port, const QString errorText);
void haveStatusUpdate(const networkStatus status);
void haveNetworkAudioLevels(const networkAudioLevels l);
void dataForComm(const QByteArray &outData);
void toggleRTS(bool rtsOn);
@ -397,6 +400,11 @@ private:
quint16 decodeTone(QByteArray eTone);
quint16 decodeTone(QByteArray eTone, bool &tinv, bool &rinv);
unsigned char audioLevelRxMean[50];
unsigned char audioLevelRxPeak[50];
unsigned char audioLevelTxMean[50];
unsigned char audioLevelTxPeak[50];
void parseMode();
void parseSpectrum();
void parseWFData();

Wyświetl plik

@ -331,7 +331,7 @@ void rtHandler::convertedOutput(audioPacket packet)
audioMutex.lock();
arrayBuffer.append(packet.data);
audioMutex.unlock();
amplitude = packet.amplitude;
amplitude = packet.amplitudePeak;
currentLatency = packet.time.msecsTo(QTime::currentTime()) + (outFormat.durationForBytes(audio->getStreamLatency() * (outFormat.sampleSize() / 8) * outFormat.channelCount())/1000);
emit haveLevels(getAmplitude(), setup.latency, currentLatency, isUnderrun, isOverrun);
}
@ -342,7 +342,7 @@ void rtHandler::convertedInput(audioPacket packet)
{
if (packet.data.size() > 0) {
emit haveAudioData(packet);
amplitude = packet.amplitude;
amplitude = packet.amplitudePeak;
currentLatency = packet.time.msecsTo(QTime::currentTime()) + (outFormat.durationForBytes(audio->getStreamLatency() * (outFormat.sampleSize() / 8) * outFormat.channelCount())/1000);
emit haveLevels(getAmplitude(), setup.latency, currentLatency, isUnderrun, isOverrun);
}

Wyświetl plik

@ -37,6 +37,15 @@ struct udpPreferences {
quint8 waterfallFormat;
};
struct networkAudioLevels {
bool haveTxLevels = false;
bool haveRxLevels = false;
quint8 rxAudioRMS = 0;
quint8 txAudioRMS = 0;
quint8 rxAudioPeak = 0;
quint8 txAudioPeak = 0;
};
struct networkStatus {
quint8 rxAudioBufferPercent;
quint8 txAudioBufferPercent;

Wyświetl plik

@ -149,6 +149,17 @@ void udpHandler::getRxLevels(quint16 amplitude,quint16 latency,quint16 current,
status.rxCurrentLatency = current;
status.rxUnderrun = under;
status.rxOverrun = over;
audioLevelsRxPeak[(audioLevelsRxPeakPosition++)%audioLevelBufferSize] = amplitude;
if((audioLevelsRxPeakPosition++)%3 == 0)
{
// calculate mean and emit signal
unsigned char mean = findMean(audioLevelsRxPeak);
networkAudioLevels l;
l.haveRxLevels = true;
l.rxAudioPeak = mean;
//qDebug(logSystem()) << "audio level meter being emitted from udpHandler";
emit haveNetworkAudioLevels(l);
}
}
void udpHandler::getTxLevels(quint16 amplitude,quint16 latency, quint16 current, bool under, bool over) {
@ -157,6 +168,26 @@ void udpHandler::getTxLevels(quint16 amplitude,quint16 latency, quint16 current,
status.txCurrentLatency = current;
status.txUnderrun = under;
status.txOverrun = over;
audioLevelsTxPeak[(audioLevelsTxPeakPosition++)%audioLevelBufferSize] = amplitude;
if((audioLevelsTxPeakPosition++)%3 == 0)
{
// calculate mean and emit signal
unsigned char mean = findMean(audioLevelsTxPeak);
networkAudioLevels l;
l.haveTxLevels = true;
l.txAudioPeak = mean;
emit haveNetworkAudioLevels(l);
}
}
unsigned char udpHandler::findMean(unsigned char *data)
{
unsigned int sum=0;
for(int p=0; p < audioLevelBufferSize; p++)
{
sum += data[p];
}
return sum / audioLevelBufferSize;
}
void udpHandler::dataReceived()

Wyświetl plik

@ -29,7 +29,7 @@
#include "udpcivdata.h"
#include "udpaudio.h"
#define audioLevelBufferSize (3)
// Class to handle the connection/disconnection of the radio.
class udpHandler: public udpBase
@ -58,7 +58,8 @@ public slots:
void setCurrentRadio(quint8 radio);
void getRxLevels(quint16 amplitude, quint16 latency, quint16 current, bool under, bool over);
void getTxLevels(quint16 amplitude, quint16 latency, quint16 current, bool under, bool over);
//void handleRxLevels(networkAudioLevels);
//void handleTxLevels(networkAudioLevels);
signals:
void haveDataFromPort(QByteArray data); // emit this when we have data, connect to rigcommander
@ -67,6 +68,7 @@ signals:
void haveChangeLatency(quint16 value);
void haveSetVolume(unsigned char value);
void haveNetworkStatus(networkStatus);
void haveNetworkAudioLevels(networkAudioLevels);
void haveBaudRate(quint32 baudrate);
void requestRadioSelection(QList<radio_cap_packet> radios);
void setRadioUsage(quint8, quint8 busy, QString name, QString mac);
@ -122,6 +124,14 @@ private:
quint16 txSampleRates = 0;
networkStatus status;
bool splitWf = false;
unsigned char audioLevelsTxPeak[audioLevelBufferSize];
unsigned char audioLevelsRxPeak[audioLevelBufferSize];
unsigned char audioLevelsTxPeakPosition = 0;
unsigned char audioLevelsRxPeakPosition = 0;
unsigned char findMean(unsigned char *d);
};

Wyświetl plik

@ -47,6 +47,7 @@ wfmain::wfmain(const QString serialPortCL, const QString hostCL, const QString s
qRegisterMetaType<rigstate*>();
qRegisterMetaType<QList<radio_cap_packet>>();
qRegisterMetaType<networkStatus>();
qRegisterMetaType<networkAudioLevels>();
haveRigCaps = false;
@ -424,6 +425,7 @@ void wfmain::makeRig()
// Rig status and Errors:
connect(rig, SIGNAL(haveSerialPortError(QString, QString)), this, SLOT(receiveSerialPortError(QString, QString)));
connect(rig, SIGNAL(haveStatusUpdate(networkStatus)), this, SLOT(receiveStatusUpdate(networkStatus)));
connect(rig, SIGNAL(haveNetworkAudioLevels(networkAudioLevels)), this, SLOT(receiveNetworkAudioLevels(networkAudioLevels)));
connect(rig, SIGNAL(requestRadioSelection(QList<radio_cap_packet>)), this, SLOT(radioSelection(QList<radio_cap_packet>)));
connect(rig, SIGNAL(setRadioUsage(quint8, quint8, QString, QString)), selRad, SLOT(setInUse(quint8, quint8, QString, QString)));
connect(selRad, SIGNAL(selectedRadio(quint8)), rig, SLOT(setCurrentRadio(quint8)));
@ -615,6 +617,22 @@ void wfmain::receiveStatusUpdate(networkStatus status)
//qInfo(logSystem()) << "Got Status Update" << status.rxAudioLevel;
}
void wfmain::receiveNetworkAudioLevels(networkAudioLevels l)
{
qInfo(logSystem()) << "audio level meter received.";
meterKind m = meterNone;
if(l.haveRxLevels)
{
m = meterRxAudio;
receiveMeter(m, l.rxAudioPeak);
}
if(l.haveTxLevels)
{
m = meterTxMod;
receiveMeter(m, l.txAudioPeak);
}
}
void wfmain::setupPlots()
{
spectrumDrawLock = true;
@ -746,6 +764,10 @@ void wfmain::setupMainUI()
ui->meter2selectionCombo->addItem("Voltage", meterVoltage);
ui->meter2selectionCombo->addItem("Current", meterCurrent);
ui->meter2selectionCombo->addItem("Center", meterCenter);
ui->meter2selectionCombo->addItem("TxRxAudio", meterAudio);
ui->meter2selectionCombo->addItem("RxAudio", meterRxAudio);
ui->meter2selectionCombo->addItem("TxAudio", meterTxMod);
ui->meter2Widget->hide();
ui->meter2selectionCombo->show();
@ -5096,6 +5118,12 @@ void wfmain::receiveMeter(meterKind inMeter, unsigned char level)
if(ui->meter2Widget->getMeterType() == inMeter)
{
ui->meter2Widget->setLevel(level);
} else if ( (ui->meter2Widget->getMeterType() == meterAudio) &&
(inMeter == meterTxMod) && amTransmitting) {
ui->meter2Widget->setLevel(level);
} else if ( (ui->meter2Widget->getMeterType() == meterAudio) &&
(inMeter == meterRxAudio) && !amTransmitting) {
ui->meter2Widget->setLevel(level);
}
break;
}
@ -5765,7 +5793,8 @@ void wfmain::on_meter2selectionCombo_activated(int index)
} else {
ui->meter2Widget->show();
ui->meter2Widget->setMeterType(newMeterType);
insertPeriodicCommandUnique(newCmd);
if((newMeterType!=meterRxAudio) && (newMeterType!=meterTxMod) && (newMeterType!=meterAudio))
insertPeriodicCommandUnique(newCmd);
}
prefs.meter2Type = newMeterType;

Wyświetl plik

@ -275,6 +275,7 @@ private slots:
void receiveFoundRigID(rigCapabilities rigCaps);
void receiveSerialPortError(QString port, QString errorText);
void receiveStatusUpdate(networkStatus status);
void receiveNetworkAudioLevels(networkAudioLevels l);
void handlePlotClick(QMouseEvent *);
void handlePlotDoubleClick(QMouseEvent *);
void handleWFClick(QMouseEvent *);
@ -943,6 +944,7 @@ Q_DECLARE_METATYPE(struct SERVERCONFIG)
Q_DECLARE_METATYPE(struct timekind)
Q_DECLARE_METATYPE(struct datekind)
Q_DECLARE_METATYPE(struct networkStatus)
Q_DECLARE_METATYPE(struct networkAudioLevels)
Q_DECLARE_METATYPE(enum rigInput)
Q_DECLARE_METATYPE(enum meterKind)
Q_DECLARE_METATYPE(enum spectrumMode)