Add opus encoding/decoding

merge-requests/6/head
Phil Taylor 2021-06-16 09:49:38 +01:00
rodzic 8cd64c2dde
commit 869659ad54
5 zmienionych plików z 87 dodań i 14 usunięć

Wyświetl plik

@ -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<audioPacket>(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();
}

Wyświetl plik

@ -33,6 +33,7 @@ typedef signed short MY_TYPE;
#include <QMap>
#include "resampler/speex_resampler.h"
#include "ring/ring.h"
#include "opus.h"
#include <QDebug>
@ -179,6 +180,8 @@ private:
qreal volume=1.0;
int devChannels;
audioSetup setup;
OpusEncoder* encoder=Q_NULLPTR;
OpusDecoder* decoder=Q_NULLPTR;
};
#endif // AUDIOHANDLER_H

Wyświetl plik

@ -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();

Wyświetl plik

@ -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

Wyświetl plik

@ -48,7 +48,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>.;..\qcustomplot;resampler;rtaudio;release;/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>.;..\qcustomplot;..\opus\include;resampler;rtaudio;release;/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>-Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 %(AdditionalOptions)</AdditionalOptions>
<AssemblerListingLocation>release\</AssemblerListingLocation>
<BrowseInformation>false</BrowseInformation>
@ -57,7 +57,7 @@
<ExceptionHandling>Sync</ExceptionHandling>
<ObjectFileName>release\</ObjectFileName>
<Optimization>MaxSpeed</Optimization>
<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="ea09e1f";HOST="wfview.org";UNAME="build";QT_NO_DEBUG;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<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)</PreprocessorDefinitions>
<PreprocessToFile>false</PreprocessToFile>
<ProgramDataBaseFileName></ProgramDataBaseFileName>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
@ -66,8 +66,8 @@
<WarningLevel>Level3</WarningLevel>
<MultiProcessorCompilation>true</MultiProcessorCompilation></ClCompile>
<Link>
<AdditionalDependencies>shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>C:\opensslx86\lib;C:\Utils\my_sql\mysql-5.6.11-win32\lib;C:\Utils\postgresqlx86\pgsql\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>..\opus\win32\VS2015\Win32\Release\opus.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\opus\win32\VS2015\Win32\Release;C:\opensslx86\lib;C:\Utils\my_sql\mysql-5.6.11-win32\lib;C:\Utils\postgresqlx86\pgsql\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)</AdditionalOptions>
<DataExecutionPrevention>true</DataExecutionPrevention>
<GenerateDebugInformation>false</GenerateDebugInformation>
@ -84,12 +84,12 @@
<WarningLevel>0</WarningLevel>
</Midl>
<ResourceCompile>
<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=\"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)</PreprocessorDefinitions>
<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)</PreprocessorDefinitions>
</ResourceCompile>
<QtMoc><CompilerFlavor>msvc</CompilerFlavor><Include>./$(Configuration)/moc_predefs.h</Include><ExecutionDescription>Moc'ing %(Identity)...</ExecutionDescription><DynamicSource>output</DynamicSource><QtMocDir>$(Configuration)</QtMocDir><QtMocFileName>moc_%(Filename).cpp</QtMocFileName></QtMoc><QtRcc><Compression>default</Compression><ExecutionDescription>Rcc'ing %(Identity)...</ExecutionDescription><QtRccDir>$(Configuration)</QtRccDir><QtRccFileName>qrc_%(Filename).cpp</QtRccFileName></QtRcc><QtUic><ExecutionDescription>Uic'ing %(Identity)...</ExecutionDescription><QtUicDir>$(ProjectDir)</QtUicDir><QtUicFileName>ui_%(Filename).h</QtUicFileName></QtUic></ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>.;..\qcustomplot;resampler;rtaudio;debug;/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>.;..\qcustomplot;..\opus\include;resampler;rtaudio;debug;/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>-Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 %(AdditionalOptions)</AdditionalOptions>
<AssemblerListingLocation>debug\</AssemblerListingLocation>
<BrowseInformation>false</BrowseInformation>
@ -98,7 +98,7 @@
<ExceptionHandling>Sync</ExceptionHandling>
<ObjectFileName>debug\</ObjectFileName>
<Optimization>Disabled</Optimization>
<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="ea09e1f";HOST="wfview.org";UNAME="build";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<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)</PreprocessorDefinitions>
<PreprocessToFile>false</PreprocessToFile>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<SuppressStartupBanner>true</SuppressStartupBanner>
@ -106,8 +106,8 @@
<WarningLevel>Level3</WarningLevel>
<MultiProcessorCompilation>true</MultiProcessorCompilation></ClCompile>
<Link>
<AdditionalDependencies>shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>C:\opensslx86\lib;C:\Utils\my_sql\mysql-5.6.11-win32\lib;C:\Utils\postgresqlx86\pgsql\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>..\opus\win32\VS2015\Win32\Debug\opus.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\opus\win32\VS2015\Win32\Debug;C:\opensslx86\lib;C:\Utils\my_sql\mysql-5.6.11-win32\lib;C:\Utils\postgresqlx86\pgsql\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)</AdditionalOptions>
<DataExecutionPrevention>true</DataExecutionPrevention>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -123,7 +123,7 @@
<WarningLevel>0</WarningLevel>
</Midl>
<ResourceCompile>
<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=\"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)</PreprocessorDefinitions>
<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)</PreprocessorDefinitions>
</ResourceCompile>
<QtMoc><CompilerFlavor>msvc</CompilerFlavor><Include>./$(Configuration)/moc_predefs.h</Include><ExecutionDescription>Moc'ing %(Identity)...</ExecutionDescription><DynamicSource>output</DynamicSource><QtMocDir>$(Configuration)</QtMocDir><QtMocFileName>moc_%(Filename).cpp</QtMocFileName></QtMoc><QtRcc><Compression>default</Compression><ExecutionDescription>Rcc'ing %(Identity)...</ExecutionDescription><QtRccDir>$(Configuration)</QtRccDir><QtRccFileName>qrc_%(Filename).cpp</QtRccFileName></QtRcc><QtUic><ExecutionDescription>Uic'ing %(Identity)...</ExecutionDescription><QtUicDir>$(ProjectDir)</QtUicDir><QtUicFileName>ui_%(Filename).h</QtUicFileName></QtUic></ItemDefinitionGroup>
<ItemGroup>