mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
refactor: remove dependency on libfilteraudio
The audio filtering/echo compensation didn't ever work reliably, so just remove it.
This commit is contained in:
parent
715794f664
commit
4f7056385f
|
@ -24,7 +24,6 @@ cmake_minimum_required(VERSION 2.8.11)
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||||
|
|
||||||
option(PLATFORM_EXTENSIONS "Enable platform specific extensions, requires extra dependencies" ON)
|
option(PLATFORM_EXTENSIONS "Enable platform specific extensions, requires extra dependencies" ON)
|
||||||
option(USE_FILTERAUDIO "Enable the echo canceling backend" ON)
|
|
||||||
option(UPDATE_CHECK "Enable automatic update check" ON)
|
option(UPDATE_CHECK "Enable automatic update check" ON)
|
||||||
option(USE_CCACHE "Use ccache when available" ON)
|
option(USE_CCACHE "Use ccache when available" ON)
|
||||||
option(SPELL_CHECK "Enable spell cheching support" ON)
|
option(SPELL_CHECK "Enable spell cheching support" ON)
|
||||||
|
@ -623,19 +622,6 @@ if(AVFOUNDATION_FOUND)
|
||||||
src/platform/camera/avfoundation.h)
|
src/platform/camera/avfoundation.h)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(${USE_FILTERAUDIO})
|
|
||||||
search_dependency(FILTERAUDIO LIBRARY filteraudio HEADER filter_audio.h OPTIONAL)
|
|
||||||
if(${FILTERAUDIO_FOUND})
|
|
||||||
set(${PROJECT_NAME}_SOURCES ${${PROJECT_NAME}_SOURCES}
|
|
||||||
src/audio/backend/openal2.cpp
|
|
||||||
src/audio/backend/openal2.h)
|
|
||||||
add_definitions(-DUSE_FILTERAUDIO=1)
|
|
||||||
message(STATUS "using filteraudio")
|
|
||||||
else()
|
|
||||||
message(STATUS "not using filteraudio, libfilteraudio not found")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(${UPDATE_CHECK})
|
if(${UPDATE_CHECK})
|
||||||
add_definitions(-DUPDATE_CHECK_ENABLED=1)
|
add_definitions(-DUPDATE_CHECK_ENABLED=1)
|
||||||
set(${PROJECT_NAME}_SOURCES ${${PROJECT_NAME}_SOURCES}
|
set(${PROJECT_NAME}_SOURCES ${${PROJECT_NAME}_SOURCES}
|
||||||
|
|
|
@ -46,7 +46,6 @@
|
||||||
| [qrencode] | >= 3.0.3 | |
|
| [qrencode] | >= 3.0.3 | |
|
||||||
| [sqlcipher] | >= 3.2.0 | |
|
| [sqlcipher] | >= 3.2.0 | |
|
||||||
| [pkg-config] | >= 0.28 | |
|
| [pkg-config] | >= 0.28 | |
|
||||||
| [filteraudio] | >= 0.0.1 | optional dependency |
|
|
||||||
| [snorenotify] | >= 0.7.0 | optional dependency |
|
| [snorenotify] | >= 0.7.0 | optional dependency |
|
||||||
|
|
||||||
## Optional dependencies
|
## Optional dependencies
|
||||||
|
@ -812,6 +811,5 @@ Switches:
|
||||||
[Qt]: https://www.qt.io/
|
[Qt]: https://www.qt.io/
|
||||||
[sqlcipher]: https://www.zetetic.net/sqlcipher/
|
[sqlcipher]: https://www.zetetic.net/sqlcipher/
|
||||||
[toxcore]: https://github.com/TokTok/c-toxcore/
|
[toxcore]: https://github.com/TokTok/c-toxcore/
|
||||||
[filteraudio]: https://github.com/irungentoo/filter_audio
|
|
||||||
[sonnet]: https://github.com/KDE/sonnet
|
[sonnet]: https://github.com/KDE/sonnet
|
||||||
[snorenotify]: https://techbase.kde.org/Projects/Snorenotify
|
[snorenotify]: https://techbase.kde.org/Projects/Snorenotify
|
||||||
|
|
|
@ -41,7 +41,6 @@ QT_VER=($(ls ${QT_DIR} | sed -n -e 's/^\([0-9]*\.([0-9]*\.([0-9]*\).*/\1/' -e '1
|
||||||
QT_DIR_VER="${QT_DIR}/${QT_VER[1]}"
|
QT_DIR_VER="${QT_DIR}/${QT_VER[1]}"
|
||||||
|
|
||||||
TOXCORE_DIR="${MAIN_DIR}/toxcore" # Change to Git location
|
TOXCORE_DIR="${MAIN_DIR}/toxcore" # Change to Git location
|
||||||
FILTERAUIO_DIR="${MAIN_DIR}/filter_audio" # Change to Git location
|
|
||||||
|
|
||||||
LIB_INSTALL_PREFIX="${QTOX_DIR}/libs"
|
LIB_INSTALL_PREFIX="${QTOX_DIR}/libs"
|
||||||
|
|
||||||
|
@ -208,12 +207,6 @@ install() {
|
||||||
kill $DOT_PID
|
kill $DOT_PID
|
||||||
fi
|
fi
|
||||||
|
|
||||||
fcho "Cloning filter_audio ... "
|
|
||||||
git clone --branch v0.0.1 --depth=1 https://github.com/irungentoo/filter_audio "$FILTERAUIO_DIR"
|
|
||||||
cd "$FILTERAUIO_DIR"
|
|
||||||
fcho "Installing filter_audio ... "
|
|
||||||
make install PREFIX="$LIB_INSTALL_PREFIX"
|
|
||||||
|
|
||||||
QT_VER=($(ls ${QT_DIR} | sed -n -e 's/^\([0-9]*\.([0-9]*\.([0-9]*\).*/\1/' -e '1p;$p'))
|
QT_VER=($(ls ${QT_DIR} | sed -n -e 's/^\([0-9]*\.([0-9]*\.([0-9]*\).*/\1/' -e '1p;$p'))
|
||||||
QT_DIR_VER="${QT_DIR}/${QT_VER[1]}"
|
QT_DIR_VER="${QT_DIR}/${QT_VER[1]}"
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,6 @@
|
||||||
#include "src/audio/audio.h"
|
#include "src/audio/audio.h"
|
||||||
#include "src/audio/iaudiosettings.h"
|
#include "src/audio/iaudiosettings.h"
|
||||||
#include "src/audio/backend/openal.h"
|
#include "src/audio/backend/openal.h"
|
||||||
#ifdef USE_FILTERAUDIO
|
|
||||||
#include "src/audio/backend/openal2.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Select the audio backend
|
* @brief Select the audio backend
|
||||||
|
@ -33,14 +30,5 @@
|
||||||
*/
|
*/
|
||||||
std::unique_ptr<IAudioControl> Audio::makeAudio(IAudioSettings& settings)
|
std::unique_ptr<IAudioControl> Audio::makeAudio(IAudioSettings& settings)
|
||||||
{
|
{
|
||||||
#ifdef USE_FILTERAUDIO
|
|
||||||
const bool Backend2 = settings.getEnableBackend2();
|
|
||||||
|
|
||||||
if (Backend2) {
|
|
||||||
return std::unique_ptr<IAudioControl>(new OpenAL2());
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
return std::unique_ptr<IAudioControl>(new OpenAL());
|
return std::unique_ptr<IAudioControl>(new OpenAL());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,357 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright © 2017-2019 by The qTox Project Contributors
|
|
||||||
|
|
||||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
|
||||||
|
|
||||||
qTox is libre software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
qTox is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with qTox. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "openal2.h"
|
|
||||||
#include "src/persistence/settings.h"
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QFile>
|
|
||||||
#include <QMutexLocker>
|
|
||||||
#include <QPointer>
|
|
||||||
#include <QThread>
|
|
||||||
#include <QWaitCondition>
|
|
||||||
#include <QtMath>
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#include <filter_audio.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class OpenAL
|
|
||||||
* @brief Provides the OpenAL audio backend
|
|
||||||
*
|
|
||||||
* The following graphic describes the audio rendering pipeline with echo canceling
|
|
||||||
*
|
|
||||||
* | alProxyContext | | alOutContext |
|
|
||||||
* peerSources[] | | |
|
|
||||||
* \ | | |
|
|
||||||
* -> alProxyDev -> filter_audio -> alProxySource -> alOutDev -> Soundcard
|
|
||||||
* /
|
|
||||||
* alMainSource
|
|
||||||
*
|
|
||||||
* Without echo cancelling the pipeline is simplified through alProxyDev = alOutDev
|
|
||||||
* and alProxyContext = alOutContext
|
|
||||||
*
|
|
||||||
* | alProxyContext |
|
|
||||||
* peerSources[] |
|
|
||||||
* \ |
|
|
||||||
* -> alOutDev -> Soundcard
|
|
||||||
* /
|
|
||||||
* alMainSource
|
|
||||||
*
|
|
||||||
* To keep all functions in writing to the correct context, all functions changing
|
|
||||||
* the context MUST exit with alProxyContext as active context and MUST not be
|
|
||||||
* interrupted. For this to work, all functions of the base class modifying the
|
|
||||||
* context have to be overriden.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static const unsigned int PROXY_BUFFER_COUNT = 4;
|
|
||||||
|
|
||||||
#define GET_PROC_ADDR(dev, name) name = reinterpret_cast<LP##name>(alcGetProcAddress(dev, #name))
|
|
||||||
|
|
||||||
typedef LPALCLOOPBACKOPENDEVICESOFT LPalcLoopbackOpenDeviceSOFT;
|
|
||||||
typedef LPALCISRENDERFORMATSUPPORTEDSOFT LPalcIsRenderFormatSupportedSOFT;
|
|
||||||
typedef LPALGETSOURCEDVSOFT LPalGetSourcedvSOFT;
|
|
||||||
typedef LPALCRENDERSAMPLESSOFT LPalcRenderSamplesSOFT;
|
|
||||||
|
|
||||||
|
|
||||||
OpenAL2::OpenAL2()
|
|
||||||
: alProxyDev{nullptr}
|
|
||||||
, alProxyContext{nullptr}
|
|
||||||
, alProxySource{0}
|
|
||||||
, alProxyBuffer{0}
|
|
||||||
{}
|
|
||||||
|
|
||||||
bool OpenAL2::initInput(const QString& deviceName)
|
|
||||||
{
|
|
||||||
return OpenAL::initInput(deviceName, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Loads the OpenAL extension methods needed for echo cancellation
|
|
||||||
* @param dev OpenAL device used for the output
|
|
||||||
* @return True when functions successfully loaded, false otherwise
|
|
||||||
*/
|
|
||||||
bool OpenAL2::loadOpenALExtensions(ALCdevice* dev)
|
|
||||||
{
|
|
||||||
// load OpenAL extension functions
|
|
||||||
GET_PROC_ADDR(dev, alcLoopbackOpenDeviceSOFT);
|
|
||||||
checkAlcError(dev);
|
|
||||||
if (!alcLoopbackOpenDeviceSOFT) {
|
|
||||||
qDebug() << "Failed to load alcLoopbackOpenDeviceSOFT function!";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
GET_PROC_ADDR(dev, alcIsRenderFormatSupportedSOFT);
|
|
||||||
checkAlcError(dev);
|
|
||||||
if (!alcIsRenderFormatSupportedSOFT) {
|
|
||||||
qDebug() << "Failed to load alcIsRenderFormatSupportedSOFT function!";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
GET_PROC_ADDR(dev, alGetSourcedvSOFT);
|
|
||||||
checkAlcError(dev);
|
|
||||||
if (!alGetSourcedvSOFT) {
|
|
||||||
qDebug() << "Failed to load alGetSourcedvSOFT function!";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
GET_PROC_ADDR(dev, alcRenderSamplesSOFT);
|
|
||||||
checkAlcError(dev);
|
|
||||||
if (!alcRenderSamplesSOFT) {
|
|
||||||
qDebug() << "Failed to load alcRenderSamplesSOFT function!";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Initializes the output with echo cancelling enabled
|
|
||||||
* @return true on success, false otherwise
|
|
||||||
* Creates a loopback device and a proxy source on the main output device.
|
|
||||||
* If this function returns true only the proxy source should be used for
|
|
||||||
* audio output.
|
|
||||||
*/
|
|
||||||
bool OpenAL2::initOutputEchoCancel()
|
|
||||||
{
|
|
||||||
// check for the needed extensions for echo cancelation
|
|
||||||
if (alcIsExtensionPresent(alOutDev, "ALC_SOFT_loopback") != AL_TRUE) {
|
|
||||||
qDebug() << "Device doesn't support loopback";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (alIsExtensionPresent("AL_SOFT_source_latency") != AL_TRUE) {
|
|
||||||
qDebug() << "Device doesn't support source latency";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!loadOpenALExtensions(alOutDev)) {
|
|
||||||
qDebug() << "Couldn't load needed OpenAL extensions";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// source for proxy output
|
|
||||||
alGenSources(1, &alProxySource);
|
|
||||||
checkAlError();
|
|
||||||
|
|
||||||
// configuration for the loopback device
|
|
||||||
ALCint attrs[] = {ALC_FORMAT_CHANNELS_SOFT,
|
|
||||||
ALC_MONO_SOFT,
|
|
||||||
ALC_FORMAT_TYPE_SOFT,
|
|
||||||
ALC_SHORT_SOFT,
|
|
||||||
ALC_FREQUENCY,
|
|
||||||
IAudioControl::AUDIO_SAMPLE_RATE,
|
|
||||||
0}; // End of List
|
|
||||||
|
|
||||||
alProxyDev = alcLoopbackOpenDeviceSOFT(nullptr);
|
|
||||||
checkAlcError(alProxyDev);
|
|
||||||
if (!alProxyDev) {
|
|
||||||
qDebug() << "Couldn't create proxy device";
|
|
||||||
alDeleteSources(1, &alProxySource); // cleanup source
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!alcIsRenderFormatSupportedSOFT(alProxyDev, attrs[5], attrs[1], attrs[3])) {
|
|
||||||
qDebug() << "Unsupported format for loopback";
|
|
||||||
alcCloseDevice(alProxyDev); // cleanup loopback dev
|
|
||||||
alDeleteSources(1, &alProxySource); // cleanup source
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
alProxyContext = alcCreateContext(alProxyDev, attrs);
|
|
||||||
checkAlcError(alProxyDev);
|
|
||||||
if (!alProxyContext) {
|
|
||||||
qDebug() << "Couldn't create proxy context";
|
|
||||||
alcCloseDevice(alProxyDev); // cleanup loopback dev
|
|
||||||
alDeleteSources(1, &alProxySource); // cleanup source
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!alcMakeContextCurrent(alProxyContext)) {
|
|
||||||
qDebug() << "Cannot activate proxy context";
|
|
||||||
alcDestroyContext(alProxyContext);
|
|
||||||
alcCloseDevice(alProxyDev); // cleanup loopback dev
|
|
||||||
alDeleteSources(1, &alProxySource); // cleanup source
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
qDebug() << "Echo cancelation enabled";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Open an audio output device
|
|
||||||
*/
|
|
||||||
bool OpenAL2::initOutput(const QString& deviceName)
|
|
||||||
{
|
|
||||||
assert(sinks.empty());
|
|
||||||
|
|
||||||
outputInitialized = false;
|
|
||||||
if (!Settings::getInstance().getAudioOutDevEnabled()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
qDebug() << "Opening audio output" << deviceName;
|
|
||||||
assert(!alOutDev);
|
|
||||||
|
|
||||||
const QByteArray qDevName = deviceName.toUtf8();
|
|
||||||
const ALchar* tmpDevName = qDevName.isEmpty() ? nullptr : qDevName.constData();
|
|
||||||
alOutDev = alcOpenDevice(tmpDevName);
|
|
||||||
|
|
||||||
if (!alOutDev) {
|
|
||||||
qWarning() << "Cannot open output audio device" << deviceName;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
qDebug() << "Opened audio output" << deviceName;
|
|
||||||
alOutContext = alcCreateContext(alOutDev, nullptr);
|
|
||||||
checkAlcError(alOutDev);
|
|
||||||
|
|
||||||
if (!alcMakeContextCurrent(alOutContext)) {
|
|
||||||
qWarning() << "Cannot create output audio context";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// try to init echo cancellation
|
|
||||||
echoCancelSupported = initOutputEchoCancel();
|
|
||||||
|
|
||||||
if (!echoCancelSupported) {
|
|
||||||
// fallback to normal, no proxy device needed
|
|
||||||
qDebug() << "Echo cancellation disabled";
|
|
||||||
alProxyDev = alOutDev;
|
|
||||||
alProxyContext = alOutContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
// init master volume
|
|
||||||
alListenerf(AL_GAIN, Settings::getInstance().getOutVolume() * 0.01f);
|
|
||||||
checkAlError();
|
|
||||||
|
|
||||||
// ensure alProxyContext is active
|
|
||||||
alcMakeContextCurrent(alProxyContext);
|
|
||||||
outputInitialized = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Close active audio output device
|
|
||||||
*/
|
|
||||||
void OpenAL2::cleanupOutput()
|
|
||||||
{
|
|
||||||
OpenAL::cleanupOutput();
|
|
||||||
|
|
||||||
if (echoCancelSupported) {
|
|
||||||
alcMakeContextCurrent(alOutContext);
|
|
||||||
alSourceStop(alProxySource);
|
|
||||||
ALint processed = 0;
|
|
||||||
ALuint bufids[PROXY_BUFFER_COUNT];
|
|
||||||
alGetSourcei(alProxySource, AL_BUFFERS_PROCESSED, &processed);
|
|
||||||
alSourceUnqueueBuffers(alProxySource, processed, bufids);
|
|
||||||
alDeleteBuffers(processed, bufids);
|
|
||||||
alcMakeContextCurrent(nullptr);
|
|
||||||
alcDestroyContext(alOutContext);
|
|
||||||
alOutContext = nullptr;
|
|
||||||
alcCloseDevice(alOutDev);
|
|
||||||
alOutDev = nullptr;
|
|
||||||
} else {
|
|
||||||
alOutContext = nullptr;
|
|
||||||
alOutDev = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Handle audio output
|
|
||||||
*/
|
|
||||||
void OpenAL2::doOutput()
|
|
||||||
{
|
|
||||||
if (!echoCancelSupported) {
|
|
||||||
kill_filter_audio(filterer);
|
|
||||||
filterer = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
alcMakeContextCurrent(alOutContext);
|
|
||||||
ALuint bufids[PROXY_BUFFER_COUNT];
|
|
||||||
ALint processed = 0, queued = 0;
|
|
||||||
alGetSourcei(alProxySource, AL_BUFFERS_PROCESSED, &processed);
|
|
||||||
alGetSourcei(alProxySource, AL_BUFFERS_QUEUED, &queued);
|
|
||||||
|
|
||||||
if (processed > 0) {
|
|
||||||
// unqueue all processed buffers
|
|
||||||
alSourceUnqueueBuffers(alProxySource, processed, bufids);
|
|
||||||
// delete all but the first buffer, reuse first for new data
|
|
||||||
alDeleteBuffers(processed - 1, bufids + 1);
|
|
||||||
} else if (queued < static_cast<ALint>(PROXY_BUFFER_COUNT)) {
|
|
||||||
// create new buffer until the maximum is reached
|
|
||||||
alGenBuffers(1, bufids);
|
|
||||||
} else {
|
|
||||||
alcMakeContextCurrent(alProxyContext);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ALdouble latency[2] = {0};
|
|
||||||
if (echoCancelSupported) {
|
|
||||||
alGetSourcedvSOFT(alProxySource, AL_SEC_OFFSET_LATENCY_SOFT, latency);
|
|
||||||
}
|
|
||||||
|
|
||||||
checkAlError();
|
|
||||||
|
|
||||||
ALshort outBuf[AUDIO_FRAME_SAMPLE_COUNT_PER_CHANNEL] = {0};
|
|
||||||
if (echoCancelSupported) {
|
|
||||||
alcMakeContextCurrent(alProxyContext);
|
|
||||||
alcRenderSamplesSOFT(alProxyDev, outBuf, AUDIO_FRAME_SAMPLE_COUNT_PER_CHANNEL);
|
|
||||||
checkAlcError(alProxyDev);
|
|
||||||
|
|
||||||
alcMakeContextCurrent(alOutContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
alBufferData(bufids[0], AL_FORMAT_MONO16, outBuf, AUDIO_FRAME_SAMPLE_COUNT_PER_CHANNEL * 2,
|
|
||||||
AUDIO_SAMPLE_RATE);
|
|
||||||
|
|
||||||
alSourceQueueBuffers(alProxySource, 1, bufids);
|
|
||||||
|
|
||||||
// initialize echo canceler if supported
|
|
||||||
if (echoCancelSupported && !filterer) {
|
|
||||||
filterer = new_filter_audio(AUDIO_SAMPLE_RATE);
|
|
||||||
int16_t filterLatency = latency[1] * 1000 * 2 + AUDIO_FRAME_DURATION;
|
|
||||||
qDebug() << "Setting filter delay to: " << filterLatency << "ms";
|
|
||||||
set_echo_delay_ms(filterer, filterLatency);
|
|
||||||
enable_disable_filters(filterer, 1, 1, 1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// do echo cancel
|
|
||||||
pass_audio_output(filterer, outBuf, AUDIO_FRAME_SAMPLE_COUNT_PER_CHANNEL);
|
|
||||||
|
|
||||||
ALint state;
|
|
||||||
alGetSourcei(alProxySource, AL_SOURCE_STATE, &state);
|
|
||||||
if (state != AL_PLAYING) {
|
|
||||||
qDebug() << "Proxy source underflow detected";
|
|
||||||
alSourcePlay(alProxySource);
|
|
||||||
}
|
|
||||||
alcMakeContextCurrent(alProxyContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenAL2::captureSamples(ALCdevice* device, int16_t* buffer, ALCsizei samples)
|
|
||||||
{
|
|
||||||
alcCaptureSamples(device, buffer, samples);
|
|
||||||
if (echoCancelSupported && filterer) {
|
|
||||||
filter_audio(filterer, buffer, samples);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,83 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright © 2014-2019 by The qTox Project Contributors
|
|
||||||
|
|
||||||
This file is part of qTox, a Qt-based graphical interface for Tox.
|
|
||||||
|
|
||||||
qTox is libre software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
qTox is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with qTox. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef OPENAL2_H
|
|
||||||
#define OPENAL2_H
|
|
||||||
|
|
||||||
#include "src/audio/iaudiocontrol.h"
|
|
||||||
#include "src/audio/backend/openal.h"
|
|
||||||
|
|
||||||
#include <atomic>
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
#include <QMutex>
|
|
||||||
#include <QObject>
|
|
||||||
#include <QTimer>
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
#include <AL/al.h>
|
|
||||||
#include <AL/alc.h>
|
|
||||||
#include <AL/alext.h>
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#include <filter_audio.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
// needed because Ubuntu 14.04 lacks the AL_SOFT_source_latency extension
|
|
||||||
#ifndef AL_SOFT_source_latency
|
|
||||||
#define AL_SAMPLE_OFFSET_LATENCY_SOFT 0x1200
|
|
||||||
#define AL_SEC_OFFSET_LATENCY_SOFT 0x1201
|
|
||||||
extern "C" typedef void(AL_APIENTRY* LPALGETSOURCEDVSOFT)(ALuint, ALenum, const ALdouble*);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class OpenAL2 : public OpenAL
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
OpenAL2();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool initInput(const QString& deviceName) override;
|
|
||||||
bool initOutput(const QString& outDevDescr) override;
|
|
||||||
void cleanupOutput() override;
|
|
||||||
void playMono16SoundCleanup();
|
|
||||||
void doOutput() override;
|
|
||||||
bool loadOpenALExtensions(ALCdevice* dev);
|
|
||||||
bool initOutputEchoCancel();
|
|
||||||
void captureSamples(ALCdevice* device, int16_t* buffer, ALCsizei samples) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
ALCdevice* alProxyDev;
|
|
||||||
ALCcontext* alProxyContext;
|
|
||||||
ALuint alProxySource;
|
|
||||||
ALuint alProxyBuffer;
|
|
||||||
bool echoCancelSupported = false;
|
|
||||||
|
|
||||||
Filter_Audio* filterer = nullptr;
|
|
||||||
LPALCLOOPBACKOPENDEVICESOFT alcLoopbackOpenDeviceSOFT = nullptr;
|
|
||||||
LPALCISRENDERFORMATSUPPORTEDSOFT alcIsRenderFormatSupportedSOFT = nullptr;
|
|
||||||
LPALGETSOURCEDVSOFT alGetSourcedvSOFT = nullptr;
|
|
||||||
LPALCRENDERSAMPLESSOFT alcRenderSamplesSOFT = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // OPENAL2_H
|
|
|
@ -57,9 +57,6 @@ public:
|
||||||
virtual bool getEnableTestSound() const = 0;
|
virtual bool getEnableTestSound() const = 0;
|
||||||
virtual void setEnableTestSound(bool newValue) = 0;
|
virtual void setEnableTestSound(bool newValue) = 0;
|
||||||
|
|
||||||
virtual bool getEnableBackend2() const = 0;
|
|
||||||
virtual void setEnableBackend2(bool enabled) = 0;
|
|
||||||
|
|
||||||
DECLARE_SIGNAL(inDevChanged, const QString& device);
|
DECLARE_SIGNAL(inDevChanged, const QString& device);
|
||||||
DECLARE_SIGNAL(audioInDevEnabledChanged, bool enabled);
|
DECLARE_SIGNAL(audioInDevEnabledChanged, bool enabled);
|
||||||
|
|
||||||
|
@ -71,7 +68,6 @@ public:
|
||||||
DECLARE_SIGNAL(outVolumeChanged, int volume);
|
DECLARE_SIGNAL(outVolumeChanged, int volume);
|
||||||
DECLARE_SIGNAL(audioBitrateChanged, int bitrate);
|
DECLARE_SIGNAL(audioBitrateChanged, int bitrate);
|
||||||
DECLARE_SIGNAL(enableTestSoundChanged, bool newValue);
|
DECLARE_SIGNAL(enableTestSoundChanged, bool newValue);
|
||||||
DECLARE_SIGNAL(enableBackend2Changed, bool enabled);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // I_AUDIO_SETTINGS_H
|
#endif // I_AUDIO_SETTINGS_H
|
||||||
|
|
|
@ -243,10 +243,6 @@ void Settings::loadGlobal()
|
||||||
outVolume = s.value("outVolume", 100).toInt();
|
outVolume = s.value("outVolume", 100).toInt();
|
||||||
enableTestSound = s.value("enableTestSound", true).toBool();
|
enableTestSound = s.value("enableTestSound", true).toBool();
|
||||||
audioBitrate = s.value("audioBitrate", 64).toInt();
|
audioBitrate = s.value("audioBitrate", 64).toInt();
|
||||||
enableBackend2 = false;
|
|
||||||
#ifdef USE_FILTERAUDIO
|
|
||||||
enableBackend2 = s.value("enableBackend2", false).toBool();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
s.endGroup();
|
s.endGroup();
|
||||||
|
|
||||||
|
@ -714,7 +710,6 @@ void Settings::saveGlobal()
|
||||||
s.setValue("outVolume", outVolume);
|
s.setValue("outVolume", outVolume);
|
||||||
s.setValue("enableTestSound", enableTestSound);
|
s.setValue("enableTestSound", enableTestSound);
|
||||||
s.setValue("audioBitrate", audioBitrate);
|
s.setValue("audioBitrate", audioBitrate);
|
||||||
s.setValue("enableBackend2", enableBackend2);
|
|
||||||
}
|
}
|
||||||
s.endGroup();
|
s.endGroup();
|
||||||
|
|
||||||
|
@ -2012,22 +2007,6 @@ void Settings::setAudioBitrate(int bitrate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Settings::getEnableBackend2() const
|
|
||||||
{
|
|
||||||
QMutexLocker locker{&bigLock};
|
|
||||||
return enableBackend2;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Settings::setEnableBackend2(bool enabled)
|
|
||||||
{
|
|
||||||
QMutexLocker locker{&bigLock};
|
|
||||||
|
|
||||||
if (enabled != enableBackend2) {
|
|
||||||
enableBackend2 = enabled;
|
|
||||||
emit enableBackend2Changed(enabled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QRect Settings::getScreenRegion() const
|
QRect Settings::getScreenRegion() const
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&bigLock);
|
QMutexLocker locker(&bigLock);
|
||||||
|
|
|
@ -118,8 +118,6 @@ class Settings : public QObject,
|
||||||
audioOutDevEnabledChanged FINAL)
|
audioOutDevEnabledChanged FINAL)
|
||||||
Q_PROPERTY(int outVolume READ getOutVolume WRITE setOutVolume NOTIFY outVolumeChanged FINAL)
|
Q_PROPERTY(int outVolume READ getOutVolume WRITE setOutVolume NOTIFY outVolumeChanged FINAL)
|
||||||
Q_PROPERTY(int audioBitrate READ getAudioBitrate WRITE setAudioBitrate NOTIFY audioBitrateChanged FINAL)
|
Q_PROPERTY(int audioBitrate READ getAudioBitrate WRITE setAudioBitrate NOTIFY audioBitrateChanged FINAL)
|
||||||
Q_PROPERTY(bool enableBackend2 READ getEnableBackend2 WRITE setEnableBackend2 NOTIFY
|
|
||||||
enableBackend2Changed FINAL)
|
|
||||||
|
|
||||||
// Video
|
// Video
|
||||||
Q_PROPERTY(QString videoDev READ getVideoDev WRITE setVideoDev NOTIFY videoDevChanged FINAL)
|
Q_PROPERTY(QString videoDev READ getVideoDev WRITE setVideoDev NOTIFY videoDevChanged FINAL)
|
||||||
|
@ -371,9 +369,6 @@ public:
|
||||||
bool getEnableTestSound() const override;
|
bool getEnableTestSound() const override;
|
||||||
void setEnableTestSound(bool newValue) override;
|
void setEnableTestSound(bool newValue) override;
|
||||||
|
|
||||||
bool getEnableBackend2() const override;
|
|
||||||
void setEnableBackend2(bool enabled) override;
|
|
||||||
|
|
||||||
SIGNAL_IMPL(Settings, inDevChanged, const QString& device)
|
SIGNAL_IMPL(Settings, inDevChanged, const QString& device)
|
||||||
SIGNAL_IMPL(Settings, audioInDevEnabledChanged, bool enabled)
|
SIGNAL_IMPL(Settings, audioInDevEnabledChanged, bool enabled)
|
||||||
|
|
||||||
|
@ -385,7 +380,6 @@ public:
|
||||||
SIGNAL_IMPL(Settings, outVolumeChanged, int volume)
|
SIGNAL_IMPL(Settings, outVolumeChanged, int volume)
|
||||||
SIGNAL_IMPL(Settings, audioBitrateChanged, int bitrate)
|
SIGNAL_IMPL(Settings, audioBitrateChanged, int bitrate)
|
||||||
SIGNAL_IMPL(Settings, enableTestSoundChanged, bool newValue)
|
SIGNAL_IMPL(Settings, enableTestSoundChanged, bool newValue)
|
||||||
SIGNAL_IMPL(Settings, enableBackend2Changed, bool enabled)
|
|
||||||
|
|
||||||
QString getVideoDev() const override;
|
QString getVideoDev() const override;
|
||||||
void setVideoDev(const QString& deviceSpecifier) override;
|
void setVideoDev(const QString& deviceSpecifier) override;
|
||||||
|
@ -673,7 +667,6 @@ private:
|
||||||
int outVolume;
|
int outVolume;
|
||||||
int audioBitrate;
|
int audioBitrate;
|
||||||
bool enableTestSound;
|
bool enableTestSound;
|
||||||
bool enableBackend2;
|
|
||||||
|
|
||||||
// Video
|
// Video
|
||||||
QString videoDev;
|
QString videoDev;
|
||||||
|
|
|
@ -62,11 +62,6 @@ AVForm::AVForm(IAudioControl& audio, CoreAV* coreAV, CameraSource& camera,
|
||||||
cbEnableTestSound->setChecked(audioSettings->getEnableTestSound());
|
cbEnableTestSound->setChecked(audioSettings->getEnableTestSound());
|
||||||
cbEnableTestSound->setToolTip(tr("Play a test sound while changing the output volume."));
|
cbEnableTestSound->setToolTip(tr("Play a test sound while changing the output volume."));
|
||||||
|
|
||||||
#ifndef USE_FILTERAUDIO
|
|
||||||
cbEnableBackend2->setVisible(false);
|
|
||||||
#endif
|
|
||||||
cbEnableBackend2->setChecked(audioSettings->getEnableBackend2());
|
|
||||||
|
|
||||||
connect(rescanButton, &QPushButton::clicked, this, &AVForm::rescanDevices);
|
connect(rescanButton, &QPushButton::clicked, this, &AVForm::rescanDevices);
|
||||||
|
|
||||||
playbackSlider->setTracking(false);
|
playbackSlider->setTracking(false);
|
||||||
|
@ -179,11 +174,6 @@ void AVForm::setVolume(float value)
|
||||||
volumeDisplay->setValue(getStepsFromValue(value, audio.minOutputVolume(), audio.maxOutputVolume()));
|
volumeDisplay->setValue(getStepsFromValue(value, audio.minOutputVolume(), audio.maxOutputVolume()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AVForm::on_cbEnableBackend2_stateChanged()
|
|
||||||
{
|
|
||||||
audioSettings->setEnableBackend2(cbEnableBackend2->isChecked());
|
|
||||||
}
|
|
||||||
|
|
||||||
void AVForm::on_videoModescomboBox_currentIndexChanged(int index)
|
void AVForm::on_videoModescomboBox_currentIndexChanged(int index)
|
||||||
{
|
{
|
||||||
assert(0 <= index && index < videoModes.size());
|
assert(0 <= index && index < videoModes.size());
|
||||||
|
|
|
@ -84,8 +84,6 @@ private slots:
|
||||||
void rescanDevices();
|
void rescanDevices();
|
||||||
void setVolume(float value);
|
void setVolume(float value);
|
||||||
|
|
||||||
void on_cbEnableBackend2_stateChanged();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void updateVideoModes(int curIndex);
|
void updateVideoModes(int curIndex);
|
||||||
|
|
||||||
|
|
|
@ -124,12 +124,12 @@
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="1" colspan="2">
|
<item row="5" column="1" colspan="2">
|
||||||
<widget class="QProgressBar" name="volumeDisplay">
|
<widget class="QProgressBar" name="volumeDisplay">
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="textVisible">
|
<property name="textVisible">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
|
@ -159,19 +159,6 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="0" colspan="3">
|
|
||||||
<widget class="QCheckBox" name="cbEnableBackend2">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Enables the experimental audio backend with echo cancelling support, needs qTox restart to take effect.</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Enable experimental audio backend</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -95,7 +95,6 @@ workspace
|
||||||
│ ├── dep-cache
|
│ ├── dep-cache
|
||||||
│ │ ├── libexif
|
│ │ ├── libexif
|
||||||
│ │ ├── libffmpeg
|
│ │ ├── libffmpeg
|
||||||
│ │ ├── libfilteraudio
|
|
||||||
│ │ ├── libopenal
|
│ │ ├── libopenal
|
||||||
│ │ ├── libopenssl
|
│ │ ├── libopenssl
|
||||||
│ │ ├── libopus
|
│ │ ├── libopus
|
||||||
|
@ -114,7 +113,6 @@ workspace
|
||||||
├── dep-cache
|
├── dep-cache
|
||||||
│ ├── libexif
|
│ ├── libexif
|
||||||
│ ├── libffmpeg
|
│ ├── libffmpeg
|
||||||
│ ├── libfilteraudio
|
|
||||||
│ ├── libopenal
|
│ ├── libopenal
|
||||||
│ ├── libopenssl
|
│ ├── libopenssl
|
||||||
│ ├── libopus
|
│ ├── libopus
|
||||||
|
|
|
@ -611,136 +611,6 @@ else
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
# Filteraudio
|
|
||||||
|
|
||||||
FILTERAUDIO_PREFIX_DIR="$DEP_DIR/libfilteraudio"
|
|
||||||
FILTERAUDIO_VERSION=ada2f4fdc04940cdeee47caffe43add4fa017096
|
|
||||||
FILTERAUDIO_HASH="cf481e87c860aaf28b50d125195d84556f36d0ebb529d7ebdac39f8cc497256a"
|
|
||||||
if [ ! -f "$FILTERAUDIO_PREFIX_DIR/done" ]
|
|
||||||
then
|
|
||||||
rm -rf "$FILTERAUDIO_PREFIX_DIR"
|
|
||||||
mkdir -p "$FILTERAUDIO_PREFIX_DIR"
|
|
||||||
|
|
||||||
git clone https://github.com/irungentoo/filter_audio filter_audio
|
|
||||||
cd filter*
|
|
||||||
git checkout $FILTERAUDIO_VERSION
|
|
||||||
check_sha256_git "$FILTERAUDIO_HASH"
|
|
||||||
|
|
||||||
$ARCH-w64-mingw32-gcc -O2 -g0 -c \
|
|
||||||
aec/aec_core.c \
|
|
||||||
aec/aec_core_sse2.c \
|
|
||||||
aec/aec_rdft.c \
|
|
||||||
aec/aec_rdft_sse2.c \
|
|
||||||
aec/aec_resampler.c \
|
|
||||||
aec/echo_cancellation.c \
|
|
||||||
agc/analog_agc.c \
|
|
||||||
agc/digital_agc.c \
|
|
||||||
ns/ns_core.c \
|
|
||||||
ns/nsx_core_c.c \
|
|
||||||
ns/nsx_core.c \
|
|
||||||
ns/noise_suppression_x.c \
|
|
||||||
ns/noise_suppression.c \
|
|
||||||
other/get_scaling_square.c \
|
|
||||||
other/resample_by_2.c \
|
|
||||||
other/spl_sqrt.c \
|
|
||||||
other/delay_estimator.c \
|
|
||||||
other/complex_bit_reverse.c \
|
|
||||||
other/dot_product_with_scale.c \
|
|
||||||
other/cross_correlation.c \
|
|
||||||
other/min_max_operations.c \
|
|
||||||
other/resample_48khz.c \
|
|
||||||
other/high_pass_filter.c \
|
|
||||||
other/energy.c \
|
|
||||||
other/randomization_functions.c \
|
|
||||||
other/speex_resampler.c \
|
|
||||||
other/copy_set_operations.c \
|
|
||||||
other/downsample_fast.c \
|
|
||||||
other/complex_fft.c \
|
|
||||||
other/vector_scaling_operations.c \
|
|
||||||
other/resample_by_2_internal.c \
|
|
||||||
other/delay_estimator_wrapper.c \
|
|
||||||
other/real_fft.c \
|
|
||||||
other/spl_sqrt_floor.c \
|
|
||||||
other/resample_fractional.c \
|
|
||||||
other/ring_buffer.c \
|
|
||||||
other/splitting_filter.c \
|
|
||||||
other/fft4g.c \
|
|
||||||
other/division_operations.c \
|
|
||||||
other/spl_init.c \
|
|
||||||
other/float_util.c \
|
|
||||||
zam/filters.c \
|
|
||||||
vad/vad_sp.c \
|
|
||||||
vad/vad_core.c \
|
|
||||||
vad/webrtc_vad.c \
|
|
||||||
vad/vad_gmm.c \
|
|
||||||
vad/vad_filterbank.c \
|
|
||||||
filter_audio.c \
|
|
||||||
-lpthread \
|
|
||||||
-lm
|
|
||||||
|
|
||||||
ar rcs libfilteraudio.a \
|
|
||||||
aec_core.o \
|
|
||||||
aec_core_sse2.o \
|
|
||||||
aec_rdft.o \
|
|
||||||
aec_rdft_sse2.o \
|
|
||||||
aec_resampler.o \
|
|
||||||
echo_cancellation.o \
|
|
||||||
analog_agc.o \
|
|
||||||
digital_agc.o \
|
|
||||||
ns_core.o \
|
|
||||||
nsx_core_c.o \
|
|
||||||
nsx_core.o \
|
|
||||||
noise_suppression_x.o \
|
|
||||||
noise_suppression.o \
|
|
||||||
get_scaling_square.o \
|
|
||||||
resample_by_2.o \
|
|
||||||
spl_sqrt.o \
|
|
||||||
delay_estimator.o \
|
|
||||||
complex_bit_reverse.o \
|
|
||||||
dot_product_with_scale.o \
|
|
||||||
cross_correlation.o \
|
|
||||||
min_max_operations.o \
|
|
||||||
resample_48khz.o \
|
|
||||||
high_pass_filter.o \
|
|
||||||
energy.o \
|
|
||||||
randomization_functions.o \
|
|
||||||
speex_resampler.o \
|
|
||||||
copy_set_operations.o \
|
|
||||||
downsample_fast.o \
|
|
||||||
complex_fft.o \
|
|
||||||
vector_scaling_operations.o \
|
|
||||||
resample_by_2_internal.o \
|
|
||||||
delay_estimator_wrapper.o \
|
|
||||||
real_fft.o \
|
|
||||||
spl_sqrt_floor.o \
|
|
||||||
resample_fractional.o \
|
|
||||||
ring_buffer.o \
|
|
||||||
splitting_filter.o \
|
|
||||||
fft4g.o \
|
|
||||||
division_operations.o \
|
|
||||||
spl_init.o \
|
|
||||||
float_util.o \
|
|
||||||
filters.o \
|
|
||||||
vad_sp.o \
|
|
||||||
vad_core.o \
|
|
||||||
webrtc_vad.o \
|
|
||||||
vad_gmm.o \
|
|
||||||
vad_filterbank.o \
|
|
||||||
filter_audio.o
|
|
||||||
|
|
||||||
mkdir $FILTERAUDIO_PREFIX_DIR/include
|
|
||||||
mkdir $FILTERAUDIO_PREFIX_DIR/lib
|
|
||||||
cp filter_audio.h $FILTERAUDIO_PREFIX_DIR/include
|
|
||||||
cp libfilteraudio.a $FILTERAUDIO_PREFIX_DIR/lib
|
|
||||||
echo -n $FILTERAUDIO_VERSION > $FILTERAUDIO_PREFIX_DIR/done
|
|
||||||
|
|
||||||
cd ..
|
|
||||||
rm -rf ./filter*
|
|
||||||
else
|
|
||||||
echo "Using cached build of Filteraudio `cat $FILTERAUDIO_PREFIX_DIR/done`"
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
# QREncode
|
# QREncode
|
||||||
|
|
||||||
QRENCODE_PREFIX_DIR="$DEP_DIR/libqrencode"
|
QRENCODE_PREFIX_DIR="$DEP_DIR/libqrencode"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user