Non working test

merge-requests/5/head
Phil Taylor 2021-05-23 16:09:41 +01:00
rodzic f22f4224dd
commit ae69ef05e5
9 zmienionych plików z 187 dodań i 840 usunięć

Wyświetl plik

@ -1,247 +1,130 @@
/*
This class handles both RX and TX audio, each is created as a seperate instance of the class
but as the setup/handling if output (RX) and input (TX) devices is so similar I have combined them.
This class handles both RX and TX audio, each is created as a seperate instance of the class
but as the setup/handling if output (RX) and input (TX) devices is so similar I have combined them.
*/
#include "audiohandler.h"
#ifndef USE_RTAUDIO
#include "logcategories.h"
#define MULAW_BIAS 33
#define MULAW_MAX 0x1fff
audioHandler::audioHandler(QObject* parent) :
QIODevice(parent),
isInitialized(false),
audioOutput(Q_NULLPTR),
audioInput(Q_NULLPTR),
isUlaw(false),
audioLatency(0),
isInput(0),
isInitialized(false),
isUlaw(false),
audioLatency(0),
isInput(0),
chunkAvailable(false)
{
}
audioHandler::~audioHandler()
{
stop();
if (audioOutput != Q_NULLPTR) {
audioOutput->stop();
delete audioOutput;
}
if (audioInput != Q_NULLPTR) {
audioInput->stop();
delete audioInput;
}
//stop();
if (resampler != NULL) {
if (resampler != Q_NULLPTR) {
speex_resampler_destroy(resampler);
}
if (audio.isStreamRunning())
{
audio.stopStream();
}
delete buf;
}
bool audioHandler::init(const quint8 bits, const quint8 channels, const quint16 samplerate, const quint16 audioLatency, const bool ulaw, const bool isinput, int device, quint8 resampleQuality)
bool audioHandler::init(const quint8 bits, const quint8 channels, const quint16 samplerate, const quint16 latency, const bool ulaw, const bool isinput, int port, quint8 resampleQuality)
{
if (isInitialized) {
return false;
}
/* Always use 16 bit 48K samples internally*/
format.setSampleSize(16);
format.setChannelCount(channels);
format.setSampleRate(INTERNAL_SAMPLE_RATE);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);
if (isInitialized) {
return false;
}
this->audioLatency = latency;
this->isUlaw = ulaw;
this->isInput = isinput;
this->radioSampleBits = bits;
this->radioSampleRate = samplerate;
this->isInput = isinput;
this->radioSampleBits = bits;
this->radioSampleRate = samplerate;
this->radioChannels = channels;
// chunk size is always relative to Internal Sample Rate.
this->chunkSize = (INTERNAL_SAMPLE_RATE / 25) * radioChannels;
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "chunkSize: " << this->chunkSize;
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "bufferLength (latency): " << this->latency;
if (port > 0) {
aParams.deviceId = port;
}
else if (isInput) {
aParams.deviceId = audio.getDefaultInputDevice();
}
else {
aParams.deviceId = audio.getDefaultOutputDevice();
}
aParams.nChannels = channels;
aParams.firstChannel = 0;
int resample_error=0;
info = audio.getDeviceInfo(aParams.deviceId);
buf = new quint16[960];
if (info.probed)
{
qInfo(logAudio()) << (isInput ? "Input" : "Output") << QString::fromStdString(info.name) << "(" << aParams.deviceId << ") successfully probed";
if (info.nativeFormats == 0)
qInfo(logAudio()) << " No natively supported data formats!";
else {
qDebug(logAudio()) << " Supported formats:" <<
(info.nativeFormats & RTAUDIO_SINT8 ? "8-bit int," : "") <<
(info.nativeFormats & RTAUDIO_SINT16 ? "16-bit int," : "") <<
(info.nativeFormats & RTAUDIO_SINT24 ? "24-bit int," : "") <<
(info.nativeFormats & RTAUDIO_SINT32 ? "32-bit int," : "") <<
(info.nativeFormats & RTAUDIO_FLOAT32 ? "32-bit float," : "") <<
(info.nativeFormats & RTAUDIO_FLOAT64 ? "64-bit float," : "");
qInfo(logAudio()) << " Preferred sample rate:" << info.preferredSampleRate;
}
qInfo(logAudio()) << " chunkSize: " << chunkSize;
}
else
{
qCritical(logAudio()) << (isInput ? "Input" : "Output") << QString::fromStdString(info.name) << "(" << aParams.deviceId << ") could not be probed, check audio configuration!";
}
int resample_error = 0;
if (isInput) {
resampler = wf_resampler_init(radioChannels, INTERNAL_SAMPLE_RATE, samplerate, resampleQuality, &resample_error);
isInitialized = setDevice(port);
if (!isInitialized) {
qInfo(logAudio()) << "Input device " << port.deviceName() << " not found, using default";
isInitialized = setDevice(QAudioDeviceInfo::defaultInputDevice());
try {
audio.openStream(NULL, &aParams, RTAUDIO_SINT16, INTERNAL_SAMPLE_RATE, &this->chunkSize, &staticWrite);
audio.startStream();
}
catch (RtAudioError& e) {
qInfo(logAudio()) << "Error opening:" << QString::fromStdString(e.getMessage());
return false;
}
}
else
{
resampler = wf_resampler_init(radioChannels, samplerate, INTERNAL_SAMPLE_RATE, resampleQuality, &resample_error);
isInitialized = setDevice(port);
if (!isInitialized) {
qInfo(logAudio()) << "Output device " << deviceInfo.deviceName() << " not found, using default";
isInitialized = setDevice(QAudioDeviceInfo::defaultOutputDevice());
try {
unsigned int length = chunkSize / 2;
audio.openStream(&aParams, NULL, RTAUDIO_SINT16, INTERNAL_SAMPLE_RATE, &length, &staticRead);
audio.startStream();
}
catch (RtAudioError& e) {
qInfo(logAudio()) << "Error opening:" << QString::fromStdString(e.getMessage());
return false;
}
}
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "device successfully opened";
wf_resampler_get_ratio(resampler, &ratioNum, &ratioDen);
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "wf_resampler_init() returned: " << resample_error << " ratioNum" << ratioNum << " ratioDen" << ratioDen;
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "wf_resampler_init() returned: " << resample_error << " ratioNum" << ratioNum << " ratioDen" << ratioDen;
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "audio port name: " << deviceInfo.deviceName();
return isInitialized;
return isInitialized;
}
void audioHandler::setVolume(unsigned char volume)
{
//qInfo(logAudio()) << (isInput ? "Input" : "Output") << "setVolume: " << volume << "(" << (qreal)(volume/255.0) << ")";
if (audioOutput != Q_NULLPTR) {
audioOutput->setVolume((qreal)(volume / 255.0));
}
else if (audioInput != Q_NULLPTR) {
audioInput->setVolume((qreal)(volume / 255.0));
}
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "setVolume: " << volume << "(" << (qreal)(volume/255.0) << ")";
}
bool audioHandler::setDevice(QAudioDeviceInfo deviceInfo)
{
bool ret = true;
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "setDevice() running :" << deviceInfo.deviceName();
if (!deviceInfo.isFormatSupported(format)) {
if (deviceInfo.isNull())
{
qInfo(logAudio()) << "No audio device was found. You probably need to install libqt5multimedia-plugins.";
ret = false;
}
else {
/*
qInfo(logAudio()) << "Audio Devices found: ";
const auto deviceInfos = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);
for (const QAudioDeviceInfo& deviceInfo : deviceInfos)
{
qInfo(logAudio()) << "Device name: " << deviceInfo.deviceName();
qInfo(logAudio()) << "is null (probably not good):" << deviceInfo.isNull();
qInfo(logAudio()) << "channel count:" << deviceInfo.supportedChannelCounts();
qInfo(logAudio()) << "byte order:" << deviceInfo.supportedByteOrders();
qInfo(logAudio()) << "supported codecs:" << deviceInfo.supportedCodecs();
qInfo(logAudio()) << "sample rates:" << deviceInfo.supportedSampleRates();
qInfo(logAudio()) << "sample sizes:" << deviceInfo.supportedSampleSizes();
qInfo(logAudio()) << "sample types:" << deviceInfo.supportedSampleTypes();
}
qInfo(logAudio()) << "----- done with audio info -----";
*/
ret=false;
}
qInfo(logAudio()) << "Format not supported, choosing nearest supported format - which may not work!";
deviceInfo.nearestFormat(format);
}
this->deviceInfo = deviceInfo;
this->reinit();
return ret;
}
void audioHandler::reinit()
{
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "reinit() running";
if (audioOutput != Q_NULLPTR && audioOutput->state() != QAudio::StoppedState) {
this->stop();
}
if (this->isInput)
{
// (Re)initialize audio input
if (audioInput != Q_NULLPTR)
delete audioInput;
audioInput = new QAudioInput(deviceInfo, format, this);
connect(audioInput, SIGNAL(notify()), SLOT(notified()));
connect(audioInput, SIGNAL(stateChanged(QAudio::State)), SLOT(stateChanged(QAudio::State)));
}
else {
// (Re)initialize audio output
if (audioOutput != Q_NULLPTR)
delete audioOutput;
audioOutput = Q_NULLPTR;
audioOutput = new QAudioOutput(deviceInfo, format, this);
// This seems to only be needed on Linux but is critical in aligning buffer sizes.
//#ifdef Q_OS_MAC
audioOutput->setBufferSize(chunkSize*8);
//#else
// audioOutput->setBufferSize(chunkSize*4);
//#endif
connect(audioOutput, SIGNAL(notify()), SLOT(notified()));
connect(audioOutput, SIGNAL(stateChanged(QAudio::State)), SLOT(stateChanged(QAudio::State)));
}
this->start();
this->flush();
}
void audioHandler::start()
{
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "start() running";
if ((audioOutput == Q_NULLPTR || audioOutput->state() != QAudio::StoppedState) &&
(audioInput == Q_NULLPTR || audioInput->state() != QAudio::StoppedState) ) {
return;
}
if (isInput) {
//this->open(QIODevice::WriteOnly | QIODevice::Unbuffered);
this->open(QIODevice::WriteOnly);
audioInput->start(this);
}
else {
//this->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
this->open(QIODevice::ReadOnly);
audioOutput->start(this);
}
}
void audioHandler::flush()
{
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "flush() running";
this->stop();
if (isInput) {
audioInput->reset();
}
else {
audioOutput->reset();
}
QMutexLocker locker(&mutex);
audioBuffer.clear();
this->start();
}
void audioHandler::stop()
{
if (audioOutput != Q_NULLPTR && audioOutput->state() != QAudio::StoppedState) {
// Stop audio output
audioOutput->stop();
this->close();
}
if (audioInput != Q_NULLPTR && audioInput->state() != QAudio::StoppedState) {
// Stop audio output
audioInput->stop();
this->close();
}
}
/// <summary>
/// This function processes the incoming audio FROM the radio and pushes it into the playback buffer *data
@ -249,85 +132,34 @@ void audioHandler::stop()
/// <param name="data"></param>
/// <param name="maxlen"></param>
/// <returns></returns>
qint64 audioHandler::readData(char* data, qint64 maxlen)
int audioHandler::readData(void* outputBuffer, void* inputBuffer, unsigned int nFrames, double streamTime, RtAudioStreamStatus status)
{
// Calculate output length, always full samples
// Calculate output length, always full samples
int sentlen = 0;
qint16* buffer = (qint16*)outputBuffer;
qDebug(logAudio()) << "looking for: " << nFrames;
//qInfo(logAudio()) << "Looking for: " << maxlen << " bytes";
// We must lock the mutex for the entire time that the buffer may be modified.
// Get next packet from buffer.
if (!inputBuffer.isEmpty())
for (int f = 0; f < nFrames; f++)
{
// Output buffer is ALWAYS 16 bit.
QMutexLocker locker(&mutex);
auto packet = inputBuffer.begin();
while (packet != inputBuffer.end() && sentlen < maxlen)
{
int timediff = packet->time.msecsTo(QTime::currentTime());
if (timediff > (int)audioLatency * 2) {
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "Packet " << hex << packet->seq <<
" arrived too late (increase output latency!) " <<
dec << packet->time.msecsTo(QTime::currentTime()) << "ms";
while (packet !=audioBuffer.end() && timediff > (int)audioLatency) {
timediff = packet->time.msecsTo(QTime::currentTime());
lastSeq=packet->seq;
packet = inputBuffer.erase(packet); // returns next packet
}
if (packet == inputBuffer.end()) {
break;
}
}
// If we got here then packet time must be within latency threshold
if (packet->seq == lastSeq+1 || packet->seq <= lastSeq)
{
int send = qMin((int)maxlen-sentlen, packet->dataout.length() - packet->sent);
lastSeq = packet->seq;
//qInfo(logAudio()) << "Packet " << hex << packet->seq << " arrived on time " << Qt::dec << packet->time.msecsTo(QTime::currentTime()) << "ms";
memcpy(data + sentlen, packet->dataout.constData() + packet->sent, send);
sentlen = sentlen + send;
if (send == packet->dataout.length() - packet->sent)
{
//qInfo(logAudio()) << "Get next packet";
packet = inputBuffer.erase(packet); // returns next packet
}
else
{
// Store sent amount (could be zero if audioOutput buffer full) then break.
packet->sent = send;
break;
}
} else {
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "Missing audio packet(s) from: " << hex << lastSeq + 1 << " to " << hex << packet->seq - 1;
lastSeq = packet->seq;
}
}
}
else {
// Fool audio system into thinking it has valid data, this seems to be required
// for MacOS Built in audio but shouldn't cause any issues with other platforms.
memset(data, 0x0, maxlen);
return maxlen;
qDebug(logAudio()) << "*";
*buffer++ = getBuffer(f);
//*buffer++ = f;
}
return sentlen;
return 0;
}
qint64 audioHandler::writeData(const char* data, qint64 len)
quint16 audioHandler::getBuffer(int i) {
return buf[i];
}
int audioHandler::writeData(void* outputBuffer, void* inputBuffer, unsigned int nFrames, double streamTime, RtAudioStreamStatus status)
{
qint64 sentlen = 0;
int sentlen = 0;
/*
QMutexLocker locker(&mutex);
audioPacket *current;
audioPacket* current;
while (sentlen < len) {
if (!audioBuffer.isEmpty())
@ -345,37 +177,37 @@ qint64 audioHandler::writeData(const char* data, qint64 len)
}
current = &audioBuffer.last();
int send = qMin((int)(len - sentlen), (int)chunkSize-current->sent);
int send = qMin((int)(len - sentlen), (int)chunkSize - current->sent);
current->datain.append(QByteArray::fromRawData(data + sentlen, send ));
current->datain.append(QByteArray::fromRawData(data + sentlen, send));
sentlen = sentlen + send;
current->seq = 0; // Not used in TX
current->time = QTime::currentTime();
current->sent = current->datain.length();
if (current->sent == chunkSize)
{
chunkAvailable = true;
}
else if (audioBuffer.length()<=1 && current->sent != chunkSize) {
else if (audioBuffer.length() <= 1 && current->sent != chunkSize) {
chunkAvailable = false;
}
}
return (sentlen); // Always return the same number as we received
}
*/
return (sentlen); // Always return the same number as we received
}
qint64 audioHandler::bytesAvailable() const
{
return 0;
return 0;
}
bool audioHandler::isSequential() const
{
return true;
return true;
}
void audioHandler::notified()
@ -385,46 +217,13 @@ void audioHandler::notified()
void audioHandler::stateChanged(QAudio::State state)
{
// Process the state
switch (state)
{
case QAudio::IdleState:
{
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "Audio now in idle state: " << audioBuffer.length() << " packets in buffer";
if (audioOutput != Q_NULLPTR && audioOutput->error() == QAudio::UnderrunError)
{
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "buffer underrun";
audioOutput->suspend();
}
break;
}
case QAudio::ActiveState:
{
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "Audio now in active state: " << audioBuffer.length() << " packets in buffer";
break;
}
case QAudio::SuspendedState:
{
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "Audio now in suspended state: " << audioBuffer.length() << " packets in buffer";
break;
}
case QAudio::StoppedState:
{
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "Audio now in stopped state: " << audioBuffer.length() << " packets in buffer";
break;
}
default: {
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "Unhandled audio state: " << audioBuffer.length() << " packets in buffer";
}
}
}
void audioHandler::incomingAudio(audioPacket data)
{
if (audioOutput != Q_NULLPTR && audioOutput->state() != QAudio::StoppedState) {
QMutexLocker locker(&mutex);
// Incoming data is 8bits?
if (radioSampleBits == 8)
@ -446,7 +245,7 @@ void audioHandler::incomingAudio(audioPacket data)
data.datain = inPacket; // Replace incoming data with converted.
}
//qInfo(logAudio()) << "Adding packet to buffer:" << data.seq << ": " << data.datain.length();
qInfo(logAudio()) << "Adding packet to buffer:" << data.seq << ": " << data.datain.length();
/* We now have an array of 16bit samples in the NATIVE samplerate of the radio
If the radio sample rate is below 48000, we need to resample.
@ -467,42 +266,37 @@ void audioHandler::incomingAudio(audioPacket data)
err = wf_resampler_process_interleaved_int(resampler, (const qint16*)data.datain.constData(), &inFrames, (qint16*)data.dataout.data(), &outFrames);
}
if (err) {
qInfo(logAudio()) <<(isInput ? "Input" : "Output") << "Resampler error " << err << " inFrames:" << inFrames << " outFrames:" << outFrames;
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "Resampler error " << err << " inFrames:" << inFrames << " outFrames:" << outFrames;
}
}
else {
data.dataout = data.datain;
data.dataout = data.datain;
}
inputBuffer.insert(data.seq, data);
// Restart playback
if (audioOutput->state() == QAudio::SuspendedState)
{
qInfo(logAudio()) << "Output Audio Suspended, Resuming...";
audioOutput->resume();
}
}
memcpy(buf, data.dataout.constData(), data.dataout.length());
qDebug(logAudio()) << "Got data: " << data.dataout.length();
//audioBuffer.insert({ data.seq, data });
}
void audioHandler::changeLatency(const quint16 newSize)
{
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "Changing latency to: " << newSize << " from " << audioLatency;
audioLatency = newSize;
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "Changing latency to: " << newSize << " from " << audioLatency;
audioLatency = newSize;
}
void audioHandler::getLatency()
{
emit sendLatency(audioLatency);
emit sendLatency(audioLatency);
}
bool audioHandler::isChunkAvailable()
{
return (chunkAvailable);
return (chunkAvailable);
}
void audioHandler::getNextAudioChunk(QByteArray& ret)
{
/*
if (!audioBuffer.isEmpty() && chunkAvailable)
{
@ -512,18 +306,18 @@ void audioHandler::getNextAudioChunk(QByteArray& ret)
auto packet = audioBuffer.begin();
while (packet != audioBuffer.end())
{
if (packet->time.msecsTo(QTime::currentTime()) > latency) {
//qInfo(logAudio()) << "TX Packet too old " << dec << packet->time.msecsTo(QTime::currentTime()) << "ms";
if (packet->time.msecsTo(QTime::currentTime()) > 100) {
//qInfo(logAudio()) << "TX Packet too old " << dec << packet->time.msecsTo(QTime::currentTime()) << "ms";
packet = audioBuffer.erase(packet); // returns next packet
}
else {
if (packet->datain.length() == chunkSize && ret.length() == 0)
{
/* We now have an array of samples in the computer native format (48000)
If the radio sample rate is below 48000, we need to resample.
*/
// We now have an array of samples in the computer native format (48000)
// If the radio sample rate is below 48000, we need to resample.
if (ratioNum != 1)
if (ratioNum != 1)
{
// We need to resample (we are STILL 16 bit!)
quint32 outFrames = ((packet->datain.length() / 2) / ratioNum) / radioChannels;
@ -546,11 +340,11 @@ void audioHandler::getNextAudioChunk(QByteArray& ret)
//qInfo(logAudio()) << "Resampler run inLen:" << packet->datain.length() << " outLen:" << packet->dataout.length();
if (radioSampleBits == 8)
{
packet->datain=packet->dataout; // Copy output packet back to input buffer.
packet->datain = packet->dataout; // Copy output packet back to input buffer.
packet->dataout.clear(); // Buffer MUST be cleared ready to be re-filled by the upsampling below.
}
}
else if (radioSampleBits == 16 ){
else if (radioSampleBits == 16) {
// Only copy buffer if radioSampleBits is 16, as it will be handled below otherwise.
packet->dataout = packet->datain;
}
@ -575,7 +369,7 @@ void audioHandler::getNextAudioChunk(QByteArray& ret)
packet->dataout[f] = (char)outdata;
}
}
ret=packet->dataout;
ret = packet->dataout;
packet = audioBuffer.erase(packet); // returns next packet
}
else {
@ -584,8 +378,9 @@ void audioHandler::getNextAudioChunk(QByteArray& ret)
}
}
}
return;
*/
return;
}
#endif

Wyświetl plik

@ -1,32 +1,17 @@
#ifndef AUDIOHANDLER_H
#define AUDIOHANDLER_H
#define USE_RTAUDIO
#undef USE_QTAUDIO
#include <QObject>
#include <QtMultimedia/QAudioOutput>
#include <QMutexLocker>
#include <QByteArray>
#include <QtEndian>
#ifdef USE_QTAUDIO
#include <QAudioFormat>
#include <QAudioDeviceInfo>
#include <QAudioOutput>
#include <QAudioInput>
#include <QIODevice>
#endif
#ifdef USE_RTAUDIO
#include "rtaudio/RtAudio.h"
typedef signed short MY_TYPE;
#define FORMAT RTAUDIO_SINT16
#define SCALE 32767.0
#endif
#include <QThread>
#include <QTimer>
@ -774,12 +759,10 @@ struct audioPacket {
QByteArray dataout;
};
class audioHandler : public QIODevice
class audioHandler : public QObject
{
Q_OBJECT
public:
audioHandler(QObject* parent = 0);
~audioHandler();
@ -792,17 +775,27 @@ public:
void flush();
void stop();
qint64 readData(char* data, qint64 maxlen);
qint64 writeData(const char* data, qint64 len);
int readData(void* outputBuffer, void* inputBuffer, unsigned int nFrames, double streamTime, RtAudioStreamStatus status);
static int staticRead(void* outputBuffer, void* inputBuffer, unsigned int nFrames, double streamTime, RtAudioStreamStatus status, void* userData) {
return static_cast<audioHandler*>(userData)->readData(outputBuffer, inputBuffer, nFrames, streamTime, status);
}
int writeData(void* outputBuffer, void* inputBuffer, unsigned int nFrames, double streamTime, RtAudioStreamStatus status);
static int staticWrite(void* outputBuffer, void* inputBuffer, unsigned int nFrames, double streamTime, RtAudioStreamStatus status, void* userData) {
return static_cast<audioHandler*>(userData)->writeData(outputBuffer, inputBuffer, nFrames, streamTime, status);
}
qint64 bytesAvailable() const;
bool isSequential() const;
void getNextAudioChunk(QByteArray &data);
bool isChunkAvailable();
private slots:
bool init(const quint8 bits, const quint8 channels, const quint16 samplerate, const quint16 latency, const bool isulaw, const bool isinput, int port, quint8 resampleQuality);
void incomingAudio(const audioPacket data);
void changeLatency(const quint16 newSize);
private slots:
void notified();
void stateChanged(QAudio::State state);
void setVolume(unsigned char volume);
@ -815,28 +808,22 @@ signals:
private:
void reinit();
quint16 getBuffer(int);
QMutex mutex;
std::mutex mutex;
bool isInitialized;
#ifdef USE_RTAUDIO
RtAudio audio;
int audioDevice = 0;
RtAudio::StreamParameters aParams;
RtAudio::DeviceInfo info;
#elif defined(USE_QTAUDIO)
QAudioOutput* audioOutput;
QAudioInput* audioInput;
QAudioFormat format;
QAudioDeviceInfo deviceInfo;
#endif
SpeexResamplerState* resampler;
SpeexResamplerState* resampler = Q_NULLPTR;
bool isUlaw;
quint16 audioLatency;
bool isInput; // Used to determine whether input or output audio
int chunkSize;
unsigned int chunkSize;
bool chunkAvailable;
quint32 lastSeq;
@ -844,10 +831,10 @@ private:
quint16 radioSampleRate;
quint8 radioSampleBits;
quint8 radioChannels;
QVector <audioPacket> audioBuffer;
QMap<quint32, audioPacket>inputBuffer;
SpeexResamplerState* resampler=NULL;
quint16 *buf;
std::map<quint32, audioPacket>audioBuffer;
unsigned int ratioNum;
unsigned int ratioDen;

Wyświetl plik

@ -1,421 +0,0 @@
/*
This class handles both RX and TX audio, each is created as a seperate instance of the class
but as the setup/handling if output (RX) and input (TX) devices is so similar I have combined them.
*/
#include "audiohandler.h"
#include "logcategories.h"
audioHandler::audioHandler(QObject* parent) :
QIODevice(parent),
isInitialized(false),
isUlaw(false),
audioLatency(0),
isInput(0),
chunkAvailable(false)
{
}
audioHandler::~audioHandler()
{
//stop();
if (resampler) {
speex_resampler_destroy(resampler);
}
}
bool audioHandler::init(const quint8 bits, const quint8 channels, const quint16 samplerate, const quint16 latency, const bool ulaw, const bool isinput, QString port, int device, quint8 resampleQuality)
{
if (isInitialized) {
return false;
}
this->audioDevice = device;
this->audioLatency = latency;
this->isUlaw = ulaw;
this->isInput = isinput;
this->radioSampleBits = bits;
this->radioSampleRate = samplerate;
this->radioChannels = channels;
// chunk size is always relative to Internal Sample Rate.
this->chunkSize = (INTERNAL_SAMPLE_RATE / 25) * radioChannels;
if (device != 0) {
aParams.deviceId = device;
}
else if (isInput) {
aParams.deviceId = audio.getDefaultInputDevice();
}
else {
aParams.deviceId = audio.getDefaultOutputDevice();
}
info = audio.getDeviceInfo(aParams.deviceId);
if (info.probed)
{
qInfo(logAudio()) << (isInput ? "Input" : "Output") << QString::fromStdString(info.name) << "(" << aParams.deviceId << ") successfully probed";
if (info.nativeFormats == 0)
qInfo(logAudio()) << " No natively supported data formats!";
else {
qDebug(logAudio()) << " Supported formats:" <<
(info.nativeFormats & RTAUDIO_SINT8 ? "8-bit int," : "") <<
(info.nativeFormats & RTAUDIO_SINT16 ? "16-bit int," : "") <<
(info.nativeFormats & RTAUDIO_SINT24 ? "24-bit int," : "") <<
(info.nativeFormats & RTAUDIO_SINT32 ? "32-bit int," : "") <<
(info.nativeFormats & RTAUDIO_FLOAT32 ? "32-bit float," : "") <<
(info.nativeFormats & RTAUDIO_FLOAT64 ? "64-bit float," : "");
qInfo(logAudio()) << " Preferred sample rate:" << info.preferredSampleRate;
}
qInfo(logAudio()) << " chunkSize: " << chunkSize;
}
else
{
qCritical(logAudio()) << (isInput ? "Input" : "Output") << QString::fromStdString(info.name) << "(" << aParams.deviceId << ") could not be probed, check audio configuration!";
}
int resample_error = 0;
if (isInput) {
resampler = wf_resampler_init(radioChannels, INTERNAL_SAMPLE_RATE, samplerate, resampleQuality, &resample_error);
//audio.openStream(&aParams, NULL, RTAUDIO_SINT16, INTERNAL_SAMPLE_RATE, &this->chunkSize, &output, (void*)&data);
}
else
{
resampler = wf_resampler_init(radioChannels, samplerate, INTERNAL_SAMPLE_RATE, resampleQuality, &resample_error);
//audio.openStream(&aParams, NULL, RTAUDIO_SINT16, INTERNAL_SAMPLE_RATE, &this->chunkSize, &output, (void*)&data);
}
wf_resampler_get_ratio(resampler, &ratioNum, &ratioDen);
qInfo(logAudio()) << " wf_resampler_init() returned: " << resample_error << " ratioNum" << ratioNum << " ratioDen" << ratioDen;
return isInitialized;
}
void audioHandler::setVolume(unsigned char volume)
{
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "setVolume: " << volume << "(" << (qreal)(volume/255.0) << ")";
}
/// <summary>
/// This function processes the incoming audio FROM the radio and pushes it into the playback buffer *data
/// </summary>
/// <param name="data"></param>
/// <param name="maxlen"></param>
/// <returns></returns>
qint64 audioHandler::readData(char* data, qint64 maxlen)
{
// Calculate output length, always full samples
int sentlen = 0;
//qInfo(logAudio()) << "Looking for: " << maxlen << " bytes";
// We must lock the mutex for the entire time that the buffer may be modified.
// Get next packet from buffer.
if (!audioBuffer.isEmpty())
{
// Output buffer is ALWAYS 16 bit.
QMutexLocker locker(&mutex);
auto packet = audioBuffer.begin();
while (packet != audioBuffer.end() && sentlen < maxlen)
{
int timediff = packet->time.msecsTo(QTime::currentTime());
if (timediff > (int)audioLatency * 2) {
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "Packet " << hex << packet->seq <<
" arrived too late (increase output latency!) " <<
dec << packet->time.msecsTo(QTime::currentTime()) << "ms";
while (packet != audioBuffer.end() && timediff > (int)audioLatency) {
timediff = packet->time.msecsTo(QTime::currentTime());
lastSeq = packet->seq;
packet = audioBuffer.erase(packet); // returns next packet
}
if (packet == audioBuffer.end()) {
break;
}
}
// If we got here then packet time must be within latency threshold
if (packet->seq == lastSeq + 1 || packet->seq <= lastSeq)
{
int send = qMin((int)maxlen - sentlen, packet->dataout.length() - packet->sent);
lastSeq = packet->seq;
//qInfo(logAudio()) << "Packet " << hex << packet->seq << " arrived on time " << Qt::dec << packet->time.msecsTo(QTime::currentTime()) << "ms";
memcpy(data + sentlen, packet->dataout.constData() + packet->sent, send);
sentlen = sentlen + send;
if (send == packet->dataout.length() - packet->sent)
{
//qInfo(logAudio()) << "Get next packet";
packet = audioBuffer.erase(packet); // returns next packet
}
else
{
// Store sent amount (could be zero if audioOutput buffer full) then break.
packet->sent = send;
break;
}
}
else {
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "Missing audio packet(s) from: " << hex << lastSeq + 1 << " to " << hex << packet->seq - 1;
lastSeq = packet->seq;
}
}
}
else {
// Fool audio system into thinking it has valid data, this seems to be required
// for MacOS Built in audio but shouldn't cause any issues with other platforms.
memset(data, 0x0, maxlen);
return maxlen;
}
return sentlen;
}
qint64 audioHandler::writeData(const char* data, qint64 len)
{
qint64 sentlen = 0;
QMutexLocker locker(&mutex);
audioPacket* current;
while (sentlen < len) {
if (!audioBuffer.isEmpty())
{
if (audioBuffer.last().sent == chunkSize)
{
audioBuffer.append(audioPacket());
audioBuffer.last().sent = 0;
}
}
else
{
audioBuffer.append(audioPacket());
audioBuffer.last().sent = 0;
}
current = &audioBuffer.last();
int send = qMin((int)(len - sentlen), (int)chunkSize - current->sent);
current->datain.append(QByteArray::fromRawData(data + sentlen, send));
sentlen = sentlen + send;
current->seq = 0; // Not used in TX
current->time = QTime::currentTime();
current->sent = current->datain.length();
if (current->sent == chunkSize)
{
chunkAvailable = true;
}
else if (audioBuffer.length() <= 1 && current->sent != chunkSize) {
chunkAvailable = false;
}
}
return (sentlen); // Always return the same number as we received
}
qint64 audioHandler::bytesAvailable() const
{
return 0;
}
bool audioHandler::isSequential() const
{
return true;
}
void audioHandler::notified()
{
}
void audioHandler::stateChanged(QAudio::State state)
{
}
void audioHandler::incomingAudio(audioPacket data)
{
QMutexLocker locker(&mutex);
// Incoming data is 8bits?
if (radioSampleBits == 8)
{
QByteArray inPacket((int)data.datain.length() * 2, (char)0xff);
qint16* in = (qint16*)inPacket.data();
for (int f = 0; f < data.datain.length(); f++)
{
if (isUlaw)
{
in[f] = ulaw_decode[(quint8)data.datain[f]];
}
else
{
// Convert 8-bit sample to 16-bit
in[f] = (qint16)(((quint8)data.datain[f] << 8) - 32640);
}
}
data.datain = inPacket; // Replace incoming data with converted.
}
//qInfo(logAudio()) << "Adding packet to buffer:" << data.seq << ": " << data.datain.length();
/* We now have an array of 16bit samples in the NATIVE samplerate of the radio
If the radio sample rate is below 48000, we need to resample.
*/
if (ratioDen != 1) {
// We need to resample
quint32 outFrames = ((data.datain.length() / 2) * ratioDen) / radioChannels;
quint32 inFrames = (data.datain.length() / 2) / radioChannels;
data.dataout.resize(outFrames * 2 * radioChannels); // Preset the output buffer size.
int err = 0;
if (this->radioChannels == 1) {
err = wf_resampler_process_int(resampler, 0, (const qint16*)data.datain.constData(), &inFrames, (qint16*)data.dataout.data(), &outFrames);
}
else {
err = wf_resampler_process_interleaved_int(resampler, (const qint16*)data.datain.constData(), &inFrames, (qint16*)data.dataout.data(), &outFrames);
}
if (err) {
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "Resampler error " << err << " inFrames:" << inFrames << " outFrames:" << outFrames;
}
}
else {
data.dataout = data.datain;
}
audioBuffer.push_back(data);
// Sort the buffer by seq number. This is important and audio packets may have arrived out-of-order
std::sort(audioBuffer.begin(), audioBuffer.end(),
[](const audioPacket& a, const audioPacket& b) -> bool
{
return a.seq < b.seq;
});
}
void audioHandler::changeLatency(const quint16 newSize)
{
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "Changing latency to: " << newSize << " from " << audioLatency;
audioLatency = newSize;
}
void audioHandler::getLatency()
{
emit sendLatency(audioLatency);
}
bool audioHandler::isChunkAvailable()
{
return (chunkAvailable);
}
void audioHandler::getNextAudioChunk(QByteArray& ret)
{
if (!audioBuffer.isEmpty() && chunkAvailable)
{
QMutexLocker locker(&mutex);
// Skip through audio buffer deleting any old entry.
auto packet = audioBuffer.begin();
while (packet != audioBuffer.end())
{
if (packet->time.msecsTo(QTime::currentTime()) > 100) {
//qInfo(logAudio()) << "TX Packet too old " << dec << packet->time.msecsTo(QTime::currentTime()) << "ms";
packet = audioBuffer.erase(packet); // returns next packet
}
else {
if (packet->datain.length() == chunkSize && ret.length() == 0)
{
/* We now have an array of samples in the computer native format (48000)
If the radio sample rate is below 48000, we need to resample.
*/
if (ratioNum != 1)
{
// We need to resample (we are STILL 16 bit!)
quint32 outFrames = ((packet->datain.length() / 2) / ratioNum) / radioChannels;
quint32 inFrames = (packet->datain.length() / 2) / radioChannels;
packet->dataout.resize(outFrames * 2 * radioChannels); // Preset the output buffer size.
const qint16* in = (qint16*)packet->datain.constData();
qint16* out = (qint16*)packet->dataout.data();
int err = 0;
if (this->radioChannels == 1) {
err = wf_resampler_process_int(resampler, 0, in, &inFrames, out, &outFrames);
}
else {
err = wf_resampler_process_interleaved_int(resampler, in, &inFrames, out, &outFrames);
}
if (err) {
qInfo(logAudio()) << (isInput ? "Input" : "Output") << "Resampler error " << err << " inFrames:" << inFrames << " outFrames:" << outFrames;
}
//qInfo(logAudio()) << "Resampler run " << err << " inFrames:" << inFrames << " outFrames:" << outFrames;
//qInfo(logAudio()) << "Resampler run inLen:" << packet->datain.length() << " outLen:" << packet->dataout.length();
if (radioSampleBits == 8)
{
packet->datain = packet->dataout; // Copy output packet back to input buffer.
packet->dataout.clear(); // Buffer MUST be cleared ready to be re-filled by the upsampling below.
}
}
else if (radioSampleBits == 16) {
// Only copy buffer if radioSampleBits is 16, as it will be handled below otherwise.
packet->dataout = packet->datain;
}
// Do we need to convert 16-bit to 8-bit?
if (radioSampleBits == 8) {
packet->dataout.resize(packet->datain.length() / 2);
qint16* in = (qint16*)packet->datain.data();
for (int f = 0; f < packet->dataout.length(); f++)
{
quint8 outdata = 0;
if (isUlaw) {
qint16 enc = qFromLittleEndian<quint16>(in + f);
if (enc >= 0)
outdata = ulaw_encode[enc];
else
outdata = 0x7f & ulaw_encode[-enc];
}
else {
outdata = (quint8)(((qFromLittleEndian<qint16>(in + f) >> 8) ^ 0x80) & 0xff);
}
packet->dataout[f] = (char)outdata;
}
}
ret = packet->dataout;
packet = audioBuffer.erase(packet); // returns next packet
}
else {
packet++;
}
}
}
}
return;
}

Wyświetl plik

@ -43,6 +43,8 @@ struct udpPreferences {
QString password;
int audioOutput;
int audioInput;
QString audioOutputName;
QString audioInputName;
quint16 audioRXLatency;
quint16 audioTXLatency;

Wyświetl plik

@ -395,7 +395,7 @@ void udpServer::controlReceived()
connect(this, SIGNAL(setupTxAudio(quint8,quint8,quint16,quint16,bool,bool,int,quint8)), txaudio, SLOT(init(quint8,quint8,quint16,quint16,bool,bool,int,quint8)));
connect(txAudioThread, SIGNAL(finished()), txaudio, SLOT(deleteLater()));
emit setupTxAudio(samples, channels, current->txSampleRate, in->txbuffer, uLaw, false, config.audioOutput,config.audioOutputDevice, config.resampleQuality);
emit setupTxAudio(samples, channels, current->txSampleRate, in->txbuffer, uLaw, false, config.audioOutput, config.resampleQuality);
hasTxAudio=datagram.senderAddress();
connect(this, SIGNAL(haveAudioData(audioPacket)), txaudio, SLOT(incomingAudio(audioPacket)));
@ -428,7 +428,7 @@ void udpServer::controlReceived()
connect(this, SIGNAL(setupRxAudio(quint8,quint8,quint16,quint16,bool,bool,QString,int,quint8)), rxaudio, SLOT(init(quint8,quint8,quint16,quint16,bool,bool,int,quint8)));
connect(rxAudioThread, SIGNAL(finished()), txaudio, SLOT(deleteLater()));
emit setupRxAudio(samples, channels, current->rxSampleRate, 150, uLaw, true, config.audioInput, config.audioInputDevice, config.resampleQuality);
emit setupRxAudio(samples, channels, current->rxSampleRate, 150, uLaw, true, config.audioInput, config.resampleQuality);
rxAudioTimer = new QTimer();
rxAudioTimer->setTimerType(Qt::PreciseTimer);

Wyświetl plik

@ -169,7 +169,6 @@ wfmain::wfmain(const QString serialPortCL, const QString hostCL, const QString s
// Enumerate audio devices, need to do before settings are loaded.
#ifdef USE_RTAUDIO
std::map<int, std::string> apiMap;
apiMap[RtAudio::MACOSX_CORE] = "OS-X Core Audio";
apiMap[RtAudio::WINDOWS_ASIO] = "Windows ASIO";
@ -197,7 +196,7 @@ wfmain::wfmain(const QString serialPortCL, const QString hostCL, const QString s
unsigned int devices = audio.getDeviceCount();
qInfo(logAudio()) << "Found " << devices << " audio device(s) ...";
for (unsigned int i = 0; i < devices; i++) {
for (unsigned int i = 1; i < devices; i++) {
info = audio.getDeviceInfo(i);
if (info.outputChannels > 0) {
qInfo(logAudio()) << (info.isDefaultOutput ? "*" : " ") << "(" << i << ") Output Device : " << QString::fromStdString(info.name);
@ -297,8 +296,8 @@ wfmain::wfmain(const QString serialPortCL, const QString hostCL, const QString s
serverConfig.audioInput = udpPrefs.audioInput;
serverConfig.audioOutput = udpPrefs.audioOutput;
serverConfig.baudRate = prefs.serialPortBaud;
serverConfig.inputDevice = udpPrefs.inputDevice;
serverConfig.outputDevice = udpPrefs.outputDevice;
serverConfig.audioInput = udpPrefs.audioInput;
serverConfig.audioOutput = udpPrefs.audioOutput;
}
udp = new udpServer(serverConfig);
@ -952,15 +951,8 @@ void wfmain::setDefPrefs()
udpDefPrefs.audioLANPort = 50003;
udpDefPrefs.username = QString("");
udpDefPrefs.password = QString("");
#if defined(USE_RTAUDIO)
udpDefPrefs.audioOutput = QString::fromStdString(audio.getDeviceInfo(audio.getDefaultOutputDevice()).name);
udpDefPrefs.audioInput = QString::fromStdString(audio.getDeviceInfo(audio.getDefaultInputDevice()).name);
#elif defined(USE_QTAUDIO)
udpDefPrefs.audioOutput = QAudioDeviceInfo::defaultOutputDevice().deviceName();
udpDefPrefs.audioInput = QAudioDeviceInfo::defaultInputDevice().deviceName();
#endif
udpDefPrefs.audioInputDevice = 0;
udpDefPrefs.audioOutputDevice = 0;
udpDefPrefs.audioOutput = 0;
udpDefPrefs.audioInput = 0;
udpDefPrefs.audioRXLatency = 150;
udpDefPrefs.audioTXLatency = 150;
udpDefPrefs.audioRXSampleRate = 48000;
@ -1123,7 +1115,7 @@ void wfmain::loadSettings()
ui->audioSampleRateCombo->setEnabled(ui->lanEnableBtn->isChecked());
int audioSampleRateIndex = ui->audioSampleRateCombo->findText(QString::number(udpDefPrefs.audioRXSampleRate));
if (audioSampleRateIndex != -1) {
ui->audioOutputCombo->setCurrentIndex(audioSampleRateIndex);
ui->audioSampleRateCombo->setCurrentIndex(audioSampleRateIndex);
}
// Add codec combobox items here so that we can add userdata!
@ -1150,22 +1142,20 @@ void wfmain::loadSettings()
if (ui->audioTXCodecCombo->itemData(f).toInt() == udpPrefs.audioTXCodec)
ui->audioTXCodecCombo->setCurrentIndex(f);
udpPrefs.audioOutput = settings->value("AudioOutput", udpDefPrefs.audioOutput).toString();
qInfo(logGui()) << "Got Audio Output: " << udpPrefs.audioOutput;
//ui->audioOutputCombo->setEnabled(ui->lanEnableBtn->isChecked());
int audioOutputIndex = ui->audioOutputCombo->findText(udpPrefs.audioOutput);
udpPrefs.audioOutputName = settings->value("AudioOutput", udpDefPrefs.audioOutputName).toString();
qInfo(logGui()) << "Got Audio Output: " << udpPrefs.audioOutputName;
int audioOutputIndex = ui->audioOutputCombo->findText(udpPrefs.audioOutputName);
if (audioOutputIndex != -1) {
ui->audioOutputCombo->setCurrentIndex(audioOutputIndex);
udpPrefs.audioOutputDevice = ui->audioOutputCombo->itemData(audioOutputIndex).toInt();
udpPrefs.audioOutput = ui->audioOutputCombo->itemData(audioOutputIndex).toInt();
}
udpPrefs.audioInput = settings->value("AudioInput", udpDefPrefs.audioInput).toString();
qInfo(logGui()) << "Got Audio Input: " << udpPrefs.audioInput;
//ui->audioInputCombo->setEnabled(ui->lanEnableBtn->isChecked());
int audioInputIndex = ui->audioInputCombo->findText(udpPrefs.audioInput);
udpPrefs.audioInputName = settings->value("AudioInput", udpDefPrefs.audioInputName).toString();
qInfo(logGui()) << "Got Audio Input: " << udpPrefs.audioInputName;
int audioInputIndex = ui->audioInputCombo->findText(udpPrefs.audioInputName);
if (audioInputIndex != -1) {
ui->audioInputCombo->setCurrentIndex(audioInputIndex);
udpPrefs.audioInputDevice = ui->audioInputCombo->itemData(audioInputIndex).toInt();
udpPrefs.audioInput = ui->audioInputCombo->itemData(audioInputIndex).toInt();
}
udpPrefs.resampleQuality = settings->value("ResampleQuality", udpDefPrefs.resampleQuality).toInt();
@ -1279,8 +1269,8 @@ void wfmain::saveSettings()
settings->setValue("AudioRXCodec", udpPrefs.audioRXCodec);
settings->setValue("AudioTXSampleRate", udpPrefs.audioRXSampleRate);
settings->setValue("AudioTXCodec", udpPrefs.audioTXCodec);
settings->setValue("AudioOutput", udpPrefs.audioOutput);
settings->setValue("AudioInput", udpPrefs.audioInput);
settings->setValue("AudioOutput", udpPrefs.audioOutputName);
settings->setValue("AudioInput", udpPrefs.audioInputName);
settings->setValue("ResampleQuality", udpPrefs.resampleQuality);
settings->setValue("ClientName", udpPrefs.clientName);
settings->endGroup();
@ -3577,14 +3567,14 @@ void wfmain::on_passwordTxt_textChanged(QString text)
void wfmain::on_audioOutputCombo_currentIndexChanged(int value)
{
udpPrefs.audioOutput = ui->audioOutputCombo->currentText();
udpPrefs.audioOutputDevice = ui->audioOutputCombo->itemData(value).toInt();
udpPrefs.audioOutput = ui->audioOutputCombo->itemData(value).toInt();
udpPrefs.audioOutputName = ui->audioOutputCombo->itemText(value);
}
void wfmain::on_audioInputCombo_currentIndexChanged(int value)
{
udpPrefs.audioInput = ui->audioInputCombo->currentText();
udpPrefs.audioInputDevice = ui->audioOutputCombo->itemData(value).toInt();
udpPrefs.audioInput = ui->audioInputCombo->itemData(value).toInt();
udpPrefs.audioInputName = ui->audioInputCombo->itemText(value);
}
void wfmain::on_audioSampleRateCombo_currentIndexChanged(QString text)

Wyświetl plik

@ -26,7 +26,7 @@
#include "qledlabel.h"
#include "rigctld.h"
#include <qcustomplot.h>
#include <../qcustomplot/qcustomplot.h>
#include <qserialportinfo.h>
namespace Ui {
@ -705,9 +705,7 @@ private:
SERVERCONFIG serverConfig;
#ifdef USE_RTAUDIO
RtAudio audio;
#endif
};
Q_DECLARE_METATYPE(struct rigCapabilities)

Wyświetl plik

@ -374,7 +374,8 @@
</QtUic>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="audiohandler_rt.cpp" />
<ClCompile Include="..\qcustomplot\qcustomplot.cpp" />
<ClCompile Include="audiohandler.cpp" />
<ClCompile Include="calibrationwindow.cpp" />
<ClCompile Include="commhandler.cpp" />
<ClCompile Include="freqmemory.cpp" />
@ -382,14 +383,12 @@
<ClCompile Include="qledlabel.cpp" />
<ClCompile Include="logcategories.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="c:\qcustomplot\qcustomplot.cpp" />
<ClCompile Include="meter.cpp" />
<ClCompile Include="repeatersetup.cpp" />
<ClCompile Include="resampler\resample.c" />
<ClCompile Include="rigcommander.cpp" />
<ClCompile Include="rigctld.cpp" />
<ClCompile Include="rigidentities.cpp" />
<ClCompile Include="audiohandler.cpp" />
<ClCompile Include="rtaudio\RtAudio.cpp" />
<ClCompile Include="satellitesetup.cpp" />
<ClCompile Include="udphandler.cpp" />
@ -398,6 +397,7 @@
<ClCompile Include="wfmain.cpp" />
</ItemGroup>
<ItemGroup>
<QtMoc Include="..\qcustomplot\qcustomplot.h" />
<ClInclude Include="rtaudio\RtAudio.h" />
<QtMoc Include="udpserver.h" />
<QtMoc Include="udpserversetup.h" />
@ -409,8 +409,6 @@
<ClInclude Include="freqmemory.h" />
<QtMoc Include="qledlabel.h" />
<ClInclude Include="logcategories.h" />
<QtMoc Include="c:\qcustomplot\qcustomplot.h">
</QtMoc>
<QtMoc Include="rigcommander.h">
</QtMoc>
<QtMoc Include="meter.h" />

Wyświetl plik

@ -69,9 +69,6 @@
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="c:\qcustomplot\qcustomplot.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="rigcommander.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -84,9 +81,6 @@
<ClCompile Include="wfmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="audiohandler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="calibrationwindow.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -120,7 +114,10 @@
<ClCompile Include="rtaudio\RtAudio.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="audiohandler_rt.cpp">
<ClCompile Include="audiohandler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\qcustomplot\qcustomplot.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
@ -134,9 +131,6 @@
<ClInclude Include="logcategories.h">
<Filter>Header Files</Filter>
</ClInclude>
<QtMoc Include="c:\qcustomplot\qcustomplot.h">
<Filter>Header Files</Filter>
</QtMoc>
<QtMoc Include="rigcommander.h">
<Filter>Header Files</Filter>
</QtMoc>
@ -179,6 +173,9 @@
<QtMoc Include="rigctld.h">
<Filter>Header Files</Filter>
</QtMoc>
<QtMoc Include="..\qcustomplot\qcustomplot.h">
<Filter>Header Files</Filter>
</QtMoc>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="debug\moc_predefs.h.cbt">
@ -359,6 +356,7 @@
<None Include="resources\wfview.png" />
<None Include="resources\wfview.png" />
<None Include="resources\wfview.png" />
<None Include="resources\wfview.png" />
</ItemGroup>
<ItemGroup>
<None Include="resources\install.sh">