kopia lustrzana https://gitlab.com/eliggett/wfview
194 wiersze
6.0 KiB
C++
194 wiersze
6.0 KiB
C++
#include "tciaudiohandler.h"
|
|
|
|
#include "logcategories.h"
|
|
#include "tciserver.h"
|
|
|
|
|
|
tciAudioHandler::tciAudioHandler(QObject* parent)
|
|
{
|
|
Q_UNUSED(parent)
|
|
}
|
|
|
|
tciAudioHandler::~tciAudioHandler()
|
|
{
|
|
|
|
if (converterThread != Q_NULLPTR) {
|
|
converterThread->quit();
|
|
converterThread->wait();
|
|
}
|
|
|
|
}
|
|
|
|
bool tciAudioHandler::init(audioSetup setup)
|
|
{
|
|
if (isInitialized) {
|
|
return false;
|
|
}
|
|
|
|
this->setup = setup;
|
|
qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "TCI Audio handler starting:" << setup.name;
|
|
|
|
radioFormat = toQAudioFormat(setup.codec, setup.sampleRate);
|
|
|
|
qDebug(logAudio()) << "Creating" << (setup.isinput ? "Input" : "Output") << "audio device:" << setup.name <<
|
|
#if (QT_VERSION < QT_VERSION_CHECK(6,0,0))
|
|
", bits" << radioFormat.sampleSize() <<
|
|
#else
|
|
", format" << radioFormat.sampleFormat() <<
|
|
#endif
|
|
", codec" << setup.codec <<
|
|
", latency" << setup.latency <<
|
|
", localAFGain" << setup.localAFgain <<
|
|
", radioChan" << radioFormat.channelCount() <<
|
|
", resampleQuality" << setup.resampleQuality <<
|
|
", samplerate" << radioFormat.sampleRate() <<
|
|
", uLaw" << setup.ulaw;
|
|
|
|
codecType codec = LPCM;
|
|
if (setup.codec == 0x01 || setup.codec == 0x20)
|
|
codec = PCMU;
|
|
else if (setup.codec == 0x40 || setup.codec == 0x40)
|
|
codec = OPUS;
|
|
|
|
if (setup.isinput)
|
|
nativeFormat.setChannelCount(2);
|
|
else
|
|
nativeFormat.setChannelCount(2);
|
|
|
|
nativeFormat.setSampleRate(48000);
|
|
|
|
this->setVolume(setup.localAFgain);
|
|
|
|
#if (QT_VERSION < QT_VERSION_CHECK(6,0,0))
|
|
nativeFormat.setSampleType(QAudioFormat::Float);
|
|
nativeFormat.setSampleSize(32);
|
|
#else
|
|
nativeFormat.setSampleFormat(QAudioFormat::Float);
|
|
#endif
|
|
|
|
converter = new audioConverter();
|
|
converterThread = new QThread(this);
|
|
if (setup.isinput) {
|
|
converterThread->setObjectName("audioConvIn()");
|
|
}
|
|
else {
|
|
converterThread->setObjectName("audioConvOut()");
|
|
}
|
|
converter->moveToThread(converterThread);
|
|
|
|
connect(this, SIGNAL(setupConverter(QAudioFormat,codecType,QAudioFormat,codecType,quint8,quint8)), converter, SLOT(init(QAudioFormat,codecType,QAudioFormat,codecType,quint8,quint8)));
|
|
connect(converterThread, SIGNAL(finished()), converter, SLOT(deleteLater()));
|
|
connect(this, SIGNAL(sendToConverter(audioPacket)), converter, SLOT(convert(audioPacket)));
|
|
converterThread->start(QThread::TimeCriticalPriority);
|
|
|
|
if (setup.isinput) {
|
|
emit setupConverter(nativeFormat, codecType::LPCM, radioFormat, codec, 7, setup.resampleQuality);
|
|
connect(converter, SIGNAL(converted(audioPacket)), this, SLOT(convertedInput(audioPacket)));
|
|
if (setup.tci != Q_NULLPTR) {
|
|
connect((tciServer*)setup.tci, SIGNAL(sendTCIAudio(QByteArray)), this, SLOT(receiveTCIAudio(QByteArray)));
|
|
//connect(this,SIGNAL(setupTxPacket(int)), (tciServer*)setup.tci, SLOT(setupTxPacket(int)));
|
|
//emit setupTxPacket((nativeFormat.bytesForDuration(setup.blockSize * 1000)*2)/sizeof(float));
|
|
} else {
|
|
qCritical(logAudio()) << "***** TCI NOT FOUND *****";
|
|
}
|
|
}
|
|
else {
|
|
emit setupConverter(radioFormat, codec, nativeFormat, codecType::LPCM, 7, setup.resampleQuality);
|
|
connect(converter, SIGNAL(converted(audioPacket)), this, SLOT(convertedOutput(audioPacket)));
|
|
if (setup.tci != Q_NULLPTR) {
|
|
connect(this,SIGNAL(sendTCIAudio(audioPacket)), (tciServer*)setup.tci, SLOT(receiveTCIAudio(audioPacket)));
|
|
} else {
|
|
qCritical(logAudio()) << "***** TCI NOT FOUND *****";
|
|
}
|
|
}
|
|
|
|
|
|
return isInitialized;
|
|
}
|
|
|
|
void tciAudioHandler::setVolume(unsigned char volume)
|
|
{
|
|
this->volume = audiopot[volume];
|
|
}
|
|
|
|
void tciAudioHandler::incomingAudio(audioPacket packet)
|
|
{
|
|
packet.volume = volume;
|
|
emit sendToConverter(packet);
|
|
return;
|
|
}
|
|
|
|
void tciAudioHandler::convertedOutput(audioPacket packet)
|
|
{
|
|
arrayBuffer.append(packet.data);
|
|
amplitude = packet.amplitudePeak;
|
|
currentLatency = 0;
|
|
emit haveLevels(getAmplitude(), packet.amplitudeRMS, setup.latency, currentLatency, isUnderrun, isOverrun);
|
|
if (arrayBuffer.length() >= TCI_AUDIO_LENGTH * sizeof(float)) {
|
|
packet.data.clear();
|
|
packet.data = arrayBuffer.mid(0, TCI_AUDIO_LENGTH * sizeof(float));
|
|
arrayBuffer.remove(0, TCI_AUDIO_LENGTH * sizeof(float));
|
|
emit sendTCIAudio(packet);
|
|
}
|
|
}
|
|
|
|
|
|
void tciAudioHandler::convertedInput(audioPacket packet)
|
|
{
|
|
if (packet.data.size() > 0) {
|
|
emit haveAudioData(packet);
|
|
amplitude = packet.amplitudePeak;
|
|
currentLatency = 0;
|
|
emit haveLevels(getAmplitude(), static_cast<quint16>(packet.amplitudeRMS * 255.0), setup.latency, currentLatency, isUnderrun, isOverrun);
|
|
}
|
|
}
|
|
|
|
void tciAudioHandler::getNextAudio()
|
|
{
|
|
if (tempBuf.data.length() >= nativeFormat.bytesForDuration(setup.blockSize * 1000)) {
|
|
audioPacket packet;
|
|
packet.time = QTime::currentTime();
|
|
packet.sent = 0;
|
|
packet.volume = volume;
|
|
memcpy(&packet.guid, setup.guid, GUIDLEN);
|
|
packet.data.clear();
|
|
audioMutex.lock();
|
|
packet.data = tempBuf.data.mid(0, nativeFormat.bytesForDuration(setup.blockSize * 1000));
|
|
tempBuf.data.remove(0, nativeFormat.bytesForDuration(setup.blockSize * 1000));
|
|
audioMutex.unlock();
|
|
emit sendToConverter(packet);
|
|
}
|
|
/* If there is still enough data in the buffer, call myself again in 20ms */
|
|
if (tempBuf.data.length() >= nativeFormat.bytesForDuration(setup.blockSize * 1000)) {
|
|
QTimer::singleShot(setup.blockSize, this, &tciAudioHandler::getNextAudio);
|
|
}
|
|
}
|
|
|
|
void tciAudioHandler::receiveTCIAudio(const QByteArray packet) {
|
|
|
|
|
|
if (packet.size() > 0) {
|
|
audioMutex.lock();
|
|
tempBuf.data.append(packet);
|
|
audioMutex.unlock();
|
|
}
|
|
|
|
getNextAudio();
|
|
}
|
|
|
|
|
|
void tciAudioHandler::changeLatency(const quint16 newSize)
|
|
{
|
|
qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Changing latency to: " << newSize << " from " << setup.latency;
|
|
}
|
|
|
|
int tciAudioHandler::getLatency()
|
|
{
|
|
return currentLatency;
|
|
}
|
|
|
|
quint16 tciAudioHandler::getAmplitude()
|
|
{
|
|
return static_cast<quint16>(amplitude * 255.0);
|
|
}
|