From 7dfac11315058913d5f52acc11f6eb1f88fbea33 Mon Sep 17 00:00:00 2001 From: Elliott Liggett Date: Tue, 30 Aug 2022 10:18:40 -0700 Subject: [PATCH] Added signal/slot communication for audio format. The rx audio handler will now send to the tx audio handler information about the speaker output hardware on the host. The tx handler is now smart enough to check if the format needs conversion or not. --- audiohandler.cpp | 7 +++++ audiohandler.h | 2 ++ pahandler.cpp | 73 +++++++++++++++++++++++++++++++++++------------- pahandler.h | 8 ++++-- rthandler.cpp | 5 ++++ rthandler.h | 2 +- udpaudio.cpp | 8 ++++-- 7 files changed, 80 insertions(+), 25 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index d5f1d36..99b13bc 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -182,6 +182,13 @@ bool audioHandler::init(audioSetup setup) return true; } +void audioHandler::acceptMonitorAudioFormat(QAudioFormat mformat) +{ + // TODO + qDebug(logAudio()) << "Error, this should not have been called: " << __PRETTY_FUNCTION__; + (void)mformat; +} + void audioHandler::start() { qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "start() running"; diff --git a/audiohandler.h b/audiohandler.h index 489ffb5..a9708e2 100644 --- a/audiohandler.h +++ b/audiohandler.h @@ -64,6 +64,7 @@ public slots: virtual void incomingAudio(const audioPacket data); virtual void convertedInput(audioPacket audio); virtual void convertedOutput(audioPacket audio); + virtual void acceptMonitorAudioFormat(QAudioFormat mformat); private slots: virtual void stateChanged(QAudio::State state); @@ -77,6 +78,7 @@ signals: void haveLevels(quint16 amplitudePeak, quint16 amplitudeRMS, quint16 latency,quint16 current,bool under,bool over); void setupConverter(QAudioFormat in, QAudioFormat out, quint8 opus, quint8 resamp); void sendToConverter(audioPacket audio); + void haveAudioFormat(QAudioFormat format); private: diff --git a/pahandler.cpp b/pahandler.cpp index a814817..1a498ec 100644 --- a/pahandler.cpp +++ b/pahandler.cpp @@ -41,6 +41,27 @@ void paHandler::setSharedAudioData(sharedAudioType *m) this->monitorFormat = m->monitorFormat; } +void paHandler::acceptMonitorAudioFormat(QAudioFormat mformat) +{ + qDebug(logAudio()) << "Monitor audio format received into tx audio handler."; + this->monitorFormat = mformat; + this->sharedAudioInfo->monitorFormat = mformat; + emit setupMonitorStreamConverter(outFormat, monitorFormat, 7, setup.resampleQuality); + connect(converterToMonitor, SIGNAL(converted(audioPacket)), this, SLOT(convertedMonitorAudio(audioPacket))); + if(checkFormatsSame(&outFormat, &monitorFormat)) + { + convertMonitorFormat = false; + } else { + convertMonitorFormat = true; + qDebug(logAudio()) << "outFormat: " << outFormat; + qDebug(logAudio()) << "monitorFormat: " << monitorFormat; + } + qInfo(logAudio()) << "Conversion for monitor audio: " << convertMonitorFormat; + + haveMonitorInformation = true; + +} + bool paHandler::init(audioSetup setup) { if (isInitialized) { @@ -210,17 +231,16 @@ bool paHandler::init(audioSetup setup) } } - if (setup.isinput) { - - err = Pa_OpenStream(&audio, &aParams, 0, outFormat.sampleRate(), this->chunkSize, paNoFlag, &paHandler::staticWrite, (void*)this); - emit setupConverter(outFormat, inFormat, 7, setup.resampleQuality); - emit setupMonitorStreamConverter(outFormat, outFormat, 7, setup.resampleQuality); - connect(converterToMonitor, SIGNAL(converted(audioPacket)), this, SLOT(convertedMonitorAudio(audioPacket))); - connect(converter, SIGNAL(converted(audioPacket)), this, SLOT(convertedInput(audioPacket))); - } - else { + if (setup.isinput) { + err = Pa_OpenStream(&audio, &aParams, 0, outFormat.sampleRate(), this->chunkSize, paNoFlag, &paHandler::staticWrite, (void*)this); + emit setupConverter(outFormat, inFormat, 7, setup.resampleQuality); + //emit setupMonitorStreamConverter(outFormat, monitorFormat, 7, setup.resampleQuality); + connect(converter, SIGNAL(converted(audioPacket)), this, SLOT(convertedInput(audioPacket))); + } + else { err = Pa_OpenStream(&audio, 0, &aParams, outFormat.sampleRate(), this->chunkSize, paNoFlag, NULL, NULL); emit setupConverter(inFormat, outFormat, 7, setup.resampleQuality); + emit haveAudioFormat(outFormat); connect(converter, SIGNAL(converted(audioPacket)), this, SLOT(convertedOutput(audioPacket))); } @@ -263,17 +283,21 @@ void paHandler::incomingAudio(audioPacket packet) // (not currently working) //convertedOutput(packet); - // Convert: (if needed) - //emit sendToMonitorConverter(packet); - - // if the formats are actually the same, no need to convert: - convertedMonitorAudio(packet); + if(haveMonitorInformation) + { + if(convertMonitorFormat) + { + // Convert format: (if needed) + emit sendToMonitorConverter(packet); + } else { + // if the formats are actually the same, no need to convert: + convertedMonitorAudio(packet); + } + } } return; } - - int paHandler::writeData(const void* inputBuffer, void* outputBuffer, unsigned long nFrames, const PaStreamCallbackTimeInfo * streamTime, PaStreamCallbackFlags status) @@ -313,12 +337,12 @@ void paHandler::mixAudio(QByteArray *dest, unsigned char *monitorSource) int size = dest->size(); float* mon = reinterpret_cast(monitorSource); float* dst = reinterpret_cast(dest->data()); - //32 bits per float sample means the size is divide by four. + // 32 bits per float sample means the size is divide by four. int floatSize = size / 4; for(int s=0; s < floatSize; s++) { - dst[s] = dst[s] + mon[s]; + dst[s] = dst[s] + sharedAudioInfo->monitorVolume*mon[s]; } } @@ -416,7 +440,6 @@ void paHandler::convertedMonitorAudio(audioPacket audio) } - void paHandler::convertedInput(audioPacket packet) { if (packet.data.size() > 0) { @@ -428,7 +451,17 @@ void paHandler::convertedInput(audioPacket packet) } } - +bool paHandler::checkFormatsSame(QAudioFormat *a, QAudioFormat *b) +{ + bool same = true; + same = same && (a->codec() == b->codec()); + same = same && (a->sampleRate() == b->sampleRate()); + same = same && (a->byteOrder() == b->byteOrder()); + same = same && (a->channelCount() == b->channelCount()); + same = same && (a->sampleSize() == b->sampleSize()); + same = same && (a->sampleType() == b->sampleType()); + return same; +} void paHandler::changeLatency(const quint16 newSize) { diff --git a/pahandler.h b/pahandler.h index cfbb1be..688532b 100644 --- a/pahandler.h +++ b/pahandler.h @@ -50,6 +50,7 @@ public slots: void convertedOutput(audioPacket audio); void convertedMonitorAudio(audioPacket audio); void incomingAudio(const audioPacket data); + void acceptMonitorAudioFormat(QAudioFormat mformat); private slots: @@ -63,6 +64,7 @@ signals: void setupMonitorStreamConverter(QAudioFormat in, QAudioFormat out, quint8 opus, quint8 resamp); void sendToConverter(audioPacket audio); void sendToMonitorConverter(audioPacket audio); + void haveAudioFormat(QAudioFormat format); private: @@ -76,8 +78,10 @@ private: } void mixAudio(QByteArray *dest, unsigned char *monitorSource); - - bool isInitialized = false; + bool checkFormatsSame(QAudioFormat *a, QAudioFormat *b); + bool convertMonitorFormat = true; + bool haveMonitorInformation = false; + bool isInitialized = false; PaStream* audio = Q_NULLPTR; PaStreamParameters aParams; const PaDeviceInfo* info; diff --git a/rthandler.cpp b/rthandler.cpp index 2a9226c..7e595df 100644 --- a/rthandler.cpp +++ b/rthandler.cpp @@ -250,6 +250,11 @@ errorHandler: } +void rtHandler::acceptMonitorAudioFormat(QAudioFormat mformat) +{ + // TODO + (void)mformat; +} void rtHandler::setVolume(unsigned char volume) { diff --git a/rthandler.h b/rthandler.h index 07749ec..b925d63 100644 --- a/rthandler.h +++ b/rthandler.h @@ -54,7 +54,7 @@ public slots: void convertedInput(audioPacket audio); void convertedOutput(audioPacket audio); void incomingAudio(const audioPacket data); - + void acceptMonitorAudioFormat(QAudioFormat mformat); private slots: diff --git a/udpaudio.cpp b/udpaudio.cpp index 2828703..d03f7da 100644 --- a/udpaudio.cpp +++ b/udpaudio.cpp @@ -23,8 +23,11 @@ udpAudio::udpAudio(QHostAddress local, QHostAddress ip, quint16 audioPort, quint monitorAudio.testNumber = 17; // TODO remove monitorAudio.monitorVolume = 0.5; monitorAudio.monitorFeatureOn = true; - monitorAudio.hostSetup = rxSetup; - monitorAudio.monitorFormat = toQAudioFormat(rxSetup.codec, rxSetup.sampleRate); + + // TODO: This is not the right format to copy, this is the radio's format, not + // the host audio format (speaker). + //monitorAudio.hostSetup = rxSetup; + //monitorAudio.monitorFormat = toQAudioFormat(rxSetup.codec, rxSetup.sampleRate); startAudio(); watchdogTimer = new QTimer(); @@ -303,6 +306,7 @@ void udpAudio::startAudio() { connect(txaudio, SIGNAL(haveLevels(quint16, quint16, quint16, quint16, bool, bool)), this, SLOT(getTxLevels(quint16, quint16, quint16, quint16, bool, bool))); connect(txAudioThread, SIGNAL(finished()), txaudio, SLOT(deleteLater())); + connect(rxaudio, SIGNAL(haveAudioFormat(QAudioFormat)), txaudio, SLOT(acceptMonitorAudioFormat(QAudioFormat))); emit setupTxAudio(txSetup); }