From f8beed5531ec3352d52ad2fecdb3add650b96a3c Mon Sep 17 00:00:00 2001 From: Steve Netting Date: Wed, 26 May 2021 16:21:32 +0300 Subject: [PATCH 01/77] added Fedora build/install notes --- INSTALL.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/INSTALL.md b/INSTALL.md index e725619..050a71b 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -99,3 +99,27 @@ in this case, use your homedir: wfview is now installed in /usr/local/bin --- + +### Fedora install ### +--- + +Tested under Fedora 33/34. + +Install qt5 dependencies: +- sudo dnf install qt5-qtbase-common qt5-qtbase qt5-qtbase-gui qt5-qtserialport qt5-qtmultimedia mingw64-qt5-qmake qt5-qtbase-devel qt5-qtserialport-devel qt5-qtmultimedia-devel + +Install qcustomplot: +- sudo dnf install qcustomplot qcustomplot-devel + +When done, create a build area, clone the repo, build and install: + +- mkdir -p ~/src/build && cd src +- git clone https://gitlab.com/eliggett/wfview.git +- cd build +- qmake-qt5 ../wfview/wfview.pro +- make -j +- sudo ./install.sh + +wfview is now installed in /usr/local/bin + +--- From 869659ad54c0cbddfa888bf18e09a3d137c88040 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Wed, 16 Jun 2021 09:49:38 +0100 Subject: [PATCH 02/77] Add opus encoding/decoding --- audiohandler.cpp | 67 ++++++++++++++++++++++++++++++++++++++++++++++-- audiohandler.h | 3 +++ wfmain.cpp | 3 +++ wfview.pro | 8 ++++-- wfview.vcxproj | 20 +++++++-------- 5 files changed, 87 insertions(+), 14 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index f051830..ccee899 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -40,7 +40,12 @@ audioHandler::~audioHandler() speex_resampler_destroy(resampler); qDebug(logAudio()) << "Resampler closed"; } - + if (encoder != Q_NULLPTR) { + opus_encoder_destroy(encoder); + } + if (decoder != Q_NULLPTR) { + opus_decoder_destroy(decoder); + } } bool audioHandler::init(audioSetup setupIn) @@ -71,6 +76,14 @@ bool audioHandler::init(audioSetup setupIn) if (setup.codec == 0x04 || setup.codec == 0x10) { setup.bits = 16; } + if (setup.codec == 0x40 || setup.codec == 0x80) + { + setup.bits = 16; + } + if (setup.codec == 0x80) + { + setup.radioChan = 2; + } ringBuf = new wilt::Ring(100); // Should be customizable. @@ -264,6 +277,8 @@ void audioHandler::start() return; } + int err = 0; + if (setup.isinput) { #ifdef Q_OS_MACX this->open(QIODevice::WriteOnly); @@ -271,6 +286,10 @@ void audioHandler::start() this->open(QIODevice::WriteOnly | QIODevice::Unbuffered); #endif audioInput->start(this); + if (setup.codec == 0x40 || setup.codec == 0x80) { + // Opus codec + encoder = opus_encoder_create(setup.samplerate, setup.radioChan, OPUS_APPLICATION_AUDIO, &err); + } } else { #ifdef Q_OS_MACX @@ -279,6 +298,14 @@ void audioHandler::start() this->open(QIODevice::ReadOnly | QIODevice::Unbuffered); #endif audioOutput->start(this); + if (setup.codec == 0x40 || setup.codec == 0x80) { + // Opus codec + decoder = opus_decoder_create(setup.samplerate, setup.radioChan, &err); + } + } + if (err < 0) + { + fprintf(stderr, "failed to create opus encoder or decoder: %s\n", opus_strerror(err)); } } #endif @@ -449,12 +476,30 @@ void audioHandler::incomingAudio(audioPacket inPacket) qDebug(logAudio()) << "Packet received when stream was not ready"; return; } + + if (setup.codec == 0x40 || setup.codec == 0x80) { + /* Encode the frame. */ + QByteArray outPacket(chunkSize * setup.radioChan * 2, (char)0xff); // Preset the output buffer size. + qint16* in = (qint16*)inPacket.data.data(); + unsigned char* out = (unsigned char*)outPacket.data(); + + int nbBytes = opus_decode(decoder, out, outPacket.length() / 2, in, inPacket.data.length(),0); + if (nbBytes < 0) + { + qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus encode failed:" << opus_strerror(nbBytes); + return; + } + outPacket.resize(nbBytes); + inPacket.data.clear(); + inPacket.data = outPacket; // Replace incoming data with converted. + } + //qDebug(logAudio()) << "Got" << radioSampleBits << "bits, length" << inPacket.data.length(); // Incoming data is 8bits? if (setup.bits == 8) { // Current packet is 8bit so need to create a new buffer that is 16bit - QByteArray outPacket((int)inPacket.data.length() * 2 *(devChannels/setup.radioChan), (char)0xff); + QByteArray outPacket((int)inPacket.data.length() * 2 * (devChannels / setup.radioChan), (char)0xff); qint16* out = (qint16*)outPacket.data(); for (int f = 0; f < inPacket.data.length(); f++) { @@ -625,6 +670,24 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) packet.data.clear(); packet.data = outPacket; // Copy output packet back to input buffer. } + + if (setup.codec == 0x40 || setup.codec == 0x80) { + /* Encode the frame. */ + QByteArray outPacket(packet.data.length() * 2, (char)0xff); // Preset the output buffer size. + qint16* in = (qint16*)packet.data.data(); + unsigned char* out = (unsigned char*)outPacket.data(); + + int nbBytes = opus_encode(encoder, in, packet.data.length() / 2, out, outPacket.length()); + if (nbBytes < 0) + { + qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus encode failed:" << opus_strerror(nbBytes); + return; + } + outPacket.resize(nbBytes); + packet.data.clear(); + packet.data = outPacket; // Replace incoming data with converted. + } + ret = packet.data; //qDebug(logAudio()) << "Now radio format, length" << packet.data.length(); } diff --git a/audiohandler.h b/audiohandler.h index 36993a5..740ce38 100644 --- a/audiohandler.h +++ b/audiohandler.h @@ -33,6 +33,7 @@ typedef signed short MY_TYPE; #include #include "resampler/speex_resampler.h" #include "ring/ring.h" +#include "opus.h" #include @@ -179,6 +180,8 @@ private: qreal volume=1.0; int devChannels; audioSetup setup; + OpusEncoder* encoder=Q_NULLPTR; + OpusDecoder* decoder=Q_NULLPTR; }; #endif // AUDIOHANDLER_H diff --git a/wfmain.cpp b/wfmain.cpp index ab42e4c..d8a8c4d 100644 --- a/wfmain.cpp +++ b/wfmain.cpp @@ -1234,6 +1234,8 @@ void wfmain::loadSettings() ui->audioRXCodecCombo->addItem("LPCM 2ch 16bit", 16); ui->audioRXCodecCombo->addItem("uLaw 2ch 8bit", 32); ui->audioRXCodecCombo->addItem("PCM 2ch 8bit", 8); + ui->audioRXCodecCombo->addItem("Opus 1ch", 64); + ui->audioRXCodecCombo->addItem("Opus 2ch", 128); ui->audioRXCodecCombo->blockSignals(true); rxSetup.codec = settings->value("AudioRXCodec", "4").toInt(); @@ -1246,6 +1248,7 @@ void wfmain::loadSettings() ui->audioTXCodecCombo->addItem("LPCM 1ch 16bit", 4); ui->audioTXCodecCombo->addItem("LPCM 1ch 8bit", 2); ui->audioTXCodecCombo->addItem("uLaw 1ch 8bit", 1); + ui->audioTXCodecCombo->addItem("Opus 1ch", 64); ui->audioRXCodecCombo->blockSignals(true); txSetup.codec = settings->value("AudioTXCodec", "4").toInt(); diff --git a/wfview.pro b/wfview.pro index 1e0aed9..a487ae7 100644 --- a/wfview.pro +++ b/wfview.pro @@ -92,13 +92,15 @@ linux:QMAKE_POST_LINK += echo; echo; echo "Run install.sh as root from the build CONFIG(debug, release|debug) { linux: QCPLIB = qcustomplotd + win32:LIBS += -L../opus/win32/VS2015/Win32/Debug/ -lopus } else { linux: QCPLIB = qcustomplot + win32:LIBS += -L../opus/win32/VS2015/Win32/Release/ -lopus } #linux:LIBS += -L./ -l$$QCPLIB -lpulse -lpulse-simple -lpthread -linux:LIBS += -L./ -l$$QCPLIB -macx:LIBS += -framework CoreAudio -framework CoreFoundation -lpthread +linux:LIBS += -L./ -l$$QCPLIB -lopus +macx:LIBS += -framework CoreAudio -framework CoreFoundation -lpthread -lopus #win32:SOURCES += rtaudio/RTAudio.cpp #win32:HEADERS += rtaudio/RTAUdio.h @@ -106,6 +108,8 @@ macx:LIBS += -framework CoreAudio -framework CoreFoundation -lpthread !linux:HEADERS += ../qcustomplot/qcustomplot.h !linux:INCLUDEPATH += ../qcustomplot +!linux:INCLUDEPATH += ../opus/include + INCLUDEPATH += resampler !linux:INCLUDEPATH += rtaudio diff --git a/wfview.vcxproj b/wfview.vcxproj index 2502415..dbf5fb4 100644 --- a/wfview.vcxproj +++ b/wfview.vcxproj @@ -48,7 +48,7 @@ - .;..\qcustomplot;resampler;rtaudio;release;/include;%(AdditionalIncludeDirectories) + .;..\qcustomplot;..\opus\include;resampler;rtaudio;release;/include;%(AdditionalIncludeDirectories) -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 %(AdditionalOptions) release\ false @@ -57,7 +57,7 @@ Sync release\ MaxSpeed - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;__WINDOWS_WASAPI__;GITSHORT="ea09e1f";HOST="wfview.org";UNAME="build";QT_NO_DEBUG;NDEBUG;%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;__WINDOWS_WASAPI__;GITSHORT="8cd64c2";HOST="wfview.org";UNAME="build";QT_NO_DEBUG;NDEBUG;%(PreprocessorDefinitions) false MultiThreadedDLL @@ -66,8 +66,8 @@ Level3 true - shell32.lib;%(AdditionalDependencies) - C:\opensslx86\lib;C:\Utils\my_sql\mysql-5.6.11-win32\lib;C:\Utils\postgresqlx86\pgsql\lib;%(AdditionalLibraryDirectories) + ..\opus\win32\VS2015\Win32\Release\opus.lib;shell32.lib;%(AdditionalDependencies) + ..\opus\win32\VS2015\Win32\Release;C:\opensslx86\lib;C:\Utils\my_sql\mysql-5.6.11-win32\lib;C:\Utils\postgresqlx86\pgsql\lib;%(AdditionalLibraryDirectories) "/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions) true false @@ -84,12 +84,12 @@ 0 - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;__WINDOWS_WASAPI__;GITSHORT=\"ea09e1f\";HOST=\"wfview.org\";UNAME=\"build\";QT_NO_DEBUG;QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;__WINDOWS_WASAPI__;GITSHORT=\"8cd64c2\";HOST=\"wfview.org\";UNAME=\"build\";QT_NO_DEBUG;QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;%(PreprocessorDefinitions) msvc./$(Configuration)/moc_predefs.hMoc'ing %(Identity)...output$(Configuration)moc_%(Filename).cppdefaultRcc'ing %(Identity)...$(Configuration)qrc_%(Filename).cppUic'ing %(Identity)...$(ProjectDir)ui_%(Filename).h - .;..\qcustomplot;resampler;rtaudio;debug;/include;%(AdditionalIncludeDirectories) + .;..\qcustomplot;..\opus\include;resampler;rtaudio;debug;/include;%(AdditionalIncludeDirectories) -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 %(AdditionalOptions) debug\ false @@ -98,7 +98,7 @@ Sync debug\ Disabled - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;__WINDOWS_WASAPI__;GITSHORT="ea09e1f";HOST="wfview.org";UNAME="build";%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;__WINDOWS_WASAPI__;GITSHORT="8cd64c2";HOST="wfview.org";UNAME="build";%(PreprocessorDefinitions) false MultiThreadedDebugDLL true @@ -106,8 +106,8 @@ Level3 true - shell32.lib;%(AdditionalDependencies) - C:\opensslx86\lib;C:\Utils\my_sql\mysql-5.6.11-win32\lib;C:\Utils\postgresqlx86\pgsql\lib;%(AdditionalLibraryDirectories) + ..\opus\win32\VS2015\Win32\Debug\opus.lib;shell32.lib;%(AdditionalDependencies) + ..\opus\win32\VS2015\Win32\Debug;C:\opensslx86\lib;C:\Utils\my_sql\mysql-5.6.11-win32\lib;C:\Utils\postgresqlx86\pgsql\lib;%(AdditionalLibraryDirectories) "/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions) true true @@ -123,7 +123,7 @@ 0 - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;__WINDOWS_WASAPI__;GITSHORT=\"ea09e1f\";HOST=\"wfview.org\";UNAME=\"build\";QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;_DEBUG;%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;__WINDOWS_WASAPI__;GITSHORT=\"8cd64c2\";HOST=\"wfview.org\";UNAME=\"build\";QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;_DEBUG;%(PreprocessorDefinitions) msvc./$(Configuration)/moc_predefs.hMoc'ing %(Identity)...output$(Configuration)moc_%(Filename).cppdefaultRcc'ing %(Identity)...$(Configuration)qrc_%(Filename).cppUic'ing %(Identity)...$(ProjectDir)ui_%(Filename).h From 55a38c55ea8f352d30de5d83fe323d5210194110 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Wed, 16 Jun 2021 09:52:47 +0100 Subject: [PATCH 03/77] Fix opus include directory --- audiohandler.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/audiohandler.h b/audiohandler.h index 740ce38..8a22fed 100644 --- a/audiohandler.h +++ b/audiohandler.h @@ -33,8 +33,11 @@ typedef signed short MY_TYPE; #include #include "resampler/speex_resampler.h" #include "ring/ring.h" +#ifdef Q_OS_WIN #include "opus.h" - +#else +#include "opus/opus.h" +#endif #include From 6a5e7692e63ce63881e56eada5f17927829287a8 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Wed, 16 Jun 2021 10:33:16 +0100 Subject: [PATCH 04/77] Fixes for opus --- audiohandler.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index ccee899..94e9f2c 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -483,10 +483,10 @@ void audioHandler::incomingAudio(audioPacket inPacket) qint16* in = (qint16*)inPacket.data.data(); unsigned char* out = (unsigned char*)outPacket.data(); - int nbBytes = opus_decode(decoder, out, outPacket.length() / 2, in, inPacket.data.length(),0); + int nbBytes = opus_decode(decoder, out, outPacket.length(), in, inPacket.data.length()/2,0); if (nbBytes < 0) { - qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus encode failed:" << opus_strerror(nbBytes); + qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decode failed:" << opus_strerror(nbBytes); return; } outPacket.resize(nbBytes); @@ -564,8 +564,11 @@ void audioHandler::incomingAudio(audioPacket inPacket) if (err) { qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Resampler error " << err << " inFrames:" << inFrames << " outFrames:" << outFrames; } - inPacket.data.clear(); - inPacket.data = outPacket; // Replace incoming data with converted. + else { + inPacket.data.clear(); + inPacket.data = outPacket; // Replace incoming data with converted. + qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoded" << inPacket.data.length() << "bytes, into" << outPacket.length() << "bytes"; + } } //qDebug(logAudio()) << "Adding packet to buffer:" << inPacket.seq << ": " << inPacket.data.length(); @@ -673,7 +676,7 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) if (setup.codec == 0x40 || setup.codec == 0x80) { /* Encode the frame. */ - QByteArray outPacket(packet.data.length() * 2, (char)0xff); // Preset the output buffer size. + QByteArray outPacket(638*setup.radioChan, (char)0xff); // Preset the output buffer size. qint16* in = (qint16*)packet.data.data(); unsigned char* out = (unsigned char*)outPacket.data(); @@ -683,9 +686,12 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus encode failed:" << opus_strerror(nbBytes); return; } - outPacket.resize(nbBytes); - packet.data.clear(); - packet.data = outPacket; // Replace incoming data with converted. + else { + outPacket.resize(nbBytes); + packet.data.clear(); + packet.data = outPacket; // Replace incoming data with converted. + qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus encoded" << packet.data.length() << "bytes, into" << outPacket.length() << "bytes"; + } } ret = packet.data; From 579d670a75fa50057eb9b74264034ff31e15c7e8 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Wed, 16 Jun 2021 10:35:45 +0100 Subject: [PATCH 05/77] Another opus try --- audiohandler.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index 94e9f2c..515117b 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -486,12 +486,15 @@ void audioHandler::incomingAudio(audioPacket inPacket) int nbBytes = opus_decode(decoder, out, outPacket.length(), in, inPacket.data.length()/2,0); if (nbBytes < 0) { - qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decode failed:" << opus_strerror(nbBytes); + qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decode failed:" << opus_strerror(nbBytes) << "packet size" << inPacket.data.length(); return; } - outPacket.resize(nbBytes); - inPacket.data.clear(); - inPacket.data = outPacket; // Replace incoming data with converted. + else { + outPacket.resize(nbBytes); + inPacket.data.clear(); + inPacket.data = outPacket; // Replace incoming data with converted. + qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoded" << inPacket.data.length() << "bytes, into" << outPacket.length() << "bytes"; + } } //qDebug(logAudio()) << "Got" << radioSampleBits << "bits, length" << inPacket.data.length(); @@ -564,11 +567,8 @@ void audioHandler::incomingAudio(audioPacket inPacket) if (err) { qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Resampler error " << err << " inFrames:" << inFrames << " outFrames:" << outFrames; } - else { - inPacket.data.clear(); - inPacket.data = outPacket; // Replace incoming data with converted. - qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoded" << inPacket.data.length() << "bytes, into" << outPacket.length() << "bytes"; - } + inPacket.data.clear(); + inPacket.data = outPacket; // Replace incoming data with converted. } //qDebug(logAudio()) << "Adding packet to buffer:" << inPacket.seq << ": " << inPacket.data.length(); From d3db0484af6f7c95da77259cbd6c3e5d886e0662 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Wed, 16 Jun 2021 10:38:54 +0100 Subject: [PATCH 06/77] Another opus fix --- audiohandler.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index 515117b..4cf1350 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -491,9 +491,9 @@ void audioHandler::incomingAudio(audioPacket inPacket) } else { outPacket.resize(nbBytes); + qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoded" << inPacket.data.length() << "bytes, into" << outPacket.length() << "bytes"; inPacket.data.clear(); inPacket.data = outPacket; // Replace incoming data with converted. - qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoded" << inPacket.data.length() << "bytes, into" << outPacket.length() << "bytes"; } } @@ -688,9 +688,9 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) } else { outPacket.resize(nbBytes); + qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus encoded" << packet.data.length() << "bytes, into" << outPacket.length() << "bytes"; packet.data.clear(); packet.data = outPacket; // Replace incoming data with converted. - qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus encoded" << packet.data.length() << "bytes, into" << outPacket.length() << "bytes"; } } From db1dbef168c8ff27e10aba80c9fb664c745bf0ea Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Wed, 16 Jun 2021 19:00:56 +0100 Subject: [PATCH 07/77] Try converting to Big endian first --- audiohandler.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index 4cf1350..064c952 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -478,9 +478,14 @@ void audioHandler::incomingAudio(audioPacket inPacket) } if (setup.codec == 0x40 || setup.codec == 0x80) { + + qint16* in = (qint16*)inPacket.data.data(); + for (int i = 0; i < inPacket.data.length() / 2; i++) + { + in[i] = qToLittleEndian(in[i]); + } /* Encode the frame. */ QByteArray outPacket(chunkSize * setup.radioChan * 2, (char)0xff); // Preset the output buffer size. - qint16* in = (qint16*)inPacket.data.data(); unsigned char* out = (unsigned char*)outPacket.data(); int nbBytes = opus_decode(decoder, out, outPacket.length(), in, inPacket.data.length()/2,0); @@ -675,9 +680,14 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) } if (setup.codec == 0x40 || setup.codec == 0x80) { + + qint16* in = (qint16*)packet.data.data(); + // Convert from little endian + for (int i = 0; i < packet.data.length()/2; i++) + in[i] = qToBigEndian(in[i]); + /* Encode the frame. */ QByteArray outPacket(638*setup.radioChan, (char)0xff); // Preset the output buffer size. - qint16* in = (qint16*)packet.data.data(); unsigned char* out = (unsigned char*)outPacket.data(); int nbBytes = opus_encode(encoder, in, packet.data.length() / 2, out, outPacket.length()); From 7c0b2a51b191e94c16e78e4480956acdab3d67b4 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Wed, 16 Jun 2021 19:14:21 +0100 Subject: [PATCH 08/77] Another attempt for Opus audio --- audiohandler.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index 064c952..84e9ad3 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -479,16 +479,16 @@ void audioHandler::incomingAudio(audioPacket inPacket) if (setup.codec == 0x40 || setup.codec == 0x80) { - qint16* in = (qint16*)inPacket.data.data(); - for (int i = 0; i < inPacket.data.length() / 2; i++) - { - in[i] = qToLittleEndian(in[i]); - } + unsigned char* in = (unsigned char*)inPacket.data.data(); + //for (int i = 0; i < inPacket.data.length() / 2; i++) + //{ + // in[i] = qToLittleEndian(in[i]); + //} /* Encode the frame. */ QByteArray outPacket(chunkSize * setup.radioChan * 2, (char)0xff); // Preset the output buffer size. - unsigned char* out = (unsigned char*)outPacket.data(); + qint16* out = (qint16*)outPacket.data(); - int nbBytes = opus_decode(decoder, out, outPacket.length(), in, inPacket.data.length()/2,0); + int nbBytes = opus_decode(decoder, in, inPacket.data.length(), out, outPacket.length()/2, 0); if (nbBytes < 0) { qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decode failed:" << opus_strerror(nbBytes) << "packet size" << inPacket.data.length(); @@ -502,6 +502,7 @@ void audioHandler::incomingAudio(audioPacket inPacket) } } + //qDebug(logAudio()) << "Got" << radioSampleBits << "bits, length" << inPacket.data.length(); // Incoming data is 8bits? if (setup.bits == 8) @@ -683,8 +684,8 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) qint16* in = (qint16*)packet.data.data(); // Convert from little endian - for (int i = 0; i < packet.data.length()/2; i++) - in[i] = qToBigEndian(in[i]); + //for (int i = 0; i < packet.data.length()/2; i++) + // in[i] = qToBigEndian(in[i]); /* Encode the frame. */ QByteArray outPacket(638*setup.radioChan, (char)0xff); // Preset the output buffer size. From 74382b29eec772626999fb1380deb33d4971bb4a Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Wed, 16 Jun 2021 23:44:59 +0100 Subject: [PATCH 09/77] Enable FEC for Opus codec --- audiohandler.cpp | 19 ++++++++++++++----- udphandler.cpp | 2 +- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index 84e9ad3..f310351 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -2,11 +2,13 @@ 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" #include "ulaw.h" + audioHandler::audioHandler(QObject* parent) { Q_UNUSED(parent) @@ -288,7 +290,10 @@ void audioHandler::start() audioInput->start(this); if (setup.codec == 0x40 || setup.codec == 0x80) { // Opus codec + encoder = opus_encoder_create(setup.samplerate, setup.radioChan, OPUS_APPLICATION_AUDIO, &err); + opus_encoder_ctl(encoder, OPUS_SET_INBAND_FEC(1)); + opus_encoder_ctl(encoder, OPUS_SET_PACKET_LOSS_PERC(5)); } } else { @@ -488,22 +493,26 @@ void audioHandler::incomingAudio(audioPacket inPacket) QByteArray outPacket(chunkSize * setup.radioChan * 2, (char)0xff); // Preset the output buffer size. qint16* out = (qint16*)outPacket.data(); - int nbBytes = opus_decode(decoder, in, inPacket.data.length(), out, outPacket.length()/2, 0); + int nbBytes = opus_decode(decoder, in, inPacket.data.size(), out, outPacket.size()/2, 1); if (nbBytes < 0) { qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decode failed:" << opus_strerror(nbBytes) << "packet size" << inPacket.data.length(); return; } else { - outPacket.resize(nbBytes); - qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoded" << inPacket.data.length() << "bytes, into" << outPacket.length() << "bytes"; + if (nbBytes * 2 != outPacket.size()) + { + qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoder mismatch: nbBytes:" << nbBytes*2 << "outPacket:" << outPacket.size() ; + outPacket.resize(nbBytes * 2); + } + qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoded" << inPacket.data.size() << "bytes, into" << outPacket.length() << "bytes"; inPacket.data.clear(); inPacket.data = outPacket; // Replace incoming data with converted. } } - //qDebug(logAudio()) << "Got" << radioSampleBits << "bits, length" << inPacket.data.length(); + //qDebug(logAudio()) << "Got" << setup.bits << "bits, length" << inPacket.data.length(); // Incoming data is 8bits? if (setup.bits == 8) { @@ -555,7 +564,7 @@ void audioHandler::incomingAudio(audioPacket inPacket) /* 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. */ - //qDebug(logAudio()) << "Now 16 bit stereo, length" << inPacket.data.length(); + qDebug(logAudio()) << "Now 16 bit stereo, length" << inPacket.data.length(); if (ratioDen != 1) { diff --git a/udphandler.cpp b/udphandler.cpp index a2c8e49..66e18c6 100644 --- a/udphandler.cpp +++ b/udphandler.cpp @@ -912,7 +912,7 @@ void udpAudio::dataReceived() control_packet_t in = (control_packet_t)r.constData(); - if (in->type != 0x01 && in->len >= 0xAC) { + if (in->type != 0x01 && in->len >= 0x20) { if (in->seq == 0) { // Seq number has rolled over. From bbf981cc24d4f909e0608491a976521289df3f9f Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Thu, 17 Jun 2021 09:55:09 +0100 Subject: [PATCH 10/77] Trying to fix stereo opus stream --- audiohandler.cpp | 19 +++++++++++-------- audiohandler.h | 3 ++- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index f310351..aac56e6 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -292,8 +292,8 @@ void audioHandler::start() // Opus codec encoder = opus_encoder_create(setup.samplerate, setup.radioChan, OPUS_APPLICATION_AUDIO, &err); - opus_encoder_ctl(encoder, OPUS_SET_INBAND_FEC(1)); - opus_encoder_ctl(encoder, OPUS_SET_PACKET_LOSS_PERC(5)); + //opus_encoder_ctl(encoder, OPUS_SET_INBAND_FEC(1)); + //opus_encoder_ctl(encoder, OPUS_SET_PACKET_LOSS_PERC(5)); } } else { @@ -306,6 +306,8 @@ void audioHandler::start() if (setup.codec == 0x40 || setup.codec == 0x80) { // Opus codec decoder = opus_decoder_create(setup.samplerate, setup.radioChan, &err); + //opus_decoder_ctl(decoder, OPUS_SET_INBAND_FEC(1)); + //opus_decoder_ctl(decoder, OPUS_SET_PACKET_LOSS_PERC(5)); } } if (err < 0) @@ -483,17 +485,17 @@ void audioHandler::incomingAudio(audioPacket inPacket) } if (setup.codec == 0x40 || setup.codec == 0x80) { - unsigned char* in = (unsigned char*)inPacket.data.data(); - //for (int i = 0; i < inPacket.data.length() / 2; i++) - //{ - // in[i] = qToLittleEndian(in[i]); - //} /* Encode the frame. */ QByteArray outPacket(chunkSize * setup.radioChan * 2, (char)0xff); // Preset the output buffer size. qint16* out = (qint16*)outPacket.data(); + int nbBytes = 0; + //while (lastSentSeq>0 && lastSentSeq++ < inPacket.seq) + //{ + // nbBytes = opus_decode(decoder, Q_NULLPTR, inPacket.data.size(), out, outPacket.size(), 1); + //} + nbBytes = opus_decode(decoder, in, inPacket.data.size(), out, outPacket.size()/2, 0); - int nbBytes = opus_decode(decoder, in, inPacket.data.size(), out, outPacket.size()/2, 1); if (nbBytes < 0) { qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decode failed:" << opus_strerror(nbBytes) << "packet size" << inPacket.data.length(); @@ -587,6 +589,7 @@ void audioHandler::incomingAudio(audioPacket inPacket) } //qDebug(logAudio()) << "Adding packet to buffer:" << inPacket.seq << ": " << inPacket.data.length(); + lastSentSeq = inPacket.seq; if (!ringBuf->try_write(inPacket)) { diff --git a/audiohandler.h b/audiohandler.h index 8a22fed..3828763 100644 --- a/audiohandler.h +++ b/audiohandler.h @@ -164,7 +164,8 @@ private: bool chunkAvailable; quint32 lastSeq; - + quint32 lastSentSeq=0; + quint16 radioSampleRate; quint16 nativeSampleRate=0; quint8 radioSampleBits; From 17f186354e4db5b8dd5f193212d23b17c34831c9 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Fri, 18 Jun 2021 23:47:22 +0100 Subject: [PATCH 11/77] Mono opus working ok but stereo still crashing? --- audiohandler.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index aac56e6..62ae7f8 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -487,14 +487,14 @@ void audioHandler::incomingAudio(audioPacket inPacket) if (setup.codec == 0x40 || setup.codec == 0x80) { unsigned char* in = (unsigned char*)inPacket.data.data(); /* Encode the frame. */ - QByteArray outPacket(chunkSize * setup.radioChan * 2, (char)0xff); // Preset the output buffer size. + QByteArray outPacket((chunkSize * setup.radioChan * 2), (char)0xff); // Preset the output buffer size. qint16* out = (qint16*)outPacket.data(); int nbBytes = 0; //while (lastSentSeq>0 && lastSentSeq++ < inPacket.seq) //{ // nbBytes = opus_decode(decoder, Q_NULLPTR, inPacket.data.size(), out, outPacket.size(), 1); //} - nbBytes = opus_decode(decoder, in, inPacket.data.size(), out, outPacket.size()/2, 0); + nbBytes = opus_decode(decoder, in, inPacket.data.size(), out, outPacket.size()/2 , 0); if (nbBytes < 0) { @@ -508,11 +508,11 @@ void audioHandler::incomingAudio(audioPacket inPacket) outPacket.resize(nbBytes * 2); } qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoded" << inPacket.data.size() << "bytes, into" << outPacket.length() << "bytes"; - inPacket.data.clear(); - inPacket.data = outPacket; // Replace incoming data with converted. + //inPacket.data.clear(); + inPacket.data = outPacket.data(); // Replace incoming data with converted. } } - + //return; //qDebug(logAudio()) << "Got" << setup.bits << "bits, length" << inPacket.data.length(); // Incoming data is 8bits? From b9551edf36d825d0c45b33c1d6336df05bbc0a41 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 19 Jun 2021 00:11:25 +0100 Subject: [PATCH 12/77] More opus work --- audiohandler.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index 62ae7f8..ea71629 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -490,11 +490,15 @@ void audioHandler::incomingAudio(audioPacket inPacket) QByteArray outPacket((chunkSize * setup.radioChan * 2), (char)0xff); // Preset the output buffer size. qint16* out = (qint16*)outPacket.data(); int nbBytes = 0; - //while (lastSentSeq>0 && lastSentSeq++ < inPacket.seq) - //{ - // nbBytes = opus_decode(decoder, Q_NULLPTR, inPacket.data.size(), out, outPacket.size(), 1); - //} - nbBytes = opus_decode(decoder, in, inPacket.data.size(), out, outPacket.size()/2 , 0); + /* + if (lastSentSeq > 0) { + while (lastSentSeq > 0 && lastSentSeq++ < inPacket.seq) + { + nbBytes = opus_decode(decoder, 0, 0, out, outPacket.size(), 1); + } + } + */ + nbBytes = opus_decode(decoder, in, inPacket.data.size(), out, outPacket.size()/2, 0); if (nbBytes < 0) { @@ -508,13 +512,12 @@ void audioHandler::incomingAudio(audioPacket inPacket) outPacket.resize(nbBytes * 2); } qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoded" << inPacket.data.size() << "bytes, into" << outPacket.length() << "bytes"; - //inPacket.data.clear(); - inPacket.data = outPacket.data(); // Replace incoming data with converted. + inPacket.data.clear(); + inPacket.data = outPacket; // Replace incoming data with converted. } } - //return; - //qDebug(logAudio()) << "Got" << setup.bits << "bits, length" << inPacket.data.length(); + qDebug(logAudio()) << "Got" << setup.bits << "bits, length" << inPacket.data.length(); // Incoming data is 8bits? if (setup.bits == 8) { From 0329ea65b37462e9d45c085acfb7e7b08b9c8e6f Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 19 Jun 2021 14:09:27 +0100 Subject: [PATCH 13/77] Update audiohandler.cpp --- audiohandler.cpp | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index ea71629..d58b890 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -292,8 +292,13 @@ void audioHandler::start() // Opus codec encoder = opus_encoder_create(setup.samplerate, setup.radioChan, OPUS_APPLICATION_AUDIO, &err); - //opus_encoder_ctl(encoder, OPUS_SET_INBAND_FEC(1)); - //opus_encoder_ctl(encoder, OPUS_SET_PACKET_LOSS_PERC(5)); + opus_encoder_ctl(encoder, OPUS_SET_MAX_BANDWIDTH(setup.samplerate)); + opus_encoder_ctl(encoder, OPUS_SET_BITRATE(OPUS_AUTO)); + opus_encoder_ctl(encoder, OPUS_SET_FORCE_CHANNELS(setup.radioChan)); + opus_encoder_ctl(encoder, OPUS_SET_VBR(1)); + opus_encoder_ctl(encoder, OPUS_SET_INBAND_FEC(1)); + opus_encoder_ctl(encoder, OPUS_SET_DTX(1)); + opus_encoder_ctl(encoder, OPUS_SET_PACKET_LOSS_PERC(5)); } } else { @@ -306,8 +311,6 @@ void audioHandler::start() if (setup.codec == 0x40 || setup.codec == 0x80) { // Opus codec decoder = opus_decoder_create(setup.samplerate, setup.radioChan, &err); - //opus_decoder_ctl(decoder, OPUS_SET_INBAND_FEC(1)); - //opus_decoder_ctl(decoder, OPUS_SET_PACKET_LOSS_PERC(5)); } } if (err < 0) @@ -487,19 +490,17 @@ void audioHandler::incomingAudio(audioPacket inPacket) if (setup.codec == 0x40 || setup.codec == 0x80) { unsigned char* in = (unsigned char*)inPacket.data.data(); /* Encode the frame. */ - QByteArray outPacket((chunkSize * setup.radioChan * 2), (char)0xff); // Preset the output buffer size. + QByteArray outPacket(((setup.samplerate / 50) * setup.radioChan * 2), (char)0xff); // Preset the output buffer size. qint16* out = (qint16*)outPacket.data(); int nbBytes = 0; - /* - if (lastSentSeq > 0) { - while (lastSentSeq > 0 && lastSentSeq++ < inPacket.seq) - { - nbBytes = opus_decode(decoder, 0, 0, out, outPacket.size(), 1); - } + + if (lastSentSeq > 0 && lastSentSeq+1 < inPacket.seq) + { + nbBytes = opus_decode(decoder, NULL, 0, out, outPacket.size()/2, 1); + } + else { + nbBytes = opus_decode(decoder, in, inPacket.data.size(), out, outPacket.size() / 2, 0); } - */ - nbBytes = opus_decode(decoder, in, inPacket.data.size(), out, outPacket.size()/2, 0); - if (nbBytes < 0) { qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decode failed:" << opus_strerror(nbBytes) << "packet size" << inPacket.data.length(); @@ -508,7 +509,7 @@ void audioHandler::incomingAudio(audioPacket inPacket) else { if (nbBytes * 2 != outPacket.size()) { - qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoder mismatch: nbBytes:" << nbBytes*2 << "outPacket:" << outPacket.size() ; + qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoder mismatch: nbBytes:" << nbBytes * 2 << "outPacket:" << outPacket.size(); outPacket.resize(nbBytes * 2); } qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoded" << inPacket.data.size() << "bytes, into" << outPacket.length() << "bytes"; @@ -703,7 +704,7 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) // in[i] = qToBigEndian(in[i]); /* Encode the frame. */ - QByteArray outPacket(638*setup.radioChan, (char)0xff); // Preset the output buffer size. + QByteArray outPacket(1275, (char)0xff); // Preset the output buffer size to MAXIMUM possible Opus frame size unsigned char* out = (unsigned char*)outPacket.data(); int nbBytes = opus_encode(encoder, in, packet.data.length() / 2, out, outPacket.length()); From 0258ae8bf9c4b0585ee68396812a800fd9b8768c Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Wed, 23 Jun 2021 20:25:45 +0100 Subject: [PATCH 14/77] Remove extra debugging for Opus and add warning where opus isn't available --- audiohandler.cpp | 4 ++-- udphandler.cpp | 9 +++++++++ wfview.vcxproj | 13 +++++++------ 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index d58b890..c8e45d4 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -518,7 +518,7 @@ void audioHandler::incomingAudio(audioPacket inPacket) } } - qDebug(logAudio()) << "Got" << setup.bits << "bits, length" << inPacket.data.length(); + //qDebug(logAudio()) << "Got" << setup.bits << "bits, length" << inPacket.data.length(); // Incoming data is 8bits? if (setup.bits == 8) { @@ -570,7 +570,7 @@ void audioHandler::incomingAudio(audioPacket inPacket) /* 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. */ - qDebug(logAudio()) << "Now 16 bit stereo, length" << inPacket.data.length(); + //qDebug(logAudio()) << "Now 16 bit stereo, length" << inPacket.data.length(); if (ratioDen != 1) { diff --git a/udphandler.cpp b/udphandler.cpp index 66e18c6..d211a69 100644 --- a/udphandler.cpp +++ b/udphandler.cpp @@ -299,6 +299,15 @@ void udpHandler::dataReceived() { highBandwidthConnection = true; } + if (!strcmp(in->connection, "WFVIEW")) + { + } + else { + if (rxSetup.codec >= 0x40 || txSetup.codec >= 0x40) + { + emit haveNetworkError(QString("UDP"),QString("Opus codec not supported")); + } + } qInfo(logUdp()) << this->metaObject()->className() << ": Detected connection speed " << in->connection; } diff --git a/wfview.vcxproj b/wfview.vcxproj index dbf5fb4..4a7e73d 100644 --- a/wfview.vcxproj +++ b/wfview.vcxproj @@ -57,7 +57,7 @@ Sync release\ MaxSpeed - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;__WINDOWS_WASAPI__;GITSHORT="8cd64c2";HOST="wfview.org";UNAME="build";QT_NO_DEBUG;NDEBUG;%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;__WINDOWS_WASAPI__;GITSHORT="8917ffa";HOST="wfview.org";UNAME="build";NDEBUG;QT_NO_DEBUG;%(PreprocessorDefinitions) false MultiThreadedDLL @@ -67,12 +67,13 @@ true ..\opus\win32\VS2015\Win32\Release\opus.lib;shell32.lib;%(AdditionalDependencies) - ..\opus\win32\VS2015\Win32\Release;C:\opensslx86\lib;C:\Utils\my_sql\mysql-5.6.11-win32\lib;C:\Utils\postgresqlx86\pgsql\lib;%(AdditionalLibraryDirectories) + ..\opus\win32\VS2015\Win32\Release;C:\opensslx86\lib;C:\Utils\my_sql\mysql-5.7.25-win32\lib;C:\Utils\postgresqlx86\pgsql\lib;%(AdditionalLibraryDirectories) "/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions) true false true false + true $(OutDir)\wfview.exe true Windows @@ -84,7 +85,7 @@ 0 - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;__WINDOWS_WASAPI__;GITSHORT=\"8cd64c2\";HOST=\"wfview.org\";UNAME=\"build\";QT_NO_DEBUG;QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;__WINDOWS_WASAPI__;GITSHORT=\"8917ffa\";HOST=\"wfview.org\";UNAME=\"build\";NDEBUG;QT_NO_DEBUG;QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;%(PreprocessorDefinitions) msvc./$(Configuration)/moc_predefs.hMoc'ing %(Identity)...output$(Configuration)moc_%(Filename).cppdefaultRcc'ing %(Identity)...$(Configuration)qrc_%(Filename).cppUic'ing %(Identity)...$(ProjectDir)ui_%(Filename).h @@ -98,7 +99,7 @@ Sync debug\ Disabled - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;__WINDOWS_WASAPI__;GITSHORT="8cd64c2";HOST="wfview.org";UNAME="build";%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;__WINDOWS_WASAPI__;GITSHORT="8917ffa";HOST="wfview.org";UNAME="build";%(PreprocessorDefinitions) false MultiThreadedDebugDLL true @@ -107,7 +108,7 @@ true ..\opus\win32\VS2015\Win32\Debug\opus.lib;shell32.lib;%(AdditionalDependencies) - ..\opus\win32\VS2015\Win32\Debug;C:\opensslx86\lib;C:\Utils\my_sql\mysql-5.6.11-win32\lib;C:\Utils\postgresqlx86\pgsql\lib;%(AdditionalLibraryDirectories) + ..\opus\win32\VS2015\Win32\Debug;C:\opensslx86\lib;C:\Utils\my_sql\mysql-5.7.25-win32\lib;C:\Utils\postgresqlx86\pgsql\lib;%(AdditionalLibraryDirectories) "/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions) true true @@ -123,7 +124,7 @@ 0 - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;__WINDOWS_WASAPI__;GITSHORT=\"8cd64c2\";HOST=\"wfview.org\";UNAME=\"build\";QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;_DEBUG;%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;__WINDOWS_WASAPI__;GITSHORT=\"8917ffa\";HOST=\"wfview.org\";UNAME=\"build\";QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;_DEBUG;%(PreprocessorDefinitions) msvc./$(Configuration)/moc_predefs.hMoc'ing %(Identity)...output$(Configuration)moc_%(Filename).cppdefaultRcc'ing %(Identity)...$(Configuration)qrc_%(Filename).cppUic'ing %(Identity)...$(ProjectDir)ui_%(Filename).h From fbb4f778c4f414b9247d2a8051afa0c859172fa1 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 26 Jun 2021 10:05:00 +0100 Subject: [PATCH 15/77] Add __PRETTY_FUNCTION__ for compilers that don't have it. --- logcategories.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/logcategories.h b/logcategories.h index a76de51..7e7f461 100644 --- a/logcategories.h +++ b/logcategories.h @@ -12,4 +12,8 @@ Q_DECLARE_LOGGING_CATEGORY(logUdp) Q_DECLARE_LOGGING_CATEGORY(logUdpServer) Q_DECLARE_LOGGING_CATEGORY(logRigCtlD) +#if !defined(__PRETTY_FUNCTION__) +#define __PRETTY_FUNCTION__ __FUNCSIG__ +#endif + #endif // LOGCATEGORIES_H From 1b626b441728889bb08e678472682b48c48f480d Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 26 Jun 2021 10:12:39 +0100 Subject: [PATCH 16/77] Fix for fix of missing __PRETTY_FUNCTION__ --- logcategories.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logcategories.h b/logcategories.h index 7e7f461..172cca1 100644 --- a/logcategories.h +++ b/logcategories.h @@ -12,7 +12,7 @@ Q_DECLARE_LOGGING_CATEGORY(logUdp) Q_DECLARE_LOGGING_CATEGORY(logUdpServer) Q_DECLARE_LOGGING_CATEGORY(logRigCtlD) -#if !defined(__PRETTY_FUNCTION__) +#if defined(Q_OS_WIN) && !defined(__PRETTY_FUNCTION__) #define __PRETTY_FUNCTION__ __FUNCSIG__ #endif From 51a2d1093765667e97dc21360d99549ba538afb5 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 26 Jun 2021 10:13:35 +0100 Subject: [PATCH 17/77] Remove unnecessary escape sequence --- wfmain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wfmain.cpp b/wfmain.cpp index af7d59d..3f7c5cc 100644 --- a/wfmain.cpp +++ b/wfmain.cpp @@ -4236,7 +4236,7 @@ void wfmain::statusFromSliderRaw(QString name, int rawValue) void wfmain::statusFromSliderPercent(QString name, int rawValue) { - showStatusBarText(name + QString(": %1\%").arg((int)(100*rawValue/255.0))); + showStatusBarText(name + QString(": %1%").arg((int)(100*rawValue/255.0))); } void wfmain::receiveTxPower(unsigned char power) From c25040f793c776591c19f22c7331ba289fb9c1ab Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 26 Jun 2021 10:52:38 +0100 Subject: [PATCH 18/77] Check whether data is nullptr in doCmd --- wfmain.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/wfmain.cpp b/wfmain.cpp index 3f7c5cc..021a1f9 100644 --- a/wfmain.cpp +++ b/wfmain.cpp @@ -2231,9 +2231,14 @@ void wfmain::doCmd(commandtype cmddata) { cmds cmd = cmddata.cmd; std::shared_ptr data = cmddata.data; - // This switch is for commands with parameters. // the "default" for non-parameter commands is to call doCmd(cmd). + if (data == nullptr) + { + qInfo(logSystem()) << __PRETTY_FUNCTION__ << "WARNING: data is null"; + return; + } + switch (cmd) { case cmdSetFreq: From 19f33d1ed794c5684cc567596ed1b69deff3f815 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 26 Jun 2021 10:58:54 +0100 Subject: [PATCH 19/77] Move nullptr check to modefilter --- wfmain.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/wfmain.cpp b/wfmain.cpp index 021a1f9..2a51bf8 100644 --- a/wfmain.cpp +++ b/wfmain.cpp @@ -2233,11 +2233,6 @@ void wfmain::doCmd(commandtype cmddata) std::shared_ptr data = cmddata.data; // This switch is for commands with parameters. // the "default" for non-parameter commands is to call doCmd(cmd). - if (data == nullptr) - { - qInfo(logSystem()) << __PRETTY_FUNCTION__ << "WARNING: data is null"; - return; - } switch (cmd) { @@ -2255,8 +2250,14 @@ void wfmain::doCmd(commandtype cmddata) } case cmdSetModeFilter: { - mode_info m = (*std::static_pointer_cast(data)); - emit setMode(m); + if (data == nullptr) + { + qInfo(logSystem()) << __PRETTY_FUNCTION__ << "WARNING: data is null"; + } + else { + mode_info m = (*std::static_pointer_cast(data)); + emit setMode(m); + } break; } case cmdSetTxPower: From 6d58034a41a1caf900d4bcdcb149cd3ff5b67acf Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 26 Jun 2021 19:09:24 +0100 Subject: [PATCH 20/77] Revert "Move nullptr check to modefilter" This reverts commit 19f33d1ed794c5684cc567596ed1b69deff3f815. --- wfmain.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/wfmain.cpp b/wfmain.cpp index 2a51bf8..021a1f9 100644 --- a/wfmain.cpp +++ b/wfmain.cpp @@ -2233,6 +2233,11 @@ void wfmain::doCmd(commandtype cmddata) std::shared_ptr data = cmddata.data; // This switch is for commands with parameters. // the "default" for non-parameter commands is to call doCmd(cmd). + if (data == nullptr) + { + qInfo(logSystem()) << __PRETTY_FUNCTION__ << "WARNING: data is null"; + return; + } switch (cmd) { @@ -2250,14 +2255,8 @@ void wfmain::doCmd(commandtype cmddata) } case cmdSetModeFilter: { - if (data == nullptr) - { - qInfo(logSystem()) << __PRETTY_FUNCTION__ << "WARNING: data is null"; - } - else { - mode_info m = (*std::static_pointer_cast(data)); - emit setMode(m); - } + mode_info m = (*std::static_pointer_cast(data)); + emit setMode(m); break; } case cmdSetTxPower: From b071e8d78828db3d5125f6533f91a8ab1c1afad5 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 26 Jun 2021 19:09:41 +0100 Subject: [PATCH 21/77] Revert "Check whether data is nullptr in doCmd" This reverts commit c25040f793c776591c19f22c7331ba289fb9c1ab. --- wfmain.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/wfmain.cpp b/wfmain.cpp index 021a1f9..3f7c5cc 100644 --- a/wfmain.cpp +++ b/wfmain.cpp @@ -2231,14 +2231,9 @@ void wfmain::doCmd(commandtype cmddata) { cmds cmd = cmddata.cmd; std::shared_ptr data = cmddata.data; + // This switch is for commands with parameters. // the "default" for non-parameter commands is to call doCmd(cmd). - if (data == nullptr) - { - qInfo(logSystem()) << __PRETTY_FUNCTION__ << "WARNING: data is null"; - return; - } - switch (cmd) { case cmdSetFreq: From f4cdcccfec2a3b10fafeaf7c85a11fc58c211c6f Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Tue, 6 Jul 2021 10:04:35 +0100 Subject: [PATCH 22/77] Only start audio when stream is ready --- audiohandler.cpp | 9 +++++++-- audiohandler.h | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index c8e45d4..6c52c4d 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -350,7 +350,9 @@ qint64 audioHandler::readData(char* buffer, qint64 nBytes) #endif // Calculate output length, always full samples int sentlen = 0; - + if (!isReady) { + isReady = true; + } if (ringBuf->size()>0) { // Output buffer is ALWAYS 16 bit. @@ -439,6 +441,9 @@ int audioHandler::writeData(void* outputBuffer, void* inputBuffer, unsigned int qint64 audioHandler::writeData(const char* data, qint64 nBytes) { #endif + if (!isReady) { + isReady = true; + } int sentlen = 0; //qDebug(logAudio()) << "nFrames" << nFrames << "nBytes" << nBytes; int chunkBytes = chunkSize * devChannels * 2; @@ -481,7 +486,7 @@ void audioHandler::incomingAudio(audioPacket inPacket) // Regardless of the radio stream format, the buffered audio will ALWAYS be // 16bit sample interleaved stereo 48K (or whatever the native sample rate is) - if (!isInitialized) + if (!isInitialized && !isReady) { qDebug(logAudio()) << "Packet received when stream was not ready"; return; diff --git a/audiohandler.h b/audiohandler.h index 3828763..6bbfb26 100644 --- a/audiohandler.h +++ b/audiohandler.h @@ -141,6 +141,7 @@ private: void reinit(); bool isInitialized=false; + bool isReady = false; #if defined(RTAUDIO) RtAudio* audio = Q_NULLPTR; From a777864a0bd7ada7c47b373db4082b5e6a522c8b Mon Sep 17 00:00:00 2001 From: Elliott Liggett Date: Mon, 26 Jul 2021 09:03:09 -0700 Subject: [PATCH 23/77] Fixed error in IC-7410 attenuator spec. --- rigcommander.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rigcommander.cpp b/rigcommander.cpp index 61b9c89..4c350a2 100644 --- a/rigcommander.cpp +++ b/rigcommander.cpp @@ -3100,7 +3100,7 @@ void rigCommander::determineRigCaps() rigCaps.hasATU = true; rigCaps.hasCTCSS = true; rigCaps.hasDTCS = true; - rigCaps.attenuators.push_back('\x12'); + rigCaps.attenuators.push_back('\x20'); rigCaps.preamps.push_back('\x01'); rigCaps.preamps.push_back('\x02'); rigCaps.antennas = {0x00, 0x01}; From 2403f5352adce212474a78e245f0b56b78ed0b44 Mon Sep 17 00:00:00 2001 From: Roeland Jansen Date: Mon, 26 Jul 2021 19:50:40 +0200 Subject: [PATCH 24/77] changelog --- CHANGELOG | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 84d29a0..9a9d6af 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,9 @@ # CHANGELOG +- 20210726 + + Fix for blank username/password in server + - 20210724 small changes to INSTAll.md and addition of mint 20.2/openSUSE 15.3 From 7992d6f870b2edc92a20c0c40ac629dd32da96d6 Mon Sep 17 00:00:00 2001 From: Roeland Jansen Date: Thu, 29 Jul 2021 10:53:57 +0200 Subject: [PATCH 25/77] added /usr/local to search path for the stylesheet --- wfmain.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/wfmain.cpp b/wfmain.cpp index a5b9f08..d73de2f 100644 --- a/wfmain.cpp +++ b/wfmain.cpp @@ -2225,11 +2225,11 @@ void wfmain::setAppTheme(bool isCustom) QFile f(":"+prefs.stylesheetPath); // built-in resource #else QFile f("/usr/share/wfview/stylesheets/" + prefs.stylesheetPath); + QFile g("/usr/local/share/wfview/stylesheets/" + prefs.stylesheetPath); #endif if (!f.exists()) { - printf("Unable to set stylesheet, file not found\n"); - printf("Tried to load: [%s]\n", QString( QString("/usr/share/wfview/stylesheets/") + prefs.stylesheetPath).toStdString().c_str() ); + printf("Unable to set stylesheet, file not found or permission issue [%s]\n", QString( QString("/usr/share/wfview/stylesheets/") + prefs.stylesheetPath).toStdString().c_str() ); } else { @@ -2237,6 +2237,18 @@ void wfmain::setAppTheme(bool isCustom) QTextStream ts(&f); qApp->setStyleSheet(ts.readAll()); } + + if (!g.exists()) + { + printf("Unable to set stylesheet, file not found or permisson issue [%s]\n", QString( QString("/usr/local/share/wfview/stylesheets/") + prefs.stylesheetPath).toStdString().c_str() ); + } + else + { + g.open(QFile::ReadOnly | QFile::Text); + QTextStream ts(&g); + qApp->setStyleSheet(ts.readAll()); + } + } else { qApp->setStyleSheet(""); } From 2ac1b8c0acb6a6c6a3f4374f050aa828f07fa7a5 Mon Sep 17 00:00:00 2001 From: Roeland Jansen Date: Thu, 29 Jul 2021 11:28:45 +0200 Subject: [PATCH 26/77] fix: set the style once --- wfmain.cpp | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/wfmain.cpp b/wfmain.cpp index d73de2f..cb69885 100644 --- a/wfmain.cpp +++ b/wfmain.cpp @@ -2224,32 +2224,38 @@ void wfmain::setAppTheme(bool isCustom) #ifndef Q_OS_LINUX QFile f(":"+prefs.stylesheetPath); // built-in resource #else - QFile f("/usr/share/wfview/stylesheets/" + prefs.stylesheetPath); - QFile g("/usr/local/share/wfview/stylesheets/" + prefs.stylesheetPath); +// two paths are possible - fu = /usr; fl = /usr/local + QFile fu("/usr/share/wfview/stylesheets/" + prefs.stylesheetPath); + QFile fl("/usr/local/share/wfview/stylesheets/" + prefs.stylesheetPath); #endif - if (!f.exists()) + +// check if the filepath is in /usr and if so -- set the style and return + if (!fu.exists()) { printf("Unable to set stylesheet, file not found or permission issue [%s]\n", QString( QString("/usr/share/wfview/stylesheets/") + prefs.stylesheetPath).toStdString().c_str() ); } else { - f.open(QFile::ReadOnly | QFile::Text); - QTextStream ts(&f); + fu.open(QFile::ReadOnly | QFile::Text); + QTextStream ts(&fu); qApp->setStyleSheet(ts.readAll()); + return; } - if (!g.exists()) +// if above fails, check if filepath is in /usr/local and if so -- set the style from there and return + if (!fl.exists()) { printf("Unable to set stylesheet, file not found or permisson issue [%s]\n", QString( QString("/usr/local/share/wfview/stylesheets/") + prefs.stylesheetPath).toStdString().c_str() ); } else { - g.open(QFile::ReadOnly | QFile::Text); - QTextStream ts(&g); + fl.open(QFile::ReadOnly | QFile::Text); + QTextStream ts(&fl); qApp->setStyleSheet(ts.readAll()); + return; } - } else { +// if both fail, we revert to no style sheet set qApp->setStyleSheet(""); } } From 4e63a72106d6da3eb87e28f263415d54fc722947 Mon Sep 17 00:00:00 2001 From: Elliott Liggett Date: Fri, 30 Jul 2021 17:30:34 -0700 Subject: [PATCH 27/77] Added a little extra logic, also some cross-platform help, to the custom stylesheet loader. --- wfmain.cpp | 54 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/wfmain.cpp b/wfmain.cpp index cb69885..4d0c196 100644 --- a/wfmain.cpp +++ b/wfmain.cpp @@ -2222,40 +2222,52 @@ void wfmain::setAppTheme(bool isCustom) if(isCustom) { #ifndef Q_OS_LINUX - QFile f(":"+prefs.stylesheetPath); // built-in resource -#else -// two paths are possible - fu = /usr; fl = /usr/local - QFile fu("/usr/share/wfview/stylesheets/" + prefs.stylesheetPath); - QFile fl("/usr/local/share/wfview/stylesheets/" + prefs.stylesheetPath); -#endif - -// check if the filepath is in /usr and if so -- set the style and return - if (!fu.exists()) + QFile fresource(":"+prefs.stylesheetPath); // built-in resource + if (!fresource.exists()) { - printf("Unable to set stylesheet, file not found or permission issue [%s]\n", QString( QString("/usr/share/wfview/stylesheets/") + prefs.stylesheetPath).toStdString().c_str() ); + // This would be quite unusual... + qApp->setStyleSheet(""); + return; } else { - fu.open(QFile::ReadOnly | QFile::Text); - QTextStream ts(&fu); + fresource.open(QFile::ReadOnly | QFile::Text); + QTextStream ts(&fresource); qApp->setStyleSheet(ts.readAll()); return; } +#else +// two paths are possible - fusr = /usr; flocal = /usr/local + QFile fusr("/usr/share/wfview/stylesheets/" + prefs.stylesheetPath); + QFile flocal("/usr/local/share/wfview/stylesheets/" + prefs.stylesheetPath); + +// check if the filepath is in /usr and if so -- set the style and return + if (fusr.exists()) + { + fusr.open(QFile::ReadOnly | QFile::Text); + QTextStream ts(&fusr); + qApp->setStyleSheet(ts.readAll()); + return; + } + // if above fails, check if filepath is in /usr/local and if so -- set the style from there and return - if (!fl.exists()) + if (flocal.exists()) { - printf("Unable to set stylesheet, file not found or permisson issue [%s]\n", QString( QString("/usr/local/share/wfview/stylesheets/") + prefs.stylesheetPath).toStdString().c_str() ); - } - else - { - fl.open(QFile::ReadOnly | QFile::Text); - QTextStream ts(&fl); + flocal.open(QFile::ReadOnly | QFile::Text); + QTextStream ts(&flocal); qApp->setStyleSheet(ts.readAll()); - return; + return; } + + // Still here? Then we could not find a file: + printf("Unable to set stylesheet, file not found or permisson issue. Tried loading [%s] and ", QString( QString("/usr/local/share/wfview/stylesheets/") + prefs.stylesheetPath).toStdString().c_str() ); + printf(" [%s]\n", QString( QString("/usr/share/wfview/stylesheets/") + prefs.stylesheetPath).toStdString().c_str() ); + printf("Unsetting stylesheet."); + qApp->setStyleSheet(""); +#endif } else { -// if both fail, we revert to no style sheet set + // Not custom, proceed without: qApp->setStyleSheet(""); } } From 472709357805cdfdf6de24888397e0d768c25cce Mon Sep 17 00:00:00 2001 From: Roeland Jansen Date: Sun, 1 Aug 2021 13:55:44 +0200 Subject: [PATCH 28/77] added derSuessmann additions to have a linux install prefix --- INSTALL.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 6df4ada..11df8c7 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -40,15 +40,16 @@ git clone https://gitlab.com/eliggett/wfview.git ~~~ ### 3. Create a build directory, compile, and install: +If you want to change the default install path from `/usr/local` to a different prefix (e.g. `/opt`), you must call `qmake ../wfview/wfview.pro PREFIX=/opt` + ~~~ mkdir build cd build qmake ../wfview/wfview.pro make -j -sudo ./install.sh +sudo make install ~~~ - ### 4. You can now launch wfview, either from the terminal or from your desktop environment. If you encounter issues using the serial port, run the following command: ~~~ @@ -65,7 +66,7 @@ sudo usermod -aG dialout $USER ~~~ -### opensuse/sles/tumbleweed install ### +### opensuse/sles/tumbleweed install --- install wfview on suse 15.x sles 15.x or tumbleweed; this was done on a clean install/updated OS. From 680262b4d2ef00b49fa3e98e0f41c0ab4d6a816f Mon Sep 17 00:00:00 2001 From: Roeland Jansen Date: Sun, 1 Aug 2021 13:58:47 +0200 Subject: [PATCH 29/77] added derSuessmann additions to have a linux install prefix --- wfview.pro | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/wfview.pro b/wfview.pro index 86d16a4..9c56e55 100644 --- a/wfview.pro +++ b/wfview.pro @@ -38,6 +38,12 @@ equals(QT_ARCH, arm): DEFINES += USE_NEON DEFINES += OUTSIDE_SPEEX DEFINES += RANDOM_PREFIX=wf +isEmpty(PREFIX) { + PREFIX = /usr/local +} + +DEFINES += PREFIX=\\\"$$PREFIX\\\" + # Choose audio system, uses QTMultimedia if both are commented out. # DEFINES += RTAUDIO # DEFINES += PORTAUDIO @@ -74,18 +80,25 @@ win32:DEFINES += UNAME=\\\"build\\\" RESOURCES += qdarkstyle/style.qrc \ resources/resources.qrc +unix:target.path = $$PREFIX/bin +INSTALLS += target + # Why doesn't this seem to do anything? DISTFILES += resources/wfview.png \ resources/install.sh DISTFILES += resources/wfview.desktop -linux:QMAKE_POST_LINK += cp ../wfview/resources/wfview.png .; -linux:QMAKE_POST_LINK += cp ../wfview/resources/wfview.desktop .; -linux:QMAKE_POST_LINK += cp ../wfview/resources/install.sh .; -linux:QMAKE_POST_LINK += cp -r ../wfview/qdarkstyle .; -linux:QMAKE_POST_LINK += chmod 755 install.sh; -linux:QMAKE_POST_LINK += echo; echo; echo "Run install.sh as root from the build directory to install."; echo; echo; +unix:applications.files = resources/wfview.desktop +unix:applications.path = $$PREFIX/share/applications +INSTALLS += applications +unix:pixmaps.files = resources/wfview.png +unix:pixmaps.path = $$PREFIX/share/pixmaps +INSTALLS += pixmaps + +unix:stylesheets.files = qdarkstyle +unix:stylesheets.path = $$PREFIX/share/wfview +INSTALLS += stylesheets # Do not do this, it will hang on start: # CONFIG(release, debug|release):DEFINES += QT_NO_DEBUG_OUTPUT From bee4f03edb6edf534c2cfe71c5219a5b2a7cb382 Mon Sep 17 00:00:00 2001 From: Roeland Jansen Date: Mon, 2 Aug 2021 08:06:19 +0200 Subject: [PATCH 30/77] added derSuessman prefix code --- wfmain.cpp | 51 +++++++++------------------------------------------ 1 file changed, 9 insertions(+), 42 deletions(-) diff --git a/wfmain.cpp b/wfmain.cpp index 4d0c196..b5d1497 100644 --- a/wfmain.cpp +++ b/wfmain.cpp @@ -2222,52 +2222,22 @@ void wfmain::setAppTheme(bool isCustom) if(isCustom) { #ifndef Q_OS_LINUX - QFile fresource(":"+prefs.stylesheetPath); // built-in resource - if (!fresource.exists()) + QFile f(":"+prefs.stylesheetPath); // built-in resource +#else + QFile f(PREFIX "/share/wfview/" + prefs.stylesheetPath); +#endif + if (!f.exists()) { - // This would be quite unusual... - qApp->setStyleSheet(""); - return; + printf("Unable to set stylesheet, file not found\n"); + printf("Tried to load: [%s]\n", f.fileName().toStdString().c_str() ); } else { - fresource.open(QFile::ReadOnly | QFile::Text); - QTextStream ts(&fresource); + f.open(QFile::ReadOnly | QFile::Text); + QTextStream ts(&f); qApp->setStyleSheet(ts.readAll()); - return; } - -#else -// two paths are possible - fusr = /usr; flocal = /usr/local - QFile fusr("/usr/share/wfview/stylesheets/" + prefs.stylesheetPath); - QFile flocal("/usr/local/share/wfview/stylesheets/" + prefs.stylesheetPath); - -// check if the filepath is in /usr and if so -- set the style and return - if (fusr.exists()) - { - fusr.open(QFile::ReadOnly | QFile::Text); - QTextStream ts(&fusr); - qApp->setStyleSheet(ts.readAll()); - return; - } - -// if above fails, check if filepath is in /usr/local and if so -- set the style from there and return - if (flocal.exists()) - { - flocal.open(QFile::ReadOnly | QFile::Text); - QTextStream ts(&flocal); - qApp->setStyleSheet(ts.readAll()); - return; - } - - // Still here? Then we could not find a file: - printf("Unable to set stylesheet, file not found or permisson issue. Tried loading [%s] and ", QString( QString("/usr/local/share/wfview/stylesheets/") + prefs.stylesheetPath).toStdString().c_str() ); - printf(" [%s]\n", QString( QString("/usr/share/wfview/stylesheets/") + prefs.stylesheetPath).toStdString().c_str() ); - printf("Unsetting stylesheet."); - qApp->setStyleSheet(""); -#endif } else { - // Not custom, proceed without: qApp->setStyleSheet(""); } } @@ -3955,9 +3925,6 @@ void wfmain::on_bandGenbtn_clicked() void wfmain::on_aboutBtn_clicked() { abtBox->show(); - - - } void wfmain::on_fStoBtn_clicked() From 4a7dc5d99e77291810f4f504c74bfda3a9a64019 Mon Sep 17 00:00:00 2001 From: Roeland Jansen Date: Wed, 11 Aug 2021 08:41:45 +0200 Subject: [PATCH 31/77] changelog --- CHANGELOG | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 9a9d6af..0e30950 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,95 @@ # CHANGELOG +- 20210809 + + Add constants to make parsing (hopefully) easier + +- 20210808 + + Fake known functions + + Fix float warning + + Remove calibration debugging + + Add proper s-meter calibration + +- 20210807 + + Add ritctl model to rigCaps + + Fix to make wsjt-x work again! + + Add split/duplex support + + Update rigctld.cpp + + Correct lack of parentheses in conditionals + + Fix typo + + Remove some debug logging + + More rigctl features/fixes + +- 20210806 + + Fix for get_powerstat + + Update rigctld.cpp + + Add some levels and other functions + + Fix compile warnings + + Add frequency ranges from rigcaps + +- 20210806 + + Move rigctld settings in Ui + + Fixes for setting freq/mode + + Support for more rigctld commands + + More fixes to rigctld + + Change the way rigctl response is built + + More rigctld fixes + +- 20210804 + + Add rigctld config to ui and fix some bugs + +- 20210802 + + added derSuessman prefix code + +- 20210801 + + Fix broken 8bit audio + + added derSuessmann additions to have a linux install prefix + + Fedora build/install notes, see merge request eliggett/wfview!4 + +- 20210730 + + Added a little extra logic, also some cross-platform help, to the custom + stylesheet loader. + +- 20210729 + + fix: set the style once + + + added /usr/local to search path for the stylesheet + +- 20210726 + + Fixed error in IC-7410 attenuator spec. + - 20210726 Fix for blank username/password in server From eb637d2029a9a3b3d940e97dec170bdeb5e96d7a Mon Sep 17 00:00:00 2001 From: Roeland Jansen Date: Wed, 11 Aug 2021 08:47:51 +0200 Subject: [PATCH 32/77] WHATSNEW? --- WHATSNEW | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/WHATSNEW b/WHATSNEW index 86c24b5..15bbcbd 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -1,16 +1,9 @@ -The following highlights are in this dot-release: +The following highlights are in this 1.x-release: + + many changes/mods/updates/enhancements to rigctld + rigctld box added in the UI + build process changed: you can add the install prefix (derSuessmann) + added "do not ask again" for switching off rig and exiting wfview - added IC7700, 718, 7100. (more testing needed) - fixes and improvements to audio - ability to choose between rtaudio and qtmultimedia (default) as compile time option - fixes and lots of improvements at the usb-server end - waterfall length can be adjusted now - no need to restart to change CIV address - seamless changing rigs without restart - started support for older rigs like the 718 - wf display disappears when there is no wf capable rig - IC R8600 support improved - for older rigs added a polling timing box to keep stuff keeping smooth - Local af gain now has anti-log audio pot taper. From b336d1836e621ec511f4943605379c99fbf1d8ba Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Fri, 13 Aug 2021 20:30:53 +0100 Subject: [PATCH 33/77] Try to fix Opus 2-channel --- audiohandler.cpp | 8 +++---- wfview.vcxproj | 59 ++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 59 insertions(+), 8 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index a1c63f9..3b99157 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -500,16 +500,16 @@ void audioHandler::incomingAudio(audioPacket inPacket) if (setup.codec == 0x40 || setup.codec == 0x80) { unsigned char* in = (unsigned char*)inPacket.data.data(); /* Encode the frame. */ - QByteArray outPacket(((setup.samplerate / 50) * setup.radioChan * 2), (char)0xff); // Preset the output buffer size. + QByteArray outPacket(((setup.samplerate / 50) * setup.radioChan * sizeof(qint16)), (char)0xff); // Preset the output buffer size. qint16* out = (qint16*)outPacket.data(); int nbBytes = 0; if (lastSentSeq > 0 && lastSentSeq+1 < inPacket.seq) { - nbBytes = opus_decode(decoder, NULL, 0, out, outPacket.size()/2, 1); + nbBytes = opus_decode(decoder, NULL, 0, out, outPacket.size()/sizeof(qint16)/setup.radioChan, 1); } else { - nbBytes = opus_decode(decoder, in, inPacket.data.size(), out, outPacket.size() / 2, 0); + nbBytes = opus_decode(decoder, in, inPacket.data.size()/sizeof(qint16)/setup.radioChan, out, outPacket.size() / 2, 0); } if (nbBytes < 0) { @@ -717,7 +717,7 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) QByteArray outPacket(1275, (char)0xff); // Preset the output buffer size to MAXIMUM possible Opus frame size unsigned char* out = (unsigned char*)outPacket.data(); - int nbBytes = opus_encode(encoder, in, packet.data.length() / 2, out, outPacket.length()); + int nbBytes = opus_encode(encoder, in, packet.data.length() / sizeof(qint16) / setup.radioChan, out, outPacket.length()); if (nbBytes < 0) { qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus encode failed:" << opus_strerror(nbBytes); diff --git a/wfview.vcxproj b/wfview.vcxproj index 4a7e73d..847643e 100644 --- a/wfview.vcxproj +++ b/wfview.vcxproj @@ -57,7 +57,7 @@ Sync release\ MaxSpeed - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;__WINDOWS_WASAPI__;GITSHORT="8917ffa";HOST="wfview.org";UNAME="build";NDEBUG;QT_NO_DEBUG;%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX="/usr/local";__WINDOWS_WASAPI__;GITSHORT="eb2f897";HOST="wfview.org";UNAME="build";NDEBUG;QT_NO_DEBUG;%(PreprocessorDefinitions) false MultiThreadedDLL @@ -85,7 +85,7 @@ 0 - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;__WINDOWS_WASAPI__;GITSHORT=\"8917ffa\";HOST=\"wfview.org\";UNAME=\"build\";NDEBUG;QT_NO_DEBUG;QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX=\"/usr/local\";__WINDOWS_WASAPI__;GITSHORT=\"eb2f897\";HOST=\"wfview.org\";UNAME=\"build\";NDEBUG;QT_NO_DEBUG;QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;%(PreprocessorDefinitions) msvc./$(Configuration)/moc_predefs.hMoc'ing %(Identity)...output$(Configuration)moc_%(Filename).cppdefaultRcc'ing %(Identity)...$(Configuration)qrc_%(Filename).cppUic'ing %(Identity)...$(ProjectDir)ui_%(Filename).h @@ -99,7 +99,7 @@ Sync debug\ Disabled - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;__WINDOWS_WASAPI__;GITSHORT="8917ffa";HOST="wfview.org";UNAME="build";%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX="/usr/local";__WINDOWS_WASAPI__;GITSHORT="eb2f897";HOST="wfview.org";UNAME="build";%(PreprocessorDefinitions) false MultiThreadedDebugDLL true @@ -124,10 +124,11 @@ 0 - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;__WINDOWS_WASAPI__;GITSHORT=\"8917ffa\";HOST=\"wfview.org\";UNAME=\"build\";QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;_DEBUG;%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX=\"/usr/local\";__WINDOWS_WASAPI__;GITSHORT=\"eb2f897\";HOST=\"wfview.org\";UNAME=\"build\";QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;_DEBUG;%(PreprocessorDefinitions) msvc./$(Configuration)/moc_predefs.hMoc'ing %(Identity)...output$(Configuration)moc_%(Filename).cppdefaultRcc'ing %(Identity)...$(Configuration)qrc_%(Filename).cppUic'ing %(Identity)...$(ProjectDir)ui_%(Filename).h + @@ -145,12 +146,23 @@ + + + + + + + + + + + @@ -162,6 +174,7 @@ + @@ -270,6 +283,16 @@ + + + + + + + + + + @@ -321,6 +344,8 @@ + + Document true @@ -363,6 +388,10 @@ + + + + @@ -370,6 +399,17 @@ + + + + + + + + + + + @@ -402,6 +442,17 @@ + + + + + + + + + + + From 28b2a716d135724ef2ed323ae0fac939d19719e6 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Fri, 13 Aug 2021 20:41:42 +0100 Subject: [PATCH 34/77] Update audiohandler.cpp --- audiohandler.cpp | 63 ++++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index 3b99157..9113bfd 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -500,16 +500,16 @@ void audioHandler::incomingAudio(audioPacket inPacket) if (setup.codec == 0x40 || setup.codec == 0x80) { unsigned char* in = (unsigned char*)inPacket.data.data(); /* Encode the frame. */ - QByteArray outPacket(((setup.samplerate / 50) * setup.radioChan * sizeof(qint16)), (char)0xff); // Preset the output buffer size. + QByteArray outPacket(((setup.samplerate / 50) * 2 * setup.radioChan), (char)0xff); // Preset the output buffer size. qint16* out = (qint16*)outPacket.data(); int nbBytes = 0; if (lastSentSeq > 0 && lastSentSeq+1 < inPacket.seq) { - nbBytes = opus_decode(decoder, NULL, 0, out, outPacket.size()/sizeof(qint16)/setup.radioChan, 1); + nbBytes = opus_decode(decoder, NULL, 0, out, outPacket.size()/2/setup.radioChan, 1); } else { - nbBytes = opus_decode(decoder, in, inPacket.data.size()/sizeof(qint16)/setup.radioChan, out, outPacket.size() / 2, 0); + nbBytes = opus_decode(decoder, in, inPacket.data.size()/2/setup.radioChan, out, outPacket.size() / 2, 0); } if (nbBytes < 0) { @@ -683,8 +683,34 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) //qDebug(logAudio()) << "Now mono, length" << packet.data.length(); - // Do we need to convert 16-bit to 8-bit? - if (setup.bits == 8) { + else if (setup.codec == 0x40 || setup.codec == 0x80) + { + //Are we using the opus codec? + qint16* in = (qint16*)packet.data.data(); + // Convert from little endian + //for (int i = 0; i < packet.data.length()/2; i++) + // in[i] = qToBigEndian(in[i]); + + /* Encode the frame. */ + QByteArray outPacket(1275, (char)0xff); // Preset the output buffer size to MAXIMUM possible Opus frame size + unsigned char* out = (unsigned char*)outPacket.data(); + + int nbBytes = opus_encode(encoder, in, packet.data.length() / 2 / setup.radioChan, out, outPacket.length()); + if (nbBytes < 0) + { + qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus encode failed:" << opus_strerror(nbBytes); + return; + } + else { + outPacket.resize(nbBytes); + qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus encoded" << packet.data.length() << "bytes, into" << outPacket.length() << "bytes"; + packet.data.clear(); + packet.data = outPacket; // Replace incoming data with converted. + } + } + else if (setup.bits == 8) + { + // Do we need to convert 16-bit to 8-bit? QByteArray outPacket((int)packet.data.length() / 2, (char)0xff); qint16* in = (qint16*)packet.data.data(); for (int f = 0; f < outPacket.length(); f++) @@ -704,32 +730,7 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) } packet.data.clear(); packet.data = outPacket; // Copy output packet back to input buffer. - } - - if (setup.codec == 0x40 || setup.codec == 0x80) { - - qint16* in = (qint16*)packet.data.data(); - // Convert from little endian - //for (int i = 0; i < packet.data.length()/2; i++) - // in[i] = qToBigEndian(in[i]); - - /* Encode the frame. */ - QByteArray outPacket(1275, (char)0xff); // Preset the output buffer size to MAXIMUM possible Opus frame size - unsigned char* out = (unsigned char*)outPacket.data(); - - int nbBytes = opus_encode(encoder, in, packet.data.length() / sizeof(qint16) / setup.radioChan, out, outPacket.length()); - if (nbBytes < 0) - { - qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus encode failed:" << opus_strerror(nbBytes); - return; - } - else { - outPacket.resize(nbBytes); - qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus encoded" << packet.data.length() << "bytes, into" << outPacket.length() << "bytes"; - packet.data.clear(); - packet.data = outPacket; // Replace incoming data with converted. - } - } + } ret = packet.data; //qDebug(logAudio()) << "Now radio format, length" << packet.data.length(); From aff0e6847c5cb63e31475c3577a616eb9853ec1b Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Fri, 13 Aug 2021 20:52:18 +0100 Subject: [PATCH 35/77] Update audiohandler.cpp --- audiohandler.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index 9113bfd..6678300 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -504,13 +504,13 @@ void audioHandler::incomingAudio(audioPacket inPacket) qint16* out = (qint16*)outPacket.data(); int nbBytes = 0; - if (lastSentSeq > 0 && lastSentSeq+1 < inPacket.seq) - { - nbBytes = opus_decode(decoder, NULL, 0, out, outPacket.size()/2/setup.radioChan, 1); - } - else { - nbBytes = opus_decode(decoder, in, inPacket.data.size()/2/setup.radioChan, out, outPacket.size() / 2, 0); - } + //if (lastSentSeq > 0 && lastSentSeq+1 < inPacket.seq) + //{ + // nbBytes = opus_decode(decoder, NULL, 0, out, outPacket.size()/ 2 /setup.radioChan, 1); + //} + //else { + nbBytes = opus_decode(decoder, in, inPacket.data.size(), out, outPacket.size() / 2 / setup.radioChan, 0); + //} if (nbBytes < 0) { qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decode failed:" << opus_strerror(nbBytes) << "packet size" << inPacket.data.length(); @@ -683,7 +683,7 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) //qDebug(logAudio()) << "Now mono, length" << packet.data.length(); - else if (setup.codec == 0x40 || setup.codec == 0x80) + if (setup.codec == 0x40 || setup.codec == 0x80) { //Are we using the opus codec? qint16* in = (qint16*)packet.data.data(); From 95b10ce4656548ec3a741968ac0013453dea97d5 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Fri, 13 Aug 2021 23:35:42 +0100 Subject: [PATCH 36/77] Update audiohandler.cpp --- audiohandler.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index 6678300..2f0dce9 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -500,7 +500,7 @@ void audioHandler::incomingAudio(audioPacket inPacket) if (setup.codec == 0x40 || setup.codec == 0x80) { unsigned char* in = (unsigned char*)inPacket.data.data(); /* Encode the frame. */ - QByteArray outPacket(((setup.samplerate / 50) * 2 * setup.radioChan), (char)0xff); // Preset the output buffer size. + QByteArray outPacket(this->chunkSize * 2 * setup.radioChan, (char)0xff); // Preset the output buffer size. qint16* out = (qint16*)outPacket.data(); int nbBytes = 0; @@ -509,7 +509,7 @@ void audioHandler::incomingAudio(audioPacket inPacket) // nbBytes = opus_decode(decoder, NULL, 0, out, outPacket.size()/ 2 /setup.radioChan, 1); //} //else { - nbBytes = opus_decode(decoder, in, inPacket.data.size(), out, outPacket.size() / 2 / setup.radioChan, 0); + nbBytes = opus_decode(decoder, in, inPacket.data.size(), out, this->chunkSize, 0); //} if (nbBytes < 0) { @@ -695,7 +695,7 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) QByteArray outPacket(1275, (char)0xff); // Preset the output buffer size to MAXIMUM possible Opus frame size unsigned char* out = (unsigned char*)outPacket.data(); - int nbBytes = opus_encode(encoder, in, packet.data.length() / 2 / setup.radioChan, out, outPacket.length()); + int nbBytes = opus_encode(encoder, in, this->chunkSize, out, outPacket.length()); if (nbBytes < 0) { qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus encode failed:" << opus_strerror(nbBytes); From 88ec30bb490d2ee57e2f7d62a009d400bb41fd08 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 Aug 2021 00:01:45 +0100 Subject: [PATCH 37/77] Update audiohandler.cpp --- audiohandler.cpp | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index 2f0dce9..b5db1e4 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -295,10 +295,7 @@ void audioHandler::start() // Opus codec encoder = opus_encoder_create(setup.samplerate, setup.radioChan, OPUS_APPLICATION_AUDIO, &err); - opus_encoder_ctl(encoder, OPUS_SET_MAX_BANDWIDTH(setup.samplerate)); - opus_encoder_ctl(encoder, OPUS_SET_BITRATE(OPUS_AUTO)); - opus_encoder_ctl(encoder, OPUS_SET_FORCE_CHANNELS(setup.radioChan)); - opus_encoder_ctl(encoder, OPUS_SET_VBR(1)); + opus_encoder_ctl(encoder, OPUS_SET_LSB_DEPTH(16)); opus_encoder_ctl(encoder, OPUS_SET_INBAND_FEC(1)); opus_encoder_ctl(encoder, OPUS_SET_DTX(1)); opus_encoder_ctl(encoder, OPUS_SET_PACKET_LOSS_PERC(5)); @@ -314,6 +311,7 @@ void audioHandler::start() if (setup.codec == 0x40 || setup.codec == 0x80) { // Opus codec decoder = opus_decoder_create(setup.samplerate, setup.radioChan, &err); + opus_decoder_ctl(decoder, OPUS_SET_FORCE_CHANNELS(setup.radioChan)); } } if (err < 0) @@ -500,27 +498,28 @@ void audioHandler::incomingAudio(audioPacket inPacket) if (setup.codec == 0x40 || setup.codec == 0x80) { unsigned char* in = (unsigned char*)inPacket.data.data(); /* Encode the frame. */ - QByteArray outPacket(this->chunkSize * 2 * setup.radioChan, (char)0xff); // Preset the output buffer size. + QByteArray outPacket(this->chunkSize * sizeof(qint16) * setup.radioChan, (char)0xff); // Preset the output buffer size. qint16* out = (qint16*)outPacket.data(); - int nbBytes = 0; + int nSamples = 0; - //if (lastSentSeq > 0 && lastSentSeq+1 < inPacket.seq) - //{ - // nbBytes = opus_decode(decoder, NULL, 0, out, outPacket.size()/ 2 /setup.radioChan, 1); - //} - //else { - nbBytes = opus_decode(decoder, in, inPacket.data.size(), out, this->chunkSize, 0); - //} - if (nbBytes < 0) + if (lastSentSeq > 0 && lastSentSeq+1 < inPacket.seq) { - qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decode failed:" << opus_strerror(nbBytes) << "packet size" << inPacket.data.length(); + nSamples = opus_decode(decoder, NULL, 0, out, this->chunkSize, 1); + } + else { + nSamples = opus_decode(decoder, in, inPacket.data.size(), out, this->chunkSize, 0); + } + + if (nSamples < 0) + { + qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decode failed:" << opus_strerror(nSamples) << "packet size" << inPacket.data.length(); return; } else { - if (nbBytes * 2 != outPacket.size()) + if (nSamples * sizeof(qint16) != outPacket.size()) { - qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoder mismatch: nbBytes:" << nbBytes * 2 << "outPacket:" << outPacket.size(); - outPacket.resize(nbBytes * 2); + qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoder mismatch: nBytes:" << nSamples * sizeof(qint16) << "outPacket:" << outPacket.size(); + outPacket.resize(nSamples * sizeof(qint16)); } qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoded" << inPacket.data.size() << "bytes, into" << outPacket.length() << "bytes"; inPacket.data.clear(); From e80d12e477837644ac7b9a935b794167beaa1e71 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 Aug 2021 00:03:26 +0100 Subject: [PATCH 38/77] Update audiohandler.cpp --- audiohandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index b5db1e4..5a04cc4 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -516,7 +516,7 @@ void audioHandler::incomingAudio(audioPacket inPacket) return; } else { - if (nSamples * sizeof(qint16) != outPacket.size()) + if (int(nSamples * sizeof(qint16)) != outPacket.size()) { qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoder mismatch: nBytes:" << nSamples * sizeof(qint16) << "outPacket:" << outPacket.size(); outPacket.resize(nSamples * sizeof(qint16)); From d4023e8b36bc358762e0a914e0d45dd8f59ab491 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 Aug 2021 00:56:16 +0100 Subject: [PATCH 39/77] More Opus fixes --- audiohandler.cpp | 14 ++++++++++---- audiohandler.h | 1 - 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index 5a04cc4..c1e0d35 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -311,7 +311,6 @@ void audioHandler::start() if (setup.codec == 0x40 || setup.codec == 0x80) { // Opus codec decoder = opus_decoder_create(setup.samplerate, setup.radioChan, &err); - opus_decoder_ctl(decoder, OPUS_SET_FORCE_CHANNELS(setup.radioChan)); } } if (err < 0) @@ -497,7 +496,11 @@ void audioHandler::incomingAudio(audioPacket inPacket) if (setup.codec == 0x40 || setup.codec == 0x80) { unsigned char* in = (unsigned char*)inPacket.data.data(); - /* Encode the frame. */ + + qInfo(logAudio()) << "Opus Packet Received: << " << opus_packet_get_nb_channels(in) << "channels, " << opus_packet_get_nb_samples(in, inPacket.data.size(),setup.samplerate) << "samples"; + + /* Decode the frame. */ + //QByteArray outPacket(this->chunkSize * sizeof(qint16) * setup.radioChan, (char)0xff); // Preset the output buffer size. QByteArray outPacket(this->chunkSize * sizeof(qint16) * setup.radioChan, (char)0xff); // Preset the output buffer size. qint16* out = (qint16*)outPacket.data(); int nSamples = 0; @@ -524,6 +527,9 @@ void audioHandler::incomingAudio(audioPacket inPacket) qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoded" << inPacket.data.size() << "bytes, into" << outPacket.length() << "bytes"; inPacket.data.clear(); inPacket.data = outPacket; // Replace incoming data with converted. + qint16* in16 = (qint16*)inPacket.data.data(); + for (int i = 0; i < inPacket.data.length() / 2; i++) + in16[i] = qToLittleEndian(in16[i]); } } @@ -687,8 +693,8 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) //Are we using the opus codec? qint16* in = (qint16*)packet.data.data(); // Convert from little endian - //for (int i = 0; i < packet.data.length()/2; i++) - // in[i] = qToBigEndian(in[i]); + for (int i = 0; i < packet.data.length() / 2; i++) + in[i] = qToBigEndian(in[i]); /* Encode the frame. */ QByteArray outPacket(1275, (char)0xff); // Preset the output buffer size to MAXIMUM possible Opus frame size diff --git a/audiohandler.h b/audiohandler.h index e6618be..d2902d2 100644 --- a/audiohandler.h +++ b/audiohandler.h @@ -169,7 +169,6 @@ private: quint32 lastSeq; quint32 lastSentSeq=0; - quint16 radioSampleRate; quint16 nativeSampleRate=0; quint8 radioSampleBits; quint8 radioChannels; From f5913dc0991a6a3d98c63b5bf96c64a5e4663781 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 Aug 2021 01:01:50 +0100 Subject: [PATCH 40/77] Remove big/little endian conversion --- audiohandler.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index c1e0d35..411d9be 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -528,8 +528,8 @@ void audioHandler::incomingAudio(audioPacket inPacket) inPacket.data.clear(); inPacket.data = outPacket; // Replace incoming data with converted. qint16* in16 = (qint16*)inPacket.data.data(); - for (int i = 0; i < inPacket.data.length() / 2; i++) - in16[i] = qToLittleEndian(in16[i]); + //for (int i = 0; i < inPacket.data.length() / 2; i++) + // in16[i] = qToLittleEndian(in16[i]); } } @@ -693,8 +693,8 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) //Are we using the opus codec? qint16* in = (qint16*)packet.data.data(); // Convert from little endian - for (int i = 0; i < packet.data.length() / 2; i++) - in[i] = qToBigEndian(in[i]); + //for (int i = 0; i < packet.data.length() / 2; i++) + // in[i] = qToBigEndian(in[i]); /* Encode the frame. */ QByteArray outPacket(1275, (char)0xff); // Preset the output buffer size to MAXIMUM possible Opus frame size From d2098996ac8342696389e780c3cbf3a007dacdb5 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 Aug 2021 10:06:17 +0100 Subject: [PATCH 41/77] Use radio samplerate for opus --- audiohandler.cpp | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index 411d9be..d07c9c5 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -72,20 +72,12 @@ bool audioHandler::init(audioSetup setupIn) if (setup.codec == 0x01 || setup.codec == 0x20) { setup.ulaw = true; } - if (setup.codec == 0x08 || setup.codec == 0x10 || setup.codec == 0x20) { + if (setup.codec == 0x08 || setup.codec == 0x10 || setup.codec == 0x20 || setup.codec == 0x80) { setup.radioChan = 2; } - if (setup.codec == 0x04 || setup.codec == 0x10) { + if (setup.codec == 0x04 || setup.codec == 0x10 || setup.codec == 0x40 || setup.codec == 0x80) { setup.bits = 16; } - if (setup.codec == 0x40 || setup.codec == 0x80) - { - setup.bits = 16; - } - if (setup.codec == 0x80) - { - setup.radioChan = 2; - } ringBuf = new wilt::Ring(100); // Should be customizable. @@ -497,20 +489,22 @@ void audioHandler::incomingAudio(audioPacket inPacket) if (setup.codec == 0x40 || setup.codec == 0x80) { unsigned char* in = (unsigned char*)inPacket.data.data(); - qInfo(logAudio()) << "Opus Packet Received: << " << opus_packet_get_nb_channels(in) << "channels, " << opus_packet_get_nb_samples(in, inPacket.data.size(),setup.samplerate) << "samples"; - + qInfo(logAudio()) << "Opus Packet Received: << " << opus_packet_get_nb_channels(in) + << "channels, " << opus_packet_get_nb_samples(in, inPacket.data.size(),setup.samplerate) + << "samples" << opus_decoder_get_nb_samples(decoder,in,inPacket.data.size()) << "decoded samples"; + qInfo(logAudio()) << "Radio: channels" << setup.radioChan << "samplerate" << setup.samplerate; /* Decode the frame. */ //QByteArray outPacket(this->chunkSize * sizeof(qint16) * setup.radioChan, (char)0xff); // Preset the output buffer size. - QByteArray outPacket(this->chunkSize * sizeof(qint16) * setup.radioChan, (char)0xff); // Preset the output buffer size. + QByteArray outPacket((setup.samplerate / 50) * sizeof(qint16) * setup.radioChan, (char)0xff); // Preset the output buffer size. qint16* out = (qint16*)outPacket.data(); int nSamples = 0; if (lastSentSeq > 0 && lastSentSeq+1 < inPacket.seq) { - nSamples = opus_decode(decoder, NULL, 0, out, this->chunkSize, 1); + nSamples = opus_decode(decoder, NULL, 0, out, (setup.samplerate / 50), 1); } else { - nSamples = opus_decode(decoder, in, inPacket.data.size(), out, this->chunkSize, 0); + nSamples = opus_decode(decoder, in, inPacket.data.size(), out, (setup.samplerate / 50), 0); } if (nSamples < 0) @@ -527,7 +521,7 @@ void audioHandler::incomingAudio(audioPacket inPacket) qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoded" << inPacket.data.size() << "bytes, into" << outPacket.length() << "bytes"; inPacket.data.clear(); inPacket.data = outPacket; // Replace incoming data with converted. - qint16* in16 = (qint16*)inPacket.data.data(); + //qint16* in16 = (qint16*)inPacket.data.data(); //for (int i = 0; i < inPacket.data.length() / 2; i++) // in16[i] = qToLittleEndian(in16[i]); } @@ -700,7 +694,7 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) QByteArray outPacket(1275, (char)0xff); // Preset the output buffer size to MAXIMUM possible Opus frame size unsigned char* out = (unsigned char*)outPacket.data(); - int nbBytes = opus_encode(encoder, in, this->chunkSize, out, outPacket.length()); + int nbBytes = opus_encode(encoder, in, (setup.samplerate / 50), out, outPacket.length()); if (nbBytes < 0) { qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus encode failed:" << opus_strerror(nbBytes); From 9ca727ac65763309cd33981c0bfadf2c6f8b1f5e Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 Aug 2021 10:11:58 +0100 Subject: [PATCH 42/77] Add some debugging for decoder --- audiohandler.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index d07c9c5..851ed7c 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -489,9 +489,9 @@ void audioHandler::incomingAudio(audioPacket inPacket) if (setup.codec == 0x40 || setup.codec == 0x80) { unsigned char* in = (unsigned char*)inPacket.data.data(); - qInfo(logAudio()) << "Opus Packet Received: << " << opus_packet_get_nb_channels(in) - << "channels, " << opus_packet_get_nb_samples(in, inPacket.data.size(),setup.samplerate) - << "samples" << opus_decoder_get_nb_samples(decoder,in,inPacket.data.size()) << "decoded samples"; + qInfo(logAudio()) << "Opus Packet Received: << " << opus_packet_get_nb_channels(in) + << "channels, " << opus_packet_get_nb_samples(in, inPacket.data.size(), setup.samplerate) + << "samples" << opus_decoder_get_nb_samples(decoder, in, inPacket.data.size()) << "decoded samples"; qInfo(logAudio()) << "Radio: channels" << setup.radioChan << "samplerate" << setup.samplerate; /* Decode the frame. */ //QByteArray outPacket(this->chunkSize * sizeof(qint16) * setup.radioChan, (char)0xff); // Preset the output buffer size. @@ -706,6 +706,10 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) packet.data.clear(); packet.data = outPacket; // Replace incoming data with converted. } + qInfo(logAudio()) << "Opus Packet To Send: << " << opus_packet_get_nb_channels(out) + << "channels, " << opus_packet_get_nb_samples(out, outPacket.size(), setup.samplerate); + qInfo(logAudio()) << "Radio: channels" << setup.radioChan << "samplerate" << setup.samplerate; + } else if (setup.bits == 8) { From 2214ec7783dbbacfb89d59e2659abbf9b2753ec5 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 Aug 2021 10:29:22 +0100 Subject: [PATCH 43/77] Move opus init --- audiohandler.cpp | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index 851ed7c..7e073cf 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -242,17 +242,35 @@ bool audioHandler::init(audioSetup setupIn) } #endif - // Setup resampler if it is needed. + // Setup resampler and opus if they are needed. int resample_error = 0; + int opus_err = 0; if (setup.isinput) { resampler = wf_resampler_init(devChannels, nativeSampleRate, setup.samplerate, setup.resampleQuality, &resample_error); + if (setup.codec == 0x40 || setup.codec == 0x80) { + // Opus codec + encoder = opus_encoder_create(setup.samplerate, setup.radioChan, OPUS_APPLICATION_AUDIO, &opus_err); + opus_encoder_ctl(encoder, OPUS_SET_LSB_DEPTH(16)); + opus_encoder_ctl(encoder, OPUS_SET_INBAND_FEC(1)); + opus_encoder_ctl(encoder, OPUS_SET_DTX(1)); + opus_encoder_ctl(encoder, OPUS_SET_PACKET_LOSS_PERC(5)); + } } else { resampler = wf_resampler_init(devChannels, setup.samplerate, this->nativeSampleRate, setup.resampleQuality, &resample_error); + if (setup.codec == 0x40 || setup.codec == 0x80) { + // Opus codec + decoder = opus_decoder_create(setup.samplerate, setup.radioChan, &opus_err); + } } wf_resampler_get_ratio(resampler, &ratioNum, &ratioDen); qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "wf_resampler_init() returned: " << resample_error << " ratioNum" << ratioNum << " ratioDen" << ratioDen; + if (opus_err < 0) + { + qInfo(logAudio()) << "Faile to create opus" << (setup.isinput ? "Encoder" : "Decoder") << opus_strerror(opus_err); + } + qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "thread id" << QThread::currentThreadId(); #if !defined (RTAUDIO) && !defined(PORTAUDIO) @@ -274,8 +292,6 @@ void audioHandler::start() return; } - int err = 0; - if (setup.isinput) { #ifdef Q_OS_MACX this->open(QIODevice::WriteOnly); @@ -283,15 +299,6 @@ void audioHandler::start() this->open(QIODevice::WriteOnly | QIODevice::Unbuffered); #endif audioInput->start(this); - if (setup.codec == 0x40 || setup.codec == 0x80) { - // Opus codec - - encoder = opus_encoder_create(setup.samplerate, setup.radioChan, OPUS_APPLICATION_AUDIO, &err); - opus_encoder_ctl(encoder, OPUS_SET_LSB_DEPTH(16)); - opus_encoder_ctl(encoder, OPUS_SET_INBAND_FEC(1)); - opus_encoder_ctl(encoder, OPUS_SET_DTX(1)); - opus_encoder_ctl(encoder, OPUS_SET_PACKET_LOSS_PERC(5)); - } } else { #ifdef Q_OS_MACX @@ -300,14 +307,6 @@ void audioHandler::start() this->open(QIODevice::ReadOnly | QIODevice::Unbuffered); #endif audioOutput->start(this); - if (setup.codec == 0x40 || setup.codec == 0x80) { - // Opus codec - decoder = opus_decoder_create(setup.samplerate, setup.radioChan, &err); - } - } - if (err < 0) - { - fprintf(stderr, "failed to create opus encoder or decoder: %s\n", opus_strerror(err)); } } #endif From da53f5371bbeb35b10cbb831b83b74e1bdd771f9 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 Aug 2021 12:03:04 +0100 Subject: [PATCH 44/77] Remove extra opus debugging --- audiohandler.cpp | 33 ++++----------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index 7e073cf..b48e755 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -488,23 +488,12 @@ void audioHandler::incomingAudio(audioPacket inPacket) if (setup.codec == 0x40 || setup.codec == 0x80) { unsigned char* in = (unsigned char*)inPacket.data.data(); - qInfo(logAudio()) << "Opus Packet Received: << " << opus_packet_get_nb_channels(in) - << "channels, " << opus_packet_get_nb_samples(in, inPacket.data.size(), setup.samplerate) - << "samples" << opus_decoder_get_nb_samples(decoder, in, inPacket.data.size()) << "decoded samples"; - qInfo(logAudio()) << "Radio: channels" << setup.radioChan << "samplerate" << setup.samplerate; /* Decode the frame. */ - //QByteArray outPacket(this->chunkSize * sizeof(qint16) * setup.radioChan, (char)0xff); // Preset the output buffer size. QByteArray outPacket((setup.samplerate / 50) * sizeof(qint16) * setup.radioChan, (char)0xff); // Preset the output buffer size. qint16* out = (qint16*)outPacket.data(); int nSamples = 0; - if (lastSentSeq > 0 && lastSentSeq+1 < inPacket.seq) - { - nSamples = opus_decode(decoder, NULL, 0, out, (setup.samplerate / 50), 1); - } - else { - nSamples = opus_decode(decoder, in, inPacket.data.size(), out, (setup.samplerate / 50), 0); - } + nSamples = opus_decode(decoder, in, inPacket.data.size(), out, (setup.samplerate / 50), 0); if (nSamples < 0) { @@ -512,17 +501,13 @@ void audioHandler::incomingAudio(audioPacket inPacket) return; } else { - if (int(nSamples * sizeof(qint16)) != outPacket.size()) + if (int(nSamples * sizeof(qint16) * setup.radioChan) != outPacket.size()) { qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoder mismatch: nBytes:" << nSamples * sizeof(qint16) << "outPacket:" << outPacket.size(); - outPacket.resize(nSamples * sizeof(qint16)); + outPacket.resize(nSamples * sizeof(qint16) * setup.radioChan); } - qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoded" << inPacket.data.size() << "bytes, into" << outPacket.length() << "bytes"; inPacket.data.clear(); inPacket.data = outPacket; // Replace incoming data with converted. - //qint16* in16 = (qint16*)inPacket.data.data(); - //for (int i = 0; i < inPacket.data.length() / 2; i++) - // in16[i] = qToLittleEndian(in16[i]); } } @@ -655,8 +640,6 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) if (err) { qInfo(logAudio()) << (setup.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(); packet.data.clear(); packet.data = outPacket; // Copy output packet back to input buffer. } @@ -685,9 +668,6 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) { //Are we using the opus codec? qint16* in = (qint16*)packet.data.data(); - // Convert from little endian - //for (int i = 0; i < packet.data.length() / 2; i++) - // in[i] = qToBigEndian(in[i]); /* Encode the frame. */ QByteArray outPacket(1275, (char)0xff); // Preset the output buffer size to MAXIMUM possible Opus frame size @@ -700,15 +680,10 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) return; } else { - outPacket.resize(nbBytes); - qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus encoded" << packet.data.length() << "bytes, into" << outPacket.length() << "bytes"; + outPacket.resize(setup.radioChan); packet.data.clear(); packet.data = outPacket; // Replace incoming data with converted. } - qInfo(logAudio()) << "Opus Packet To Send: << " << opus_packet_get_nb_channels(out) - << "channels, " << opus_packet_get_nb_samples(out, outPacket.size(), setup.samplerate); - qInfo(logAudio()) << "Radio: channels" << setup.radioChan << "samplerate" << setup.samplerate; - } else if (setup.bits == 8) { From e6750be84ce0ad81011c4b38606391040642de29 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 Aug 2021 12:08:50 +0100 Subject: [PATCH 45/77] Revert "Remove extra opus debugging" This reverts commit da53f5371bbeb35b10cbb831b83b74e1bdd771f9. --- audiohandler.cpp | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index b48e755..7e073cf 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -488,12 +488,23 @@ void audioHandler::incomingAudio(audioPacket inPacket) if (setup.codec == 0x40 || setup.codec == 0x80) { unsigned char* in = (unsigned char*)inPacket.data.data(); + qInfo(logAudio()) << "Opus Packet Received: << " << opus_packet_get_nb_channels(in) + << "channels, " << opus_packet_get_nb_samples(in, inPacket.data.size(), setup.samplerate) + << "samples" << opus_decoder_get_nb_samples(decoder, in, inPacket.data.size()) << "decoded samples"; + qInfo(logAudio()) << "Radio: channels" << setup.radioChan << "samplerate" << setup.samplerate; /* Decode the frame. */ + //QByteArray outPacket(this->chunkSize * sizeof(qint16) * setup.radioChan, (char)0xff); // Preset the output buffer size. QByteArray outPacket((setup.samplerate / 50) * sizeof(qint16) * setup.radioChan, (char)0xff); // Preset the output buffer size. qint16* out = (qint16*)outPacket.data(); int nSamples = 0; - nSamples = opus_decode(decoder, in, inPacket.data.size(), out, (setup.samplerate / 50), 0); + if (lastSentSeq > 0 && lastSentSeq+1 < inPacket.seq) + { + nSamples = opus_decode(decoder, NULL, 0, out, (setup.samplerate / 50), 1); + } + else { + nSamples = opus_decode(decoder, in, inPacket.data.size(), out, (setup.samplerate / 50), 0); + } if (nSamples < 0) { @@ -501,13 +512,17 @@ void audioHandler::incomingAudio(audioPacket inPacket) return; } else { - if (int(nSamples * sizeof(qint16) * setup.radioChan) != outPacket.size()) + if (int(nSamples * sizeof(qint16)) != outPacket.size()) { qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoder mismatch: nBytes:" << nSamples * sizeof(qint16) << "outPacket:" << outPacket.size(); - outPacket.resize(nSamples * sizeof(qint16) * setup.radioChan); + outPacket.resize(nSamples * sizeof(qint16)); } + qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoded" << inPacket.data.size() << "bytes, into" << outPacket.length() << "bytes"; inPacket.data.clear(); inPacket.data = outPacket; // Replace incoming data with converted. + //qint16* in16 = (qint16*)inPacket.data.data(); + //for (int i = 0; i < inPacket.data.length() / 2; i++) + // in16[i] = qToLittleEndian(in16[i]); } } @@ -640,6 +655,8 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) if (err) { qInfo(logAudio()) << (setup.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(); packet.data.clear(); packet.data = outPacket; // Copy output packet back to input buffer. } @@ -668,6 +685,9 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) { //Are we using the opus codec? qint16* in = (qint16*)packet.data.data(); + // Convert from little endian + //for (int i = 0; i < packet.data.length() / 2; i++) + // in[i] = qToBigEndian(in[i]); /* Encode the frame. */ QByteArray outPacket(1275, (char)0xff); // Preset the output buffer size to MAXIMUM possible Opus frame size @@ -680,10 +700,15 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) return; } else { - outPacket.resize(setup.radioChan); + outPacket.resize(nbBytes); + qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus encoded" << packet.data.length() << "bytes, into" << outPacket.length() << "bytes"; packet.data.clear(); packet.data = outPacket; // Replace incoming data with converted. } + qInfo(logAudio()) << "Opus Packet To Send: << " << opus_packet_get_nb_channels(out) + << "channels, " << opus_packet_get_nb_samples(out, outPacket.size(), setup.samplerate); + qInfo(logAudio()) << "Radio: channels" << setup.radioChan << "samplerate" << setup.samplerate; + } else if (setup.bits == 8) { From f84172d5aee10e865dfaa0f95a824bd3b5d2ef60 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 Aug 2021 12:17:43 +0100 Subject: [PATCH 46/77] Try again to remove debugging! --- audiohandler.cpp | 42 ++++++++++-------------------------------- 1 file changed, 10 insertions(+), 32 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index 7e073cf..241f066 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -488,23 +488,11 @@ void audioHandler::incomingAudio(audioPacket inPacket) if (setup.codec == 0x40 || setup.codec == 0x80) { unsigned char* in = (unsigned char*)inPacket.data.data(); - qInfo(logAudio()) << "Opus Packet Received: << " << opus_packet_get_nb_channels(in) - << "channels, " << opus_packet_get_nb_samples(in, inPacket.data.size(), setup.samplerate) - << "samples" << opus_decoder_get_nb_samples(decoder, in, inPacket.data.size()) << "decoded samples"; - qInfo(logAudio()) << "Radio: channels" << setup.radioChan << "samplerate" << setup.samplerate; /* Decode the frame. */ - //QByteArray outPacket(this->chunkSize * sizeof(qint16) * setup.radioChan, (char)0xff); // Preset the output buffer size. QByteArray outPacket((setup.samplerate / 50) * sizeof(qint16) * setup.radioChan, (char)0xff); // Preset the output buffer size. qint16* out = (qint16*)outPacket.data(); - int nSamples = 0; - - if (lastSentSeq > 0 && lastSentSeq+1 < inPacket.seq) - { - nSamples = opus_decode(decoder, NULL, 0, out, (setup.samplerate / 50), 1); - } - else { - nSamples = opus_decode(decoder, in, inPacket.data.size(), out, (setup.samplerate / 50), 0); - } + + int nSamples = opus_decode(decoder, in, inPacket.data.size(), out, (setup.samplerate / 50), 0); if (nSamples < 0) { @@ -512,17 +500,14 @@ void audioHandler::incomingAudio(audioPacket inPacket) return; } else { - if (int(nSamples * sizeof(qint16)) != outPacket.size()) + if (int(nSamples * sizeof(qint16) * setup.radioChan) != outPacket.size()) { - qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoder mismatch: nBytes:" << nSamples * sizeof(qint16) << "outPacket:" << outPacket.size(); - outPacket.resize(nSamples * sizeof(qint16)); + qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoder mismatch: nBytes:" << nSamples * sizeof(qint16) * setup.radioChan << "outPacket:" << outPacket.size(); + outPacket.resize(nSamples * sizeof(qint16) * setup.radioChan); } qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoded" << inPacket.data.size() << "bytes, into" << outPacket.length() << "bytes"; inPacket.data.clear(); inPacket.data = outPacket; // Replace incoming data with converted. - //qint16* in16 = (qint16*)inPacket.data.data(); - //for (int i = 0; i < inPacket.data.length() / 2; i++) - // in16[i] = qToLittleEndian(in16[i]); } } @@ -685,9 +670,6 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) { //Are we using the opus codec? qint16* in = (qint16*)packet.data.data(); - // Convert from little endian - //for (int i = 0; i < packet.data.length() / 2; i++) - // in[i] = qToBigEndian(in[i]); /* Encode the frame. */ QByteArray outPacket(1275, (char)0xff); // Preset the output buffer size to MAXIMUM possible Opus frame size @@ -701,13 +683,9 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) } else { outPacket.resize(nbBytes); - qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus encoded" << packet.data.length() << "bytes, into" << outPacket.length() << "bytes"; packet.data.clear(); packet.data = outPacket; // Replace incoming data with converted. } - qInfo(logAudio()) << "Opus Packet To Send: << " << opus_packet_get_nb_channels(out) - << "channels, " << opus_packet_get_nb_samples(out, outPacket.size(), setup.samplerate); - qInfo(logAudio()) << "Radio: channels" << setup.radioChan << "samplerate" << setup.samplerate; } else if (setup.bits == 8) @@ -719,14 +697,14 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) { quint8 outdata = 0; if (setup.ulaw) { - qint16 enc = qFromLittleEndian(in + f); - if (enc >= 0) - outdata = ulaw_encode[enc]; + //qint16 enc = qFromLittleEndian(in + f); + if (*in+f >= 0) + outdata = ulaw_encode[*in+f]; else - outdata = 0x7f & ulaw_encode[-enc]; + outdata = 0x7f & ulaw_encode[-(*in+f)]; } else { - outdata = (quint8)(((qFromLittleEndian(in + f) >> 8) ^ 0x80) & 0xff); + outdata = (quint8)((((*in + f) >> 8) ^ 0x80) & 0xff); } outPacket[f] = (char)outdata; } From 218dc493e227fba86a545fe1aac51c8c7142d890 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 Aug 2021 12:25:50 +0100 Subject: [PATCH 47/77] Another issue with 8 bit audio --- audiohandler.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index 241f066..78c1e55 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -690,23 +690,22 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) } else if (setup.bits == 8) { + // Do we need to convert 16-bit to 8-bit? QByteArray outPacket((int)packet.data.length() / 2, (char)0xff); qint16* in = (qint16*)packet.data.data(); for (int f = 0; f < outPacket.length(); f++) { - quint8 outdata = 0; if (setup.ulaw) { //qint16 enc = qFromLittleEndian(in + f); - if (*in+f >= 0) - outdata = ulaw_encode[*in+f]; + if ((*in)+f >= 0) + outPacket[f] = (char)ulaw_encode[(*in)+f]; else - outdata = 0x7f & ulaw_encode[-(*in+f)]; + outPacket[f] = (char)0x7f & ulaw_encode[-((*in)+f)]; } else { - outdata = (quint8)((((*in + f) >> 8) ^ 0x80) & 0xff); + outPacket[f] = (char)(((((*in) + f) >> 8) ^ 0x80) & 0xff); } - outPacket[f] = (char)outdata; } packet.data.clear(); packet.data = outPacket; // Copy output packet back to input buffer. From 208ed9596ced107d3ceff43bbee6d80311fd5aaa Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 Aug 2021 13:02:07 +0100 Subject: [PATCH 48/77] 8 bit encoding fix --- audiohandler.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index 78c1e55..8042d0d 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -520,12 +520,13 @@ void audioHandler::incomingAudio(audioPacket inPacket) qint16* out = (qint16*)outPacket.data(); for (int f = 0; f < inPacket.data.length(); f++) { + qint16 samp = (quint8)inPacket.data[f]; for (int g = setup.radioChan; g <= devChannels; g++) { if (setup.ulaw) - *out++ = ulaw_decode[(quint8)inPacket.data[f]] * this->volume; + *out++ = ulaw_decode[samp] * this->volume; else - *out++ = (qint16)(((quint8)inPacket.data[f] << 8) - 32640 * this->volume); + *out++ = ((samp - 128) << 8) * this->volume; } } inPacket.data.clear(); @@ -690,21 +691,20 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) } else if (setup.bits == 8) { - // Do we need to convert 16-bit to 8-bit? QByteArray outPacket((int)packet.data.length() / 2, (char)0xff); qint16* in = (qint16*)packet.data.data(); for (int f = 0; f < outPacket.length(); f++) { + qint16 enc = (*in)+f; if (setup.ulaw) { - //qint16 enc = qFromLittleEndian(in + f); - if ((*in)+f >= 0) - outPacket[f] = (char)ulaw_encode[(*in)+f]; + if (enc >= 0) + outPacket[f] = ulaw_encode[enc]; else - outPacket[f] = (char)0x7f & ulaw_encode[-((*in)+f)]; + outPacket[f] = ulaw_encode[-enc] & 0x7f; } else { - outPacket[f] = (char)(((((*in) + f) >> 8) ^ 0x80) & 0xff); + outPacket[f] = (quint8)((enc >> 8) ^ 0x80) & 0xff; } } packet.data.clear(); From ac74f8ba5c3f41afe71a49ec90775c5647ab6ec3 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 Aug 2021 13:05:18 +0100 Subject: [PATCH 49/77] Update audiohandler.cpp --- audiohandler.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index 8042d0d..c74b7e6 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -696,15 +696,15 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) qint16* in = (qint16*)packet.data.data(); for (int f = 0; f < outPacket.length(); f++) { - qint16 enc = (*in)+f; + qint16 enc = *in++; if (setup.ulaw) { if (enc >= 0) - outPacket[f] = ulaw_encode[enc]; + outPacket[f] = (qint8)ulaw_encode[enc]; else - outPacket[f] = ulaw_encode[-enc] & 0x7f; + outPacket[f] = (qint8)ulaw_encode[-enc] & 0x7f; } else { - outPacket[f] = (quint8)((enc >> 8) ^ 0x80) & 0xff; + outPacket[f] = (qint8)((enc >> 8) ^ 0x80) & 0xff; } } packet.data.clear(); From 02ba27b6b2869bb4878d28e98e2e2b5887ee139f Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 Aug 2021 13:16:39 +0100 Subject: [PATCH 50/77] Update audiohandler.cpp --- audiohandler.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index c74b7e6..9e7f923 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -696,15 +696,15 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) qint16* in = (qint16*)packet.data.data(); for (int f = 0; f < outPacket.length(); f++) { - qint16 enc = *in++; + qint16 enc = qFromLittleEndian(*in++);; if (setup.ulaw) { if (enc >= 0) - outPacket[f] = (qint8)ulaw_encode[enc]; + outPacket[f] = (ulaw_encode[enc]); else - outPacket[f] = (qint8)ulaw_encode[-enc] & 0x7f; + outPacket[f] = (ulaw_encode[-enc] & 0x7f); } else { - outPacket[f] = (qint8)((enc >> 8) ^ 0x80) & 0xff; + outPacket[f] = ((enc >> 8) ^ 0x80) & 0xff; } } packet.data.clear(); From 2b8449d4d313135ffb82a69d719d62b831133346 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 Aug 2021 16:04:50 +0100 Subject: [PATCH 51/77] ulaw encoding test --- audiohandler.cpp | 62 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 6 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index 9e7f923..de7da15 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -607,6 +607,48 @@ int audioHandler::getLatency() return currentLatency; } + +const int cBias = 0x84; + +const int cClip = 32635; + +static char MuLawCompressTable[256] = +{ + + 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3, + + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 + +}; + void audioHandler::getNextAudioChunk(QByteArray& ret) { audioPacket packet; @@ -696,15 +738,23 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) qint16* in = (qint16*)packet.data.data(); for (int f = 0; f < outPacket.length(); f++) { - qint16 enc = qFromLittleEndian(*in++);; + qint16 sample = qFromLittleEndian(*in++);; if (setup.ulaw) { - if (enc >= 0) - outPacket[f] = (ulaw_encode[enc]); - else - outPacket[f] = (ulaw_encode[-enc] & 0x7f); + int sign = (sample >> 8) & 0x80; + if (sign) + sample = (short)-sample; + if (sample > cClip) + sample = cClip; + sample = (short)(sample + cBias); + int exponent = (int)MuLawCompressTable[(sample >> 7) & 0xFF]; + int mantissa = (sample >> (exponent + 3)) & 0x0F; + + int compressedByte = ~(sign | (exponent << 4) | mantissa); + + outPacket[f] = (unsigned char)compressedByte; } else { - outPacket[f] = ((enc >> 8) ^ 0x80) & 0xff; + outPacket[f] = ((sample >> 8) ^ 0x80) & 0xff; } } packet.data.clear(); From 9ae9e563999263182a7d7af39c7dc0037725cd32 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 Aug 2021 16:11:48 +0100 Subject: [PATCH 52/77] more 8bit fixes! --- audiohandler.cpp | 47 +--- ulaw.h | 706 ++--------------------------------------------- 2 files changed, 25 insertions(+), 728 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index de7da15..166bceb 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -608,46 +608,6 @@ int audioHandler::getLatency() } -const int cBias = 0x84; - -const int cClip = 32635; - -static char MuLawCompressTable[256] = -{ - - 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3, - - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 - -}; void audioHandler::getNextAudioChunk(QByteArray& ret) { @@ -738,7 +698,7 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) qint16* in = (qint16*)packet.data.data(); for (int f = 0; f < outPacket.length(); f++) { - qint16 sample = qFromLittleEndian(*in++);; + qint16 sample = *in++; if (setup.ulaw) { int sign = (sample >> 8) & 0x80; if (sign) @@ -748,13 +708,12 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) sample = (short)(sample + cBias); int exponent = (int)MuLawCompressTable[(sample >> 7) & 0xFF]; int mantissa = (sample >> (exponent + 3)) & 0x0F; - int compressedByte = ~(sign | (exponent << 4) | mantissa); - outPacket[f] = (unsigned char)compressedByte; } else { - outPacket[f] = ((sample >> 8) ^ 0x80) & 0xff; + int compressedByte = ((sample >> 8) ^ 0x80) & 0xff; + outPacket[f] = (unsigned char)compressedByte; } } packet.data.clear(); diff --git a/ulaw.h b/ulaw.h index 9d673a5..23eac9d 100644 --- a/ulaw.h +++ b/ulaw.h @@ -1,693 +1,31 @@ #ifndef ULAW_H #define ULAW_H +const int cBias = 0x84; -static unsigned char ulaw_encode[8193] = -{ 0xff, 0xfe, 0xfe, 0xfd, 0xfd, 0xfc, 0xfc, 0xfb, 0xfb, 0xfa, 0xfa, 0xf9, - 0xf9, 0xf8, 0xf8, 0xf7, 0xf7, 0xf6, 0xf6, 0xf5, 0xf5, 0xf4, 0xf4, 0xf3, - 0xf3, 0xf2, 0xf2, 0xf1, 0xf1, 0xf0, 0xf0, 0xef, 0xef, 0xef, 0xef, 0xee, - 0xee, 0xee, 0xee, 0xed, 0xed, 0xed, 0xed, 0xec, 0xec, 0xec, 0xec, 0xeb, - 0xeb, 0xeb, 0xeb, 0xea, 0xea, 0xea, 0xea, 0xe9, 0xe9, 0xe9, 0xe9, 0xe8, - 0xe8, 0xe8, 0xe8, 0xe7, 0xe7, 0xe7, 0xe7, 0xe6, 0xe6, 0xe6, 0xe6, 0xe5, - 0xe5, 0xe5, 0xe5, 0xe4, 0xe4, 0xe4, 0xe4, 0xe3, 0xe3, 0xe3, 0xe3, 0xe2, - 0xe2, 0xe2, 0xe2, 0xe1, 0xe1, 0xe1, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xdf, - 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xde, 0xde, 0xde, 0xde, 0xde, - 0xde, 0xde, 0xde, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdc, - 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, - 0xdb, 0xdb, 0xdb, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xd9, - 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, - 0xd8, 0xd8, 0xd8, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd6, - 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, - 0xd5, 0xd5, 0xd5, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd3, - 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, - 0xd2, 0xd2, 0xd2, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd0, - 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, - 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xce, - 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, - 0xce, 0xce, 0xce, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, - 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcb, - 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, - 0xcb, 0xcb, 0xcb, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, - 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, - 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc8, - 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, - 0xc8, 0xc8, 0xc8, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, - 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc5, - 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, - 0xc5, 0xc5, 0xc5, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, - 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, - 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc2, - 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, - 0xc2, 0xc2, 0xc2, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, - 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, - 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xbf, - 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, - 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, - 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, - 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, - 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, - 0xbe, 0xbe, 0xbe, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, - 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, - 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbc, - 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, - 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, - 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, - 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, - 0xbb, 0xbb, 0xbb, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, - 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, - 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xb9, - 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, - 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, - 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, - 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, - 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, - 0xb8, 0xb8, 0xb8, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, - 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, - 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb6, - 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, - 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, - 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, - 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, - 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, - 0xb5, 0xb5, 0xb5, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, - 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, - 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb3, - 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, - 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, - 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, - 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, - 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, - 0xb2, 0xb2, 0xb2, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, - 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, - 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb0, - 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, - 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, - 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, - 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, - 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, - 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, - 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, - 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xae, - 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, - 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, - 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, - 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, - 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, - 0xae, 0xae, 0xae, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, - 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xac, 0xac, 0xac, 0xac, 0xac, - 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, - 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, - 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, - 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, - 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xab, - 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, - 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, - 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, - 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, - 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, - 0xab, 0xab, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, - 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, - 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, - 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, - 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, - 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa8, - 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, - 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, - 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, - 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, - 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, - 0xa8, 0xa8, 0xa8, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, - 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, - 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, - 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, - 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, - 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, - 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa5, - 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, - 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, - 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, - 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, - 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, - 0xa5, 0xa5, 0xa5, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, - 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, - 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, - 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, - 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, - 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, - 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa2, - 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, - 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, - 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, - 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, - 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, - 0xa2, 0xa2, 0xa2, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, - 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, - 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, - 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, - 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, - 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0x9f, - 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, - 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, - 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, - 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, - 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, - 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, - 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, - 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, - 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, - 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, - 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9e, 0x9e, 0x9e, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9c, - 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, - 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, - 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, - 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, - 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, - 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, - 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, - 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, - 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, - 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, - 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, - 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, - 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, - 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, - 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, - 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, - 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, - 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, - 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, - 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, - 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, - 0x9b, 0x9b, 0x9b, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, - 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, - 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x98, 0x98, 0x98, 0x98, 0x98, - 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, - 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, - 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, - 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, - 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, - 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, - 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, - 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, - 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, - 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, - 0x98, 0x98, 0x98, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, - 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, - 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, - 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, - 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, - 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, - 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, - 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, - 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, - 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, - 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x96, - 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, - 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, - 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, - 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, - 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, - 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, - 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, - 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, - 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, - 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, - 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, - 0x95, 0x95, 0x95, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, - 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x93, - 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, - 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x92, 0x92, 0x92, 0x92, 0x92, - 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, - 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, - 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, - 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, - 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, - 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, - 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, - 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, - 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, - 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, - 0x92, 0x92, 0x92, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, - 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, - 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, - 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, - 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, - 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, - 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, - 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, - 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, - 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, - 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, - 0x8e, 0x8e, 0x8e, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, - 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, - 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, - 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, - 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, - 0x88, 0x88, 0x88, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, - 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, - 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, - 0x85, 0x85, 0x85, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, - 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, - 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, - 0x82, 0x82, 0x82, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, - 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 +const int cClip = 32635; + +static const char MuLawCompressTable[256] = +{ + 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 }; + static const qint16 ulaw_decode[256] = { -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764, From eb5dc0d095858f0a2a137dc2674e660c1af47c3a Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 Aug 2021 16:16:11 +0100 Subject: [PATCH 53/77] Update audiohandler.cpp --- audiohandler.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index 166bceb..3819160 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -712,8 +712,7 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) outPacket[f] = (unsigned char)compressedByte; } else { - int compressedByte = ((sample >> 8) ^ 0x80) & 0xff; - outPacket[f] = (unsigned char)compressedByte; + outPacket[f] = (unsigned char)(((sample + 32768) >> 8) & 0xff); } } packet.data.clear(); From 9d07bbc2813f91a8ad069e35a1ee19c7840cc372 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 Aug 2021 16:27:31 +0100 Subject: [PATCH 54/77] All audio codecs now work in both directions! --- audiohandler.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index 3819160..5838c8b 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -505,7 +505,7 @@ void audioHandler::incomingAudio(audioPacket inPacket) qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoder mismatch: nBytes:" << nSamples * sizeof(qint16) * setup.radioChan << "outPacket:" << outPacket.size(); outPacket.resize(nSamples * sizeof(qint16) * setup.radioChan); } - qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoded" << inPacket.data.size() << "bytes, into" << outPacket.length() << "bytes"; + //qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Opus decoded" << inPacket.data.size() << "bytes, into" << outPacket.length() << "bytes"; inPacket.data.clear(); inPacket.data = outPacket; // Replace incoming data with converted. } @@ -520,13 +520,13 @@ void audioHandler::incomingAudio(audioPacket inPacket) qint16* out = (qint16*)outPacket.data(); for (int f = 0; f < inPacket.data.length(); f++) { - qint16 samp = (quint8)inPacket.data[f]; + int samp = (quint8)inPacket.data[f]; for (int g = setup.radioChan; g <= devChannels; g++) { if (setup.ulaw) *out++ = ulaw_decode[samp] * this->volume; else - *out++ = ((samp - 128) << 8) * this->volume; + *out++ = (qint16)((samp - 128) << 8) * this->volume; } } inPacket.data.clear(); @@ -712,7 +712,8 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) outPacket[f] = (unsigned char)compressedByte; } else { - outPacket[f] = (unsigned char)(((sample + 32768) >> 8) & 0xff); + int compressedByte = (((sample + 32768) >> 8) & 0xff); + outPacket[f] = (unsigned char)compressedByte; } } packet.data.clear(); From f17e69b4be458c12ff7e5ab48c99db1a21fb316e Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 Aug 2021 17:15:44 +0100 Subject: [PATCH 55/77] Comment unused structs from rigctld --- rigctld.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rigctld.h b/rigctld.h index bf8aea5..d5840ae 100644 --- a/rigctld.h +++ b/rigctld.h @@ -202,6 +202,7 @@ static struct { RIG_MODE_NONE, "" }, }; +#if 0 static struct { quint64 func; @@ -311,6 +312,8 @@ static struct { RIG_LEVEL_NONE, "" }, }; +#endif + struct cal_table { int size; /*!< number of plots in the table */ struct { From dc299fc4f7649b45a7ee1e4bdc0a563d434cca83 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 Aug 2021 17:15:59 +0100 Subject: [PATCH 56/77] Is this going to fix 8 bit audio? --- audiohandler.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index 5838c8b..e05b226 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -709,11 +709,11 @@ void audioHandler::getNextAudioChunk(QByteArray& ret) int exponent = (int)MuLawCompressTable[(sample >> 7) & 0xFF]; int mantissa = (sample >> (exponent + 3)) & 0x0F; int compressedByte = ~(sign | (exponent << 4) | mantissa); - outPacket[f] = (unsigned char)compressedByte; + outPacket[f] = (quint8)compressedByte; } else { int compressedByte = (((sample + 32768) >> 8) & 0xff); - outPacket[f] = (unsigned char)compressedByte; + outPacket[f] = (quint8)compressedByte; } } packet.data.clear(); From c7a2561a3f24331fb6761821b4f792db99ec8269 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 Aug 2021 17:18:35 +0100 Subject: [PATCH 57/77] More commenting in rigctld.h --- rigctld.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rigctld.h b/rigctld.h index d5840ae..3cbf773 100644 --- a/rigctld.h +++ b/rigctld.h @@ -159,6 +159,8 @@ #define RIG_FUNC_SPECTRUM CONSTANT_64BIT_FLAG (43) /*!< \c SPECTRUM -- Spectrum scope data output ON/OFF */ #define RIG_FUNC_SPECTRUM_HOLD CONSTANT_64BIT_FLAG (44) /*!< \c SPECTRUM_HOLD -- Pause spectrum scope updates ON/OFF */ +#if 0 + static struct { quint64 mode; @@ -202,7 +204,6 @@ static struct { RIG_MODE_NONE, "" }, }; -#if 0 static struct { quint64 func; From 484da6e55d0911c14353c54f129b1e8c8e6c0ccb Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 Aug 2021 17:20:40 +0100 Subject: [PATCH 58/77] More warning removal! --- rigctld.cpp | 43 +++++++++++++++++++++++++++++++++++++++++++ rigctld.h | 43 ------------------------------------------- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/rigctld.cpp b/rigctld.cpp index ae4a6c3..3abe681 100644 --- a/rigctld.cpp +++ b/rigctld.cpp @@ -2,6 +2,49 @@ #include "logcategories.h" +static struct +{ + quint64 mode; + const char* str; +} mode_str[] = +{ + { RIG_MODE_AM, "AM" }, + { RIG_MODE_CW, "CW" }, + { RIG_MODE_USB, "USB" }, + { RIG_MODE_LSB, "LSB" }, + { RIG_MODE_RTTY, "RTTY" }, + { RIG_MODE_FM, "FM" }, + { RIG_MODE_WFM, "WFM" }, + { RIG_MODE_CWR, "CWR" }, + { RIG_MODE_RTTYR, "RTTYR" }, + { RIG_MODE_AMS, "AMS" }, + { RIG_MODE_PKTLSB, "PKTLSB" }, + { RIG_MODE_PKTUSB, "PKTUSB" }, + { RIG_MODE_PKTFM, "PKTFM" }, + { RIG_MODE_PKTFMN, "PKTFMN" }, + { RIG_MODE_ECSSUSB, "ECSSUSB" }, + { RIG_MODE_ECSSLSB, "ECSSLSB" }, + { RIG_MODE_FAX, "FAX" }, + { RIG_MODE_SAM, "SAM" }, + { RIG_MODE_SAL, "SAL" }, + { RIG_MODE_SAH, "SAH" }, + { RIG_MODE_DSB, "DSB"}, + { RIG_MODE_FMN, "FMN" }, + { RIG_MODE_PKTAM, "PKTAM"}, + { RIG_MODE_P25, "P25"}, + { RIG_MODE_DSTAR, "D-STAR"}, + { RIG_MODE_DPMR, "DPMR"}, + { RIG_MODE_NXDNVN, "NXDN-VN"}, + { RIG_MODE_NXDN_N, "NXDN-N"}, + { RIG_MODE_DCR, "DCR"}, + { RIG_MODE_AMN, "AMN"}, + { RIG_MODE_PSK, "PSK"}, + { RIG_MODE_PSKR, "PSKR"}, + { RIG_MODE_C4FM, "C4FM"}, + { RIG_MODE_SPEC, "SPEC"}, + { RIG_MODE_NONE, "" }, +}; + rigCtlD::rigCtlD(QObject* parent) : QTcpServer(parent) { diff --git a/rigctld.h b/rigctld.h index 3cbf773..51f3698 100644 --- a/rigctld.h +++ b/rigctld.h @@ -161,49 +161,6 @@ #if 0 -static struct -{ - quint64 mode; - const char* str; -} mode_str[] = -{ - { RIG_MODE_AM, "AM" }, - { RIG_MODE_CW, "CW" }, - { RIG_MODE_USB, "USB" }, - { RIG_MODE_LSB, "LSB" }, - { RIG_MODE_RTTY, "RTTY" }, - { RIG_MODE_FM, "FM" }, - { RIG_MODE_WFM, "WFM" }, - { RIG_MODE_CWR, "CWR" }, - { RIG_MODE_RTTYR, "RTTYR" }, - { RIG_MODE_AMS, "AMS" }, - { RIG_MODE_PKTLSB, "PKTLSB" }, - { RIG_MODE_PKTUSB, "PKTUSB" }, - { RIG_MODE_PKTFM, "PKTFM" }, - { RIG_MODE_PKTFMN, "PKTFMN" }, - { RIG_MODE_ECSSUSB, "ECSSUSB" }, - { RIG_MODE_ECSSLSB, "ECSSLSB" }, - { RIG_MODE_FAX, "FAX" }, - { RIG_MODE_SAM, "SAM" }, - { RIG_MODE_SAL, "SAL" }, - { RIG_MODE_SAH, "SAH" }, - { RIG_MODE_DSB, "DSB"}, - { RIG_MODE_FMN, "FMN" }, - { RIG_MODE_PKTAM, "PKTAM"}, - { RIG_MODE_P25, "P25"}, - { RIG_MODE_DSTAR, "D-STAR"}, - { RIG_MODE_DPMR, "DPMR"}, - { RIG_MODE_NXDNVN, "NXDN-VN"}, - { RIG_MODE_NXDN_N, "NXDN-N"}, - { RIG_MODE_DCR, "DCR"}, - { RIG_MODE_AMN, "AMN"}, - { RIG_MODE_PSK, "PSK"}, - { RIG_MODE_PSKR, "PSKR"}, - { RIG_MODE_C4FM, "C4FM"}, - { RIG_MODE_SPEC, "SPEC"}, - { RIG_MODE_NONE, "" }, -}; - static struct { quint64 func; From e5effe657192dafcc487ea66148196c774f07b34 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 Aug 2021 17:22:20 +0100 Subject: [PATCH 59/77] And another one --- rigctld.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rigctld.cpp b/rigctld.cpp index 3abe681..4879728 100644 --- a/rigctld.cpp +++ b/rigctld.cpp @@ -633,7 +633,7 @@ void rigCtlClient::socketReadyRead() } else if (command.length() > 2 && (command[0] == "L" || command[0] == "set_level")) { - unsigned char value; + unsigned char value=0; setCommand = true; if (command[1] == "AF") { value = command[2].toFloat() * 255; From 21c8b54819bc40667fd3d5370556e013eae1827f Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 Aug 2021 19:02:04 +0100 Subject: [PATCH 60/77] txrate logging wrong --- udpserver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/udpserver.cpp b/udpserver.cpp index b6eb299..95991b2 100644 --- a/udpserver.cpp +++ b/udpserver.cpp @@ -364,7 +364,7 @@ void udpServer::controlReceived() sendConnectionInfo(current); qInfo(logUdpServer()) << current->ipAddress.toString() << ": rxCodec:" << current->rxCodec << " txCodec:" << current->txCodec << " rxSampleRate" << current->rxSampleRate << - " txSampleRate" << current->rxSampleRate << + " txSampleRate" << current->txSampleRate << " txBufferLen" << current->txBufferLen; if (!config.lan) { From 758724f8af8a39948eb9fa2d97081d1a777619e9 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 Aug 2021 20:08:11 +0100 Subject: [PATCH 61/77] Fix for Opus TX audio --- udpserver.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/udpserver.cpp b/udpserver.cpp index 95991b2..3aac1dd 100644 --- a/udpserver.cpp +++ b/udpserver.cpp @@ -687,7 +687,8 @@ void udpServer::audioReceived() */ control_packet_t in = (control_packet_t)r.constData(); - if (in->type != 0x01 && in->len >= 0xAC) { + if (in->type != 0x01) { + // Opus packets can be smaller than this! && in->len >= 0xAC) { if (in->seq == 0) { // Seq number has rolled over. From c5c0046e3a3708b9e7ba54d3f29d1e0cd137fd33 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sun, 15 Aug 2021 11:19:34 +0100 Subject: [PATCH 62/77] Improve detection of unsupported codec. --- udphandler.cpp | 44 ++++++++++++++++++++++++++------------------ udphandler.h | 2 +- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/udphandler.cpp b/udphandler.cpp index 88ce282..fd25042 100644 --- a/udphandler.cpp +++ b/udphandler.cpp @@ -4,7 +4,7 @@ #include "udphandler.h" #include "logcategories.h" -udpHandler::udpHandler(udpPreferences prefs,audioSetup rx, audioSetup tx) : +udpHandler::udpHandler(udpPreferences prefs, audioSetup rx, audioSetup tx) : controlPort(prefs.controlLANPort), civPort(0), audioPort(0), @@ -237,10 +237,10 @@ void udpHandler::dataReceived() { status_packet_t in = (status_packet_t)r.constData(); if (in->type != 0x01) { - if (in->error == 0x00ffffff && !streamOpened) + if (in->error == 0xffffffff && !streamOpened) { - emit haveNetworkError(radioIP.toString(), "Auth failed, try rebooting the radio."); - qInfo(logUdp()) << this->metaObject()->className() << ": Auth failed, try rebooting the radio."; + emit haveNetworkError(radioIP.toString(), "Connection failed, wait a few minutes or reboot the radio."); + qInfo(logUdp()) << this->metaObject()->className() << ": Connection failed, wait a few minutes or reboot the radio."; } else if (in->error == 0x00000000 && in->disc == 0x01) { @@ -272,6 +272,27 @@ void udpHandler::dataReceived() { login_response_packet_t in = (login_response_packet_t)r.constData(); if (in->type != 0x01) { + + connectionType = in->connection; + qInfo(logUdp()) << "Got connection type:" << connectionType; + if (connectionType == "FTTH") + { + highBandwidthConnection = true; + } + + if (connectionType != "WFVIEW") // NOT WFVIEW + { + if (rxSetup.codec >= 0x40 || txSetup.codec >= 0x40) + { + emit haveNetworkError(QString("UDP"), QString("Opus codec not supported, forcing LPCM16")); + if (rxSetup.codec >= 0x40) + rxSetup.codec = 0x04; + if (txSetup.codec >= 0x40) + txSetup.codec = 0x04; + } + } + + if (in->error == 0xfeffffff) { emit haveNetworkStatus("Invalid Username/Password"); @@ -295,20 +316,6 @@ void udpHandler::dataReceived() } } - if (!strcmp(in->connection, "FTTH")) - { - highBandwidthConnection = true; - } - if (!strcmp(in->connection, "WFVIEW")) - { - } - else { - if (rxSetup.codec >= 0x40 || txSetup.codec >= 0x40) - { - emit haveNetworkError(QString("UDP"),QString("Opus codec not supported")); - } - } - qInfo(logUdp()) << this->metaObject()->className() << ": Detected connection speed " << in->connection; } break; @@ -317,6 +324,7 @@ void udpHandler::dataReceived() { conninfo_packet_t in = (conninfo_packet_t)r.constData(); if (in->type != 0x01) { + devName = in->name; QHostAddress ip = QHostAddress(qToBigEndian(in->ipaddress)); if (!streamOpened && in->busy) diff --git a/udphandler.h b/udphandler.h index fe155bd..c16bc4a 100644 --- a/udphandler.h +++ b/udphandler.h @@ -120,7 +120,7 @@ public: quint32 packetsLost=0; quint16 seqPrefix = 0; - + QString connectionType=""; int congestion = 0; From 04562a6ca5bcba2852a962c9aa40fc052030e411 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sun, 15 Aug 2021 11:36:08 +0100 Subject: [PATCH 63/77] Add a bit of logging for creating/destruction of opus --- audiohandler.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/audiohandler.cpp b/audiohandler.cpp index e05b226..01c4f8b 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -43,9 +43,11 @@ audioHandler::~audioHandler() qDebug(logAudio()) << "Resampler closed"; } if (encoder != Q_NULLPTR) { + qInfo(logAudio()) << "Destroying opus encoder"; opus_encoder_destroy(encoder); } if (decoder != Q_NULLPTR) { + qInfo(logAudio()) << "Destroying opus decoder"; opus_decoder_destroy(decoder); } } @@ -254,6 +256,7 @@ bool audioHandler::init(audioSetup setupIn) opus_encoder_ctl(encoder, OPUS_SET_INBAND_FEC(1)); opus_encoder_ctl(encoder, OPUS_SET_DTX(1)); opus_encoder_ctl(encoder, OPUS_SET_PACKET_LOSS_PERC(5)); + qInfo(logAudio()) << "Creating opus encoder: " << opus_strerror(opus_err); } } else { @@ -261,15 +264,12 @@ bool audioHandler::init(audioSetup setupIn) if (setup.codec == 0x40 || setup.codec == 0x80) { // Opus codec decoder = opus_decoder_create(setup.samplerate, setup.radioChan, &opus_err); + qInfo(logAudio()) << "Creating opus decoder: " << opus_strerror(opus_err); } } wf_resampler_get_ratio(resampler, &ratioNum, &ratioDen); qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "wf_resampler_init() returned: " << resample_error << " ratioNum" << ratioNum << " ratioDen" << ratioDen; - if (opus_err < 0) - { - qInfo(logAudio()) << "Faile to create opus" << (setup.isinput ? "Encoder" : "Decoder") << opus_strerror(opus_err); - } qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "thread id" << QThread::currentThreadId(); From fc2d1e24e276685429ff280468b779df2f78fab1 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sun, 15 Aug 2021 14:41:54 +0100 Subject: [PATCH 64/77] Fix for left over CIV client on server --- udpserver.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/udpserver.cpp b/udpserver.cpp index 3aac1dd..6bc80a7 100644 --- a/udpserver.cpp +++ b/udpserver.cpp @@ -461,7 +461,6 @@ void udpServer::civReceived() if (current == Q_NULLPTR) { current = new CLIENT(); - foreach(CLIENT* client, controlClients) { if (client != Q_NULLPTR) @@ -474,6 +473,13 @@ void udpServer::civReceived() } } + if (current->controlClient == Q_NULLPTR || !current->controlClient->isAuthenticated) + { + // There is no current controlClient that matches this civClient + delete current; + return; + } + current->type = "CIV"; current->civId = 0; current->connected = true; @@ -504,10 +510,6 @@ void udpServer::civReceived() } - if (current->controlClient == Q_NULLPTR || !current->controlClient->isAuthenticated) - { - return; - } switch (r.length()) { @@ -621,6 +623,14 @@ void udpServer::audioReceived() } } } + + if (current->controlClient == Q_NULLPTR || !current->controlClient->isAuthenticated) + { + // There is no current controlClient that matches this audioClient + delete current; + return; + } + current->type = "Audio"; current->connected = true; current->timeConnected = QDateTime::currentDateTime(); @@ -1581,6 +1591,7 @@ void udpServer::deleteConnection(QList* l, CLIENT* c) while (it != l->end()) { CLIENT* client = *it; if (client != Q_NULLPTR && client == c) { + qInfo(logUdpServer()) << "Found" << client->type << "connection to: " << client->ipAddress.toString() << ":" << QString::number(client->port); it = l->erase(it); } else { From 493f2f60d97300c3d13f4779e0ef35dca81b07f8 Mon Sep 17 00:00:00 2001 From: Roeland Jansen Date: Mon, 16 Aug 2021 14:40:54 +0200 Subject: [PATCH 65/77] WHATSNEW and INSTALL.md: added opus --- INSTALL.md | 5 +++-- WHATSNEW | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index d43a992..970ddab 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -13,6 +13,7 @@ sudo apt-get install libqt5multimedia5 sudo apt-get install libqt5multimedia5-plugins sudo apt-get install qtmultimedia5-dev sudo apt-get install git +sudo apt-get install libopus-dev ~~~ Now you need to install qcustomplot. There are two versions that are commonly found in linux distros: 1.3 and 2.0. Either will work fine. If you are not sure which version your linux install comes with, simply run both commands. One will work and the other will fail, and that's fine! @@ -74,7 +75,7 @@ install wfview on suse 15.x sles 15.x or tumbleweed; this was done on a clean in we need to add packages to be able to build the stuff. - sudo zypper in --type pattern devel_basis -- sudo zypper in libQt5Widgets-devel libqt5-qtbase-common-devel libqt5-qtserialport-devel libQt5SerialPort5 qcustomplot-devel libqcustomplot2 libQt5PrintSupport-devel libqt5-qtmultimedia-devel +- sudo zypper in libQt5Widgets-devel libqt5-qtbase-common-devel libqt5-qtserialport-devel libQt5SerialPort5 qcustomplot-devel libqcustomplot2 libQt5PrintSupport-devel libqt5-qtmultimedia-devel lv2-devel libopus-devel optional (mainly for development specifics): get and install qt5: @@ -107,7 +108,7 @@ wfview is now installed in /usr/local/bin Tested under Fedora 33/34. Install qt5 dependencies: -- sudo dnf install qt5-qtbase-common qt5-qtbase qt5-qtbase-gui qt5-qtserialport qt5-qtmultimedia mingw64-qt5-qmake qt5-qtbase-devel qt5-qtserialport-devel qt5-qtmultimedia-devel +- sudo dnf install qt5-qtbase-common qt5-qtbase qt5-qtbase-gui qt5-qtserialport qt5-qtmultimedia mingw64-qt5-qmake qt5-qtbase-devel qt5-qtserialport-devel qt5-qtmultimedia-devel libopus-dev Install qcustomplot: - sudo dnf install qcustomplot qcustomplot-devel diff --git a/WHATSNEW b/WHATSNEW index 15bbcbd..4cebf2d 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -5,5 +5,6 @@ The following highlights are in this 1.x-release: rigctld box added in the UI build process changed: you can add the install prefix (derSuessmann) added "do not ask again" for switching off rig and exiting wfview + added opus as audio transport From a09e8c51b81ad4de6803163f3a7ce18b949bef39 Mon Sep 17 00:00:00 2001 From: Elliott Liggett Date: Mon, 16 Aug 2021 21:51:45 -0700 Subject: [PATCH 66/77] Better meter fonts --- meter.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/meter.cpp b/meter.cpp index 07320ad..07494d2 100644 --- a/meter.cpp +++ b/meter.cpp @@ -86,20 +86,22 @@ void meter::paintEvent(QPaintEvent *) // The end effect, is that the drawing functions will all // scale to the window size. - painter.setWindow(QRect(0, 0, 255+mXstart, widgetWindowHeight)); + //painter.setWindow(QRect(0, 0, 255+mXstart, widgetWindowHeight)); - if(this->height() > widgetWindowHeight ) - { + //if(this->height() > widgetWindowHeight ) + //{ // Clamp down on stretching fonts. // TODO: Make this more elegant - painter.setFont(QFont(this->fontInfo().family(), widgetWindowHeight/3.5)); +// painter.setFont(QFont(this->fontInfo().family(), widgetWindowHeight/3.5)); + + painter.setFont(QFont(this->fontInfo().family(), fontSize)); widgetWindowHeight = this->height(); - painter.setWindow(QRect(0, 0, 255+mXstart, widgetWindowHeight)); + painter.setWindow(QRect(0, 0, 255+mXstart+15, widgetWindowHeight)); barHeight = widgetWindowHeight / 2; //painter.setFont(QFont(this->fontInfo().family(), widgetWindowHeight/2.5)); - } + //} switch(meterType) { From 7f44af239acb635ada47f8a148f8323afa99d595 Mon Sep 17 00:00:00 2001 From: Elliott Liggett Date: Mon, 16 Aug 2021 23:25:11 -0700 Subject: [PATCH 67/77] More meter work, fixed some scales and added labels. --- meter.cpp | 159 +++++++++++++++++++++++++++++++++++++++++++++--------- meter.h | 7 ++- 2 files changed, 140 insertions(+), 26 deletions(-) diff --git a/meter.cpp b/meter.cpp index 07494d2..8f0ce3b 100644 --- a/meter.cpp +++ b/meter.cpp @@ -23,6 +23,13 @@ meter::meter(QWidget *parent) : QWidget(parent) // // Text in qdarkstylesheet seems to be #EFF0F1 + if(drawLabels) + { + mXstart = 32; + } else { + mXstart = 0; + } + meterType = meterS; currentColor.setNamedColor("#148CD2"); @@ -85,52 +92,57 @@ void meter::paintEvent(QPaintEvent *) // space of the widget, and gives it corrdinates. // The end effect, is that the drawing functions will all // scale to the window size. - - //painter.setWindow(QRect(0, 0, 255+mXstart, widgetWindowHeight)); - - //if(this->height() > widgetWindowHeight ) - //{ - // Clamp down on stretching fonts. - // TODO: Make this more elegant -// painter.setFont(QFont(this->fontInfo().family(), widgetWindowHeight/3.5)); - - painter.setFont(QFont(this->fontInfo().family(), fontSize)); - widgetWindowHeight = this->height(); - painter.setWindow(QRect(0, 0, 255+mXstart+15, widgetWindowHeight)); - barHeight = widgetWindowHeight / 2; - - - //painter.setFont(QFont(this->fontInfo().family(), widgetWindowHeight/2.5)); - //} + painter.setRenderHint(QPainter::SmoothPixmapTransform); + painter.setFont(QFont(this->fontInfo().family(), fontSize)); + widgetWindowHeight = this->height(); + painter.setWindow(QRect(0, 0, 255+mXstart+15, widgetWindowHeight)); + barHeight = widgetWindowHeight / 2; switch(meterType) { case meterS: + label = "S"; peakRedLevel = 120; // S9+ drawScaleS(&painter); break; case meterPower: + label = "PWR"; peakRedLevel = 210; // 100% drawScalePo(&painter); break; case meterALC: + label = "ALC"; peakRedLevel = 100; drawScaleALC(&painter); break; case meterSWR: + label = "SWR"; peakRedLevel = 100; // SWR 2.5 drawScaleSWR(&painter); break; case meterCenter: + label = "CTR"; peakRedLevel = 256; // No need for red here drawScaleCenter(&painter); break; case meterVoltage: + label = "Vd"; peakRedLevel = 241; drawScaleVd(&painter); break; + case meterCurrent: + label = "Id"; + peakRedLevel = 120; + drawScaleId(&painter); + break; + case meterComp: + label = "CMP"; + peakRedLevel = 100; + drawScaleComp(&painter); + break; default: - peakRedLevel = 200; + label = "DN"; + peakRedLevel = 241; drawScaleRaw(&painter); break; } @@ -181,6 +193,16 @@ void meter::paintEvent(QPaintEvent *) painter.drawRect(mXstart+peak-1,mYstart,2,barHeight); } + if(drawLabels) + { + drawLabel(&painter); + } +} + +void meter::drawLabel(QPainter *qp) +{ + qp->setPen(lowLineColor); + qp->drawText(0,scaleTextYstart, label ); } void meter::setLevel(int current) @@ -231,7 +253,7 @@ void meter::drawScaleRaw(QPainter *qp) qp->setPen(lowTextColor); //qp->setFont(QFont("Arial", fontSize)); int i=mXstart; - for(; idrawText(i,scaleTextYstart, QString("%1").arg(i) ); } @@ -264,7 +286,7 @@ void meter::drawScaleVd(QPainter *qp) float VdperDn = (float)(highPointVd-midPointVd) / float(highPointDn-midPointDn); int i=mXstart; - for(; idrawText(i,scaleTextYstart, QString("%1").arg( (int)((i-mXstart) * (float(midPointVd) / float(midPointDn)) )) ); } @@ -382,6 +404,7 @@ void meter::drawScaleALC(QPainter *qp) for(; idrawText(i,scaleTextYstart, QString("%1").arg(alc) ); + qp->drawLine(i,scaleTextYstart, i, scaleTextYstart+5); alc +=20; } @@ -390,6 +413,7 @@ void meter::drawScaleALC(QPainter *qp) for(; idrawText(i,scaleTextYstart, QString("+%1").arg(alc) ); + qp->drawLine(i,scaleTextYstart, i, scaleTextYstart+5); alc +=10; } @@ -401,6 +425,44 @@ void meter::drawScaleALC(QPainter *qp) (void)qp; } +void meter::drawScaleComp(QPainter *qp) +{ + // + // 0000=0 dB, 0130=15 dB,0241=30 dB + // + + qp->setPen(lowTextColor); + + int midPointDn = 130; + int midPointdB = 15; + + int highPointDn = 241; + int highPointdB = 30; + float dBperDn = (float)(highPointdB-midPointdB) / float(highPointDn-midPointDn); + + int i=mXstart; + for(; idrawText(i,scaleTextYstart, QString("%1").arg( (int)((i-mXstart) * (float(midPointdB) / float(midPointDn)) )) ); + qp->drawLine(i,scaleTextYstart, i, scaleTextYstart+5); + } + + i = midPointDn+60; + for(; idrawText(i,scaleTextYstart, QString("%1").arg( (int) std::round( ((i-mXstart-midPointDn) * (dBperDn) ) + (midPointdB) ))); + qp->drawLine(i,scaleTextYstart, i, scaleTextYstart+5); + } + + // Now the lines: + qp->setPen(lowLineColor); + + // Line: X1, Y1 -->to--> X2, Y2 + qp->drawLine(mXstart,scaleLineYstart,peakRedLevel+mXstart,scaleLineYstart); + qp->setPen(Qt::red); + qp->drawLine(peakRedLevel+mXstart,scaleLineYstart,255+mXstart,scaleLineYstart); +} + void meter::drawScaleSWR(QPainter *qp) { // From the manual: @@ -411,26 +473,71 @@ void meter::drawScaleSWR(QPainter *qp) qp->drawText(mXstart,scaleTextYstart, QString("1.0")); qp->drawText(24+mXstart,scaleTextYstart, QString("1.3")); - qp->drawText(48+mXstart,scaleTextYstart, QString("1.5")); + qp->drawText(48+mXstart,scaleTextYstart, QString("1.5")); qp->drawText(80+mXstart,scaleTextYstart, QString("2.0")); qp->drawText(100+mXstart,scaleTextYstart, QString("2.5")); qp->drawText(120+mXstart,scaleTextYstart, QString("3.0")); + qp->drawLine( 0+mXstart,scaleTextYstart, 0+mXstart, scaleTextYstart+5); + qp->drawLine( 24+mXstart,scaleTextYstart, 24+mXstart, scaleTextYstart+5); + qp->drawLine( 48+mXstart,scaleTextYstart, 48+mXstart, scaleTextYstart+5); + qp->drawLine( 80+mXstart,scaleTextYstart, 80+mXstart, scaleTextYstart+5); + qp->drawLine(100+mXstart,scaleTextYstart,100+mXstart, scaleTextYstart+5); // does not draw? + qp->drawLine(120+mXstart,scaleTextYstart,120+mXstart, scaleTextYstart+5); + + qp->setPen(lowLineColor); qp->drawLine(mXstart,scaleLineYstart,100+mXstart,scaleLineYstart); qp->setPen(Qt::red); qp->drawLine(100+mXstart,scaleLineYstart,255+mXstart,scaleLineYstart); - (void)qp; + } void meter::drawScaleId(QPainter *qp) { - (void)qp; + // IC-7300: + // 0000=0, 0097=10, 0146=15, 0241=25 + // + + qp->setPen(lowTextColor); + //qp->setFont(QFont("Arial", fontSize)); + + // 7300/9700 and others: + int midPointDn = 97; + int midPointId = 10; + + int highPointDn = 146; + int highPointId = 15; + float IdperDn = (float)(highPointId-midPointId) / float(highPointDn-midPointDn); + + int i=mXstart; + for(; idrawText(i,scaleTextYstart, QString("%1").arg( (int)((i-mXstart) * (float(midPointId) / float(midPointDn)) )) ); + } + + for(; idrawText(i,scaleTextYstart, QString("%1").arg( (int) std::round( ((i-mXstart-midPointDn) * (IdperDn) ) + (midPointId) ))); + qp->drawLine(i,scaleTextYstart, i, scaleTextYstart+5); + } + + // Now the lines: + qp->setPen(lowLineColor); + + // Line: X1, Y1 -->to--> X2, Y2 + qp->drawLine(mXstart,scaleLineYstart,peakRedLevel+mXstart,scaleLineYstart); + qp->setPen(Qt::red); + qp->drawLine(peakRedLevel+mXstart,scaleLineYstart,255+mXstart,scaleLineYstart); } void meter::drawScaleS(QPainter *qp) { + // + // 0000=S0, 0120=S9, 0241=S9+60dB + // 120 / 9 = 13.333 steps per S-unit + qp->setPen(lowTextColor); //qp->setFont(QFont("Arial", fontSize)); int i=mXstart; @@ -439,6 +546,7 @@ void meter::drawScaleS(QPainter *qp) for(; idrawText(i,scaleTextYstart, QString("%1").arg(s++) ); + qp->drawLine(i,scaleTextYstart, i, scaleTextYstart+5); } // 2 DN per 1 dB now: @@ -454,13 +562,14 @@ void meter::drawScaleS(QPainter *qp) for(; idrawText(i,scaleTextYstart, QString("+%1").arg(s) ); + qp->drawLine(i,scaleTextYstart, i, scaleTextYstart+5); s = s + 20; } qp->setPen(lowLineColor); - qp->drawLine(mXstart,scaleLineYstart,130,scaleLineYstart); + qp->drawLine(mXstart,scaleLineYstart,peakRedLevel+mXstart,scaleLineYstart); qp->setPen(Qt::red); - qp->drawLine(130,scaleLineYstart,255,scaleLineYstart); + qp->drawLine(peakRedLevel+mXstart,scaleLineYstart,255+mXstart,scaleLineYstart); } diff --git a/meter.h b/meter.h index 1708757..472408f 100644 --- a/meter.h +++ b/meter.h @@ -50,7 +50,7 @@ private: int peakRedLevel=0; - + bool drawLabels = true; int mXstart = 0; // Starting point for S=0. int mYstart = 14; // height, down from top, where the drawing starts int barHeight = 10; // Height of meter "bar" indicators @@ -67,8 +67,13 @@ private: void drawScaleSWR(QPainter *qp); void drawScaleVd(QPainter *qp); void drawScaleId(QPainter *qp); + void drawScaleComp(QPainter *qp); void drawScaleRaw(QPainter *qp); + void drawLabel(QPainter *qp); + + QString label; + QColor currentColor; QColor averageColor; QColor peakColor; From 064d9cc2ce35038473f30f72e7595db150d75ff3 Mon Sep 17 00:00:00 2001 From: Elliott Liggett Date: Mon, 16 Aug 2021 23:37:50 -0700 Subject: [PATCH 68/77] Current scale tic marks on both sides now! --- meter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/meter.cpp b/meter.cpp index 8f0ce3b..154376b 100644 --- a/meter.cpp +++ b/meter.cpp @@ -515,6 +515,7 @@ void meter::drawScaleId(QPainter *qp) for(; idrawText(i,scaleTextYstart, QString("%1").arg( (int)((i-mXstart) * (float(midPointId) / float(midPointDn)) )) ); + qp->drawLine(i,scaleTextYstart, i, scaleTextYstart+5); } for(; i Date: Tue, 17 Aug 2021 16:11:50 +0200 Subject: [PATCH 69/77] dual meter support/WHATSNEW --- WHATSNEW | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WHATSNEW b/WHATSNEW index 4cebf2d..77dd589 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -6,5 +6,5 @@ The following highlights are in this 1.x-release: build process changed: you can add the install prefix (derSuessmann) added "do not ask again" for switching off rig and exiting wfview added opus as audio transport - + dual meter support From b8b2892a1bf0f2af8b725e9671094c753313ef37 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Tue, 17 Aug 2021 17:54:41 +0100 Subject: [PATCH 70/77] Remove unneeded submodules --- .gitmodules | 6 ------ opus-tools | 1 - rtaudio | 1 - 3 files changed, 8 deletions(-) delete mode 160000 opus-tools delete mode 160000 rtaudio diff --git a/.gitmodules b/.gitmodules index 0e24a44..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +0,0 @@ -[submodule "opus-tools"] - path = opus-tools - url = https://github.com/xiph/opus-tools.git -[submodule "rtaudio"] - path = rtaudio - url = https://github.com/thestk/rtaudio.git diff --git a/opus-tools b/opus-tools deleted file mode 160000 index ae5d6d5..0000000 --- a/opus-tools +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ae5d6d59e82ef40300a4dece7897499685f87184 diff --git a/rtaudio b/rtaudio deleted file mode 160000 index c9bf99d..0000000 --- a/rtaudio +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c9bf99d414cf81d19ef0ddd00212a4a58ccd99c6 From c2840f43d9e7a7fe2434ba9d15e85138cf37c633 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Wed, 18 Aug 2021 12:11:23 +0100 Subject: [PATCH 71/77] Update wfview.vcxproj --- wfview.vcxproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/wfview.vcxproj b/wfview.vcxproj index 847643e..bf3abb6 100644 --- a/wfview.vcxproj +++ b/wfview.vcxproj @@ -57,7 +57,7 @@ Sync release\ MaxSpeed - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX="/usr/local";__WINDOWS_WASAPI__;GITSHORT="eb2f897";HOST="wfview.org";UNAME="build";NDEBUG;QT_NO_DEBUG;%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX="/usr/local";__WINDOWS_WASAPI__;GITSHORT="fc2d1e2";HOST="wfview.org";UNAME="build";NDEBUG;QT_NO_DEBUG;%(PreprocessorDefinitions) false MultiThreadedDLL @@ -85,7 +85,7 @@ 0 - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX=\"/usr/local\";__WINDOWS_WASAPI__;GITSHORT=\"eb2f897\";HOST=\"wfview.org\";UNAME=\"build\";NDEBUG;QT_NO_DEBUG;QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX=\"/usr/local\";__WINDOWS_WASAPI__;GITSHORT=\"fc2d1e2\";HOST=\"wfview.org\";UNAME=\"build\";NDEBUG;QT_NO_DEBUG;QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;%(PreprocessorDefinitions) msvc./$(Configuration)/moc_predefs.hMoc'ing %(Identity)...output$(Configuration)moc_%(Filename).cppdefaultRcc'ing %(Identity)...$(Configuration)qrc_%(Filename).cppUic'ing %(Identity)...$(ProjectDir)ui_%(Filename).h @@ -99,7 +99,7 @@ Sync debug\ Disabled - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX="/usr/local";__WINDOWS_WASAPI__;GITSHORT="eb2f897";HOST="wfview.org";UNAME="build";%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX="/usr/local";__WINDOWS_WASAPI__;GITSHORT="fc2d1e2";HOST="wfview.org";UNAME="build";%(PreprocessorDefinitions) false MultiThreadedDebugDLL true @@ -124,7 +124,7 @@ 0 - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX=\"/usr/local\";__WINDOWS_WASAPI__;GITSHORT=\"eb2f897\";HOST=\"wfview.org\";UNAME=\"build\";QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;_DEBUG;%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX=\"/usr/local\";__WINDOWS_WASAPI__;GITSHORT=\"fc2d1e2\";HOST=\"wfview.org\";UNAME=\"build\";QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;_DEBUG;%(PreprocessorDefinitions) msvc./$(Configuration)/moc_predefs.hMoc'ing %(Identity)...output$(Configuration)moc_%(Filename).cppdefaultRcc'ing %(Identity)...$(Configuration)qrc_%(Filename).cppUic'ing %(Identity)...$(ProjectDir)ui_%(Filename).h From 58a6477f53bad1a38cb664b9c5a0e5f33f48eac4 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Thu, 19 Aug 2021 10:21:30 +0100 Subject: [PATCH 72/77] Set audio threads to be realtime priority --- udphandler.cpp | 2 ++ udpserver.cpp | 3 +++ 2 files changed, 5 insertions(+) diff --git a/udphandler.cpp b/udphandler.cpp index fd25042..3d71c05 100644 --- a/udphandler.cpp +++ b/udphandler.cpp @@ -732,6 +732,7 @@ udpAudio::udpAudio(QHostAddress local, QHostAddress ip, quint16 audioPort, audio rxaudio = new audioHandler(); rxAudioThread = new QThread(this); + rxAudioThread->setPriority(QThread::TimeCriticalPriority); rxaudio->moveToThread(rxAudioThread); @@ -749,6 +750,7 @@ udpAudio::udpAudio(QHostAddress local, QHostAddress ip, quint16 audioPort, audio txaudio = new audioHandler(); txAudioThread = new QThread(this); + txAudioThread->setPriority(QThread::TimeCriticalPriority); txaudio->moveToThread(txAudioThread); diff --git a/udpserver.cpp b/udpserver.cpp index 6bc80a7..8627284 100644 --- a/udpserver.cpp +++ b/udpserver.cpp @@ -382,6 +382,7 @@ void udpServer::controlReceived() txaudio = new audioHandler(); txAudioThread = new QThread(this); + txAudioThread->setPriority(QThread::TimeCriticalPriority); txaudio->moveToThread(txAudioThread); txAudioThread->start(); @@ -402,6 +403,8 @@ void udpServer::controlReceived() rxaudio = new audioHandler(); rxAudioThread = new QThread(this); + rxAudioThread->setPriority(QThread::TimeCriticalPriority); + rxaudio->moveToThread(rxAudioThread); rxAudioThread->start(); From d9a9a3ba2b1f50dcd1cda780e1f679fb19e91131 Mon Sep 17 00:00:00 2001 From: Elliott Liggett Date: Fri, 20 Aug 2021 22:19:47 -0700 Subject: [PATCH 73/77] Fixed issue where the "none" selection didn't work quite right. Also fixed the T/R meter switching to clear out invalid readings. --- meter.cpp | 33 ++++++++++++++++++++++++++++----- meter.h | 4 ++-- wfmain.cpp | 2 ++ 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/meter.cpp b/meter.cpp index 154376b..cc45af6 100644 --- a/meter.cpp +++ b/meter.cpp @@ -48,13 +48,23 @@ meter::meter(QWidget *parent) : QWidget(parent) } -void meter::setMeterType(meterKind type) +void meter::clearMeterOnPTTtoggle() { - if(type == meterType) - return; + // When a meter changes type, such as the fixed S -- TxPo meter, + // there is automatic clearing. However, some meters do not switch on thier own, + // and thus we are providing this clearing method. We are careful + // not to clear meters that don't make sense to clear (such as Vd and Id) - meterType = type; - // clear average and peak vectors: + + if( (meterType == meterALC) || (meterType == meterSWR) + || (meterType == meterComp) || (meterType == meterTxMod) ) + { + clearMeter(); + } +} + +void meter::clearMeter() +{ current = 0; average = 0; peak = 0; @@ -70,6 +80,16 @@ void meter::setMeterType(meterKind type) update(); } +void meter::setMeterType(meterKind type) +{ + if(type == meterType) + return; + + meterType = type; + // clear average and peak vectors: + this->clearMeter(); +} + meterKind meter::getMeterType() { return meterType; @@ -140,6 +160,9 @@ void meter::paintEvent(QPaintEvent *) peakRedLevel = 100; drawScaleComp(&painter); break; + case meterNone: + return; + break; default: label = "DN"; peakRedLevel = 241; diff --git a/meter.h b/meter.h index 472408f..d94657c 100644 --- a/meter.h +++ b/meter.h @@ -24,6 +24,8 @@ public slots: void updateDrawing(int num); void setLevels(int current, int peak, int average); void setLevel(int current); + void clearMeterOnPTTtoggle(); + void clearMeter(); void setMeterType(meterKind type); void setMeterShortString(QString); QString getMeterShortString(); @@ -47,8 +49,6 @@ private: std::vector avgLevels; std::vector peakLevels; - - int peakRedLevel=0; bool drawLabels = true; int mXstart = 0; // Starting point for S=0. diff --git a/wfmain.cpp b/wfmain.cpp index 9c83a24..2d83e08 100644 --- a/wfmain.cpp +++ b/wfmain.cpp @@ -2407,6 +2407,7 @@ void wfmain::doCmd(commandtype cmddata) { bool pttrequest = (*std::static_pointer_cast(data)); emit setPTT(pttrequest); + ui->meter2Widget->clearMeterOnPTTtoggle(); if(pttrequest) { ui->meterSPoWidget->setMeterType(meterPower); @@ -5257,6 +5258,7 @@ void wfmain::on_meter2selectionCombo_activated(int index) if(newMeterType==meterNone) { ui->meter2Widget->hide(); + ui->meter2Widget->setMeterType(newMeterType); } else { ui->meter2Widget->show(); ui->meter2Widget->setMeterType(newMeterType); From 23ccee8a21d4e96390d29ba4fadd8038be6696e1 Mon Sep 17 00:00:00 2001 From: Elliott Liggett Date: Fri, 20 Aug 2021 22:23:16 -0700 Subject: [PATCH 74/77] Clear Center readout as well. --- meter.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/meter.cpp b/meter.cpp index cc45af6..f316a6b 100644 --- a/meter.cpp +++ b/meter.cpp @@ -57,7 +57,8 @@ void meter::clearMeterOnPTTtoggle() if( (meterType == meterALC) || (meterType == meterSWR) - || (meterType == meterComp) || (meterType == meterTxMod) ) + || (meterType == meterComp) || (meterType == meterTxMod) + || (meterType == meterCenter )) { clearMeter(); } From db6a20d3d03b5d4669f303209266a18160e2ea08 Mon Sep 17 00:00:00 2001 From: Elliott Liggett Date: Mon, 23 Aug 2021 14:40:36 -0700 Subject: [PATCH 75/77] Now with dual meters for everyone! --- wfmain.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/wfmain.cpp b/wfmain.cpp index 2d83e08..2f94485 100644 --- a/wfmain.cpp +++ b/wfmain.cpp @@ -684,14 +684,9 @@ void wfmain::setupMainUI() ui->meter2selectionCombo->addItem("Center", meterCenter); ui->meter2Widget->hide(); -#ifdef QT_DEBUG - // Experimental feature: ui->meter2selectionCombo->show(); ui->secondaryMeterSelectionLabel->show(); -#else - ui->meter2selectionCombo->hide(); - ui->secondaryMeterSelectionLabel->hide(); -#endif + // Future ideas: //ui->meter2selectionCombo->addItem("Transmit Audio", meterTxMod); From 57b6f955c66358a2c0af6a4f7c66c9712bb8b476 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Mon, 23 Aug 2021 23:59:40 +0100 Subject: [PATCH 76/77] Set audio thread priority in the correct place! --- udphandler.cpp | 6 +++--- udpserver.cpp | 9 +++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/udphandler.cpp b/udphandler.cpp index fd25042..d5368a4 100644 --- a/udphandler.cpp +++ b/udphandler.cpp @@ -735,7 +735,7 @@ udpAudio::udpAudio(QHostAddress local, QHostAddress ip, quint16 audioPort, audio rxaudio->moveToThread(rxAudioThread); - rxAudioThread->start(); + rxAudioThread->start(QThread::TimeCriticalPriority); connect(this, SIGNAL(setupRxAudio(audioSetup)), rxaudio, SLOT(init(audioSetup))); @@ -752,8 +752,8 @@ udpAudio::udpAudio(QHostAddress local, QHostAddress ip, quint16 audioPort, audio txaudio->moveToThread(txAudioThread); - txAudioThread->start(); - + txAudioThread->start(QThread::TimeCriticalPriority); + connect(this, SIGNAL(setupTxAudio(audioSetup)), txaudio, SLOT(init(audioSetup))); connect(txAudioThread, SIGNAL(finished()), txaudio, SLOT(deleteLater())); diff --git a/udpserver.cpp b/udpserver.cpp index 6bc80a7..4ac5f69 100644 --- a/udpserver.cpp +++ b/udpserver.cpp @@ -384,7 +384,7 @@ void udpServer::controlReceived() txAudioThread = new QThread(this); txaudio->moveToThread(txAudioThread); - txAudioThread->start(); + txAudioThread->start(QThread::TimeCriticalPriority); connect(this, SIGNAL(setupTxAudio(audioSetup)), txaudio, SLOT(init(audioSetup))); connect(txAudioThread, SIGNAL(finished()), txaudio, SLOT(deleteLater())); @@ -401,9 +401,10 @@ void udpServer::controlReceived() inAudio.samplerate = current->rxSampleRate; rxaudio = new audioHandler(); - rxAudioThread = new QThread(this); - rxaudio->moveToThread(rxAudioThread); - rxAudioThread->start(); + rxAudioThread = new QThread(this) + + rxaudio->moveToThread(rxAudioThread); + rxAudioThread->start(QThread::TimeCriticalPriority); connect(this, SIGNAL(setupRxAudio(audioSetup)), rxaudio, SLOT(init(audioSetup))); connect(rxAudioThread, SIGNAL(finished()), rxaudio, SLOT(deleteLater())); From 7c9610283c29513659557b55eae66ab31248d3dc Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Tue, 24 Aug 2021 09:34:40 +0100 Subject: [PATCH 77/77] Replace missing ; --- udpserver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/udpserver.cpp b/udpserver.cpp index a23f28e..a23eef2 100644 --- a/udpserver.cpp +++ b/udpserver.cpp @@ -403,7 +403,7 @@ void udpServer::controlReceived() rxaudio = new audioHandler(); - rxAudioThread = new QThread(this) + rxAudioThread = new QThread(this); rxaudio->moveToThread(rxAudioThread); rxAudioThread->start(QThread::TimeCriticalPriority);