mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
privatized audio interface
This commit is contained in:
parent
c23cb0043f
commit
bb7d2a72b7
@ -38,6 +38,36 @@
|
|||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
#if defined(__APPLE__) && defined(__MACH__)
|
||||||
|
#include <OpenAL/al.h>
|
||||||
|
#include <OpenAL/alc.h>
|
||||||
|
#else
|
||||||
|
#include <AL/al.h>
|
||||||
|
#include <AL/alc.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class AudioPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AudioPrivate()
|
||||||
|
: alInDev(nullptr)
|
||||||
|
, alOutDev(nullptr)
|
||||||
|
, alContext(nullptr)
|
||||||
|
, inputVolume(1.f)
|
||||||
|
, outputVolume(1.f)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
ALCdevice* alInDev;
|
||||||
|
ALCdevice* alOutDev;
|
||||||
|
ALCcontext* alContext;
|
||||||
|
|
||||||
|
ALuint alMainSource;
|
||||||
|
qreal inputVolume;
|
||||||
|
qreal outputVolume;
|
||||||
|
};
|
||||||
|
|
||||||
Audio* Audio::instance{nullptr};
|
Audio* Audio::instance{nullptr};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -54,15 +84,10 @@ Audio& Audio::getInstance()
|
|||||||
}
|
}
|
||||||
|
|
||||||
Audio::Audio()
|
Audio::Audio()
|
||||||
: audioThread(new QThread())
|
: d(new AudioPrivate)
|
||||||
, alOutDev(nullptr)
|
, audioThread(new QThread())
|
||||||
, alInDev(nullptr)
|
|
||||||
, mInputInitialized(false)
|
, mInputInitialized(false)
|
||||||
, mOutputInitialized(false)
|
, mOutputInitialized(false)
|
||||||
, outputVolume(1.0)
|
|
||||||
, inputVolume(1.0)
|
|
||||||
, alMainSource(0)
|
|
||||||
, alContext(nullptr)
|
|
||||||
{
|
{
|
||||||
audioThread->setObjectName("qTox Audio");
|
audioThread->setObjectName("qTox Audio");
|
||||||
connect(audioThread, &QThread::finished, audioThread, &QThread::deleteLater);
|
connect(audioThread, &QThread::finished, audioThread, &QThread::deleteLater);
|
||||||
@ -94,10 +119,10 @@ void Audio::startAudioThread()
|
|||||||
/**
|
/**
|
||||||
Returns the current output volume, between 0 and 1
|
Returns the current output volume, between 0 and 1
|
||||||
*/
|
*/
|
||||||
qreal Audio::getOutputVolume()
|
qreal Audio::outputVolume()
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&mAudioLock);
|
QMutexLocker locker(&mAudioLock);
|
||||||
return outputVolume;
|
return d->outputVolume;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -107,27 +132,31 @@ void Audio::setOutputVolume(qreal volume)
|
|||||||
{
|
{
|
||||||
QMutexLocker locker(&mAudioLock);
|
QMutexLocker locker(&mAudioLock);
|
||||||
|
|
||||||
outputVolume = volume;
|
d->outputVolume = volume;
|
||||||
alSourcef(alMainSource, AL_GAIN, outputVolume);
|
alSourcef(d->alMainSource, AL_GAIN, volume);
|
||||||
|
|
||||||
for (const ToxGroupCall& call : CoreAV::groupCalls)
|
for (const ToxGroupCall& call : CoreAV::groupCalls)
|
||||||
{
|
{
|
||||||
alSourcef(call.alSource, AL_GAIN, outputVolume);
|
alSourcef(call.alSource, AL_GAIN, volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const ToxFriendCall& call : CoreAV::calls)
|
for (const ToxFriendCall& call : CoreAV::calls)
|
||||||
{
|
{
|
||||||
alSourcef(call.alSource, AL_GAIN, outputVolume);
|
alSourcef(call.alSource, AL_GAIN, volume);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
qreal Audio::inputVolume()
|
||||||
The volume must be between 0 and 2
|
{
|
||||||
*/
|
QMutexLocker locker(&mAudioLock);
|
||||||
|
|
||||||
|
return d->inputVolume;
|
||||||
|
}
|
||||||
|
|
||||||
void Audio::setInputVolume(qreal volume)
|
void Audio::setInputVolume(qreal volume)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&mAudioLock);
|
QMutexLocker locker(&mAudioLock);
|
||||||
inputVolume = volume;
|
d->inputVolume = volume;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -139,7 +168,7 @@ void Audio::subscribeInput(const void* inListener)
|
|||||||
{
|
{
|
||||||
QMutexLocker locker(&mAudioLock);
|
QMutexLocker locker(&mAudioLock);
|
||||||
|
|
||||||
if (!alInDev)
|
if (!d->alInDev)
|
||||||
initInput(Settings::getInstance().getInDev());
|
initInput(Settings::getInstance().getInDev());
|
||||||
|
|
||||||
if (!inputSubscriptions.contains(inListener)) {
|
if (!inputSubscriptions.contains(inListener)) {
|
||||||
@ -171,7 +200,7 @@ void Audio::subscribeOutput(const void* outListener)
|
|||||||
{
|
{
|
||||||
QMutexLocker locker(&mAudioLock);
|
QMutexLocker locker(&mAudioLock);
|
||||||
|
|
||||||
if (!alOutDev)
|
if (!d->alOutDev)
|
||||||
initOutput(Settings::getInstance().getOutDev());
|
initOutput(Settings::getInstance().getOutDev());
|
||||||
|
|
||||||
if (!outputSubscriptions.contains(outListener)) {
|
if (!outputSubscriptions.contains(outListener)) {
|
||||||
@ -202,7 +231,7 @@ void Audio::initInput(const QString& inDevDescr)
|
|||||||
if (inDevDescr == "none")
|
if (inDevDescr == "none")
|
||||||
return;
|
return;
|
||||||
|
|
||||||
assert(!alInDev);
|
assert(!d->alInDev);
|
||||||
|
|
||||||
/// TODO: Try to actually detect if our audio source is stereo
|
/// TODO: Try to actually detect if our audio source is stereo
|
||||||
int stereoFlag = AUDIO_CHANNELS == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
|
int stereoFlag = AUDIO_CHANNELS == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
|
||||||
@ -230,10 +259,10 @@ void Audio::initInput(const QString& inDevDescr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
alInDev = alcCaptureOpenDevice(inDevDescr.toStdString().c_str(),
|
d->alInDev = alcCaptureOpenDevice(inDevDescr.toStdString().c_str(),
|
||||||
sampleRate, stereoFlag, bufSize);
|
sampleRate, stereoFlag, bufSize);
|
||||||
|
|
||||||
if (alInDev)
|
if (d->alInDev)
|
||||||
qDebug() << "Opened audio input" << inDevDescr;
|
qDebug() << "Opened audio input" << inDevDescr;
|
||||||
else
|
else
|
||||||
qWarning() << "Cannot open input audio device" << inDevDescr;
|
qWarning() << "Cannot open input audio device" << inDevDescr;
|
||||||
@ -243,9 +272,9 @@ void Audio::initInput(const QString& inDevDescr)
|
|||||||
core->getAv()->resetCallSources(); // Force to regen each group call's sources
|
core->getAv()->resetCallSources(); // Force to regen each group call's sources
|
||||||
|
|
||||||
// Restart the capture if necessary
|
// Restart the capture if necessary
|
||||||
if (alInDev)
|
if (d->alInDev)
|
||||||
{
|
{
|
||||||
alcCaptureStart(alInDev);
|
alcCaptureStart(d->alInDev);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -270,7 +299,7 @@ bool Audio::initOutput(const QString& outDevDescr)
|
|||||||
if (outDevDescr == "none")
|
if (outDevDescr == "none")
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
assert(!alOutDev);
|
assert(!d->alOutDev);
|
||||||
|
|
||||||
if (outDevDescr.isEmpty())
|
if (outDevDescr.isEmpty())
|
||||||
{
|
{
|
||||||
@ -297,14 +326,15 @@ bool Audio::initOutput(const QString& outDevDescr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
alOutDev = alcOpenDevice(outDevDescr.toStdString().c_str());
|
d->alOutDev = alcOpenDevice(outDevDescr.toStdString().c_str());
|
||||||
|
|
||||||
if (alOutDev)
|
if (d->alOutDev)
|
||||||
{
|
{
|
||||||
alContext = alcCreateContext(alOutDev, nullptr);
|
d->alContext = alcCreateContext(d->alOutDev, nullptr);
|
||||||
if (alcMakeContextCurrent(alContext))
|
if (alcMakeContextCurrent(d->alContext))
|
||||||
{
|
{
|
||||||
alGenSources(1, &alMainSource);
|
alGenSources(1, &d->alMainSource);
|
||||||
|
alSourcef(d->alMainSource, AL_GAIN, d->outputVolume);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -332,26 +362,28 @@ void Audio::playMono16Sound(const QByteArray& data)
|
|||||||
{
|
{
|
||||||
QMutexLocker locker(&mAudioLock);
|
QMutexLocker locker(&mAudioLock);
|
||||||
|
|
||||||
if (!alOutDev)
|
if (!d->alOutDev)
|
||||||
initOutput(Settings::getInstance().getOutDev());
|
initOutput(Settings::getInstance().getOutDev());
|
||||||
|
|
||||||
|
alSourcei(d->alMainSource, AL_LOOPING, false);
|
||||||
|
alSourcef(d->alMainSource, AL_GAIN, d->outputVolume);
|
||||||
|
alSource3f(d->alMainSource, AL_POSITION, 0, 0, 0);
|
||||||
|
alSource3f(d->alMainSource, AL_VELOCITY, 0, 0, 0);
|
||||||
|
|
||||||
ALuint buffer;
|
ALuint buffer;
|
||||||
alGenBuffers(1, &buffer);
|
alGenBuffers(1, &buffer);
|
||||||
alBufferData(buffer, AL_FORMAT_MONO16, data.data(), data.size(), 44100);
|
alBufferData(buffer, AL_FORMAT_MONO16, data.constData(), data.size(), 44100);
|
||||||
alSourcef(alMainSource, AL_GAIN, outputVolume);
|
|
||||||
alSourcei(alMainSource, AL_BUFFER, buffer);
|
|
||||||
alSourcePlay(alMainSource);
|
|
||||||
|
|
||||||
ALint sizeInBytes;
|
alSourcei(d->alMainSource, AL_BUFFER, buffer);
|
||||||
ALint channels;
|
|
||||||
ALint bits;
|
|
||||||
|
|
||||||
alGetBufferi(buffer, AL_SIZE, &sizeInBytes);
|
alSourceRewind(d->alMainSource);
|
||||||
alGetBufferi(buffer, AL_CHANNELS, &channels);
|
alSourcePlay(d->alMainSource);
|
||||||
alGetBufferi(buffer, AL_BITS, &bits);
|
|
||||||
|
|
||||||
ALint frequency;
|
ALint state;
|
||||||
alGetBufferi(buffer, AL_FREQUENCY, &frequency);
|
alGetSourcei(d->alMainSource, AL_SOURCE_STATE, &state);
|
||||||
|
while (state == AL_PLAYING) {
|
||||||
|
alGetSourcei(d->alMainSource, AL_SOURCE_STATE, &state);
|
||||||
|
}
|
||||||
|
|
||||||
alDeleteBuffers(1, &buffer);
|
alDeleteBuffers(1, &buffer);
|
||||||
|
|
||||||
@ -403,7 +435,7 @@ void Audio::playGroupAudio(int group, int peer, const int16_t* data,
|
|||||||
if (!call.alSource)
|
if (!call.alSource)
|
||||||
{
|
{
|
||||||
alGenSources(1, &call.alSource);
|
alGenSources(1, &call.alSource);
|
||||||
alSourcef(call.alSource, AL_GAIN, outputVolume);
|
alSourcef(call.alSource, AL_GAIN, d->outputVolume);
|
||||||
}
|
}
|
||||||
|
|
||||||
qreal volume = 0.;
|
qreal volume = 0.;
|
||||||
@ -416,11 +448,10 @@ void Audio::playGroupAudio(int group, int peer, const int16_t* data,
|
|||||||
playAudioBuffer(call.alSource, data, samples, channels, sample_rate);
|
playAudioBuffer(call.alSource, data, samples, channels, sample_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Audio::playAudioBuffer(ALuint alSource, const int16_t *data, int samples, unsigned channels, int sampleRate)
|
void Audio::playAudioBuffer(quint32 alSource, const int16_t *data, int samples, unsigned channels, int sampleRate)
|
||||||
{
|
{
|
||||||
assert(channels == 1 || channels == 2);
|
assert(channels == 1 || channels == 2);
|
||||||
|
QMutexLocker locker(&mAudioLock);
|
||||||
QMutexLocker locker(&getInstance().mAudioLock);
|
|
||||||
|
|
||||||
ALuint bufid;
|
ALuint bufid;
|
||||||
ALint processed = 0, queued = 16;
|
ALint processed = 0, queued = 16;
|
||||||
@ -450,7 +481,7 @@ void Audio::playAudioBuffer(ALuint alSource, const int16_t *data, int samples, u
|
|||||||
|
|
||||||
ALint state;
|
ALint state;
|
||||||
alGetSourcei(alSource, AL_SOURCE_STATE, &state);
|
alGetSourcei(alSource, AL_SOURCE_STATE, &state);
|
||||||
alSourcef(alSource, AL_GAIN, getInstance().outputVolume);
|
alSourcef(alSource, AL_GAIN, d->outputVolume);
|
||||||
if (state != AL_PLAYING)
|
if (state != AL_PLAYING)
|
||||||
alSourcePlay(alSource);
|
alSourcePlay(alSource);
|
||||||
}
|
}
|
||||||
@ -464,16 +495,16 @@ void Audio::cleanupInput()
|
|||||||
{
|
{
|
||||||
mInputInitialized = false;
|
mInputInitialized = false;
|
||||||
|
|
||||||
if (alInDev)
|
if (d->alInDev)
|
||||||
{
|
{
|
||||||
#if (!FIX_SND_PCM_PREPARE_BUG)
|
#if (!FIX_SND_PCM_PREPARE_BUG)
|
||||||
qDebug() << "stopping audio capture";
|
qDebug() << "stopping audio capture";
|
||||||
alcCaptureStop(alInDev);
|
alcCaptureStop(d->alInDev);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
qDebug() << "Closing audio input";
|
qDebug() << "Closing audio input";
|
||||||
if (alcCaptureCloseDevice(alInDev) == ALC_TRUE)
|
if (alcCaptureCloseDevice(d->alInDev) == ALC_TRUE)
|
||||||
alInDev = nullptr;
|
d->alInDev = nullptr;
|
||||||
else
|
else
|
||||||
qWarning() << "Failed to close input";
|
qWarning() << "Failed to close input";
|
||||||
}
|
}
|
||||||
@ -488,20 +519,20 @@ void Audio::cleanupOutput()
|
|||||||
{
|
{
|
||||||
mOutputInitialized = false;
|
mOutputInitialized = false;
|
||||||
|
|
||||||
if (alOutDev) {
|
if (d->alOutDev) {
|
||||||
qDebug() << "Closing audio output";
|
qDebug() << "Closing audio output";
|
||||||
alSourcei(alMainSource, AL_LOOPING, AL_FALSE);
|
alSourcei(d->alMainSource, AL_LOOPING, AL_FALSE);
|
||||||
alSourceStop(alMainSource);
|
alSourceStop(d->alMainSource);
|
||||||
alDeleteSources(1, &alMainSource);
|
alDeleteSources(1, &d->alMainSource);
|
||||||
|
|
||||||
if (!alcMakeContextCurrent(nullptr))
|
if (!alcMakeContextCurrent(nullptr))
|
||||||
qWarning("Failed to clear current audio context.");
|
qWarning("Failed to clear current audio context.");
|
||||||
|
|
||||||
alcDestroyContext(alContext);
|
alcDestroyContext(d->alContext);
|
||||||
alContext = nullptr;
|
d->alContext = nullptr;
|
||||||
|
|
||||||
if (alcCloseDevice(alOutDev))
|
if (alcCloseDevice(d->alOutDev))
|
||||||
alOutDev = nullptr;
|
d->alOutDev = nullptr;
|
||||||
else
|
else
|
||||||
qWarning("Failed to close output.");
|
qWarning("Failed to close output.");
|
||||||
}
|
}
|
||||||
@ -513,7 +544,7 @@ Returns true if the input device is open and suscribed to
|
|||||||
bool Audio::isInputReady()
|
bool Audio::isInputReady()
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&mAudioLock);
|
QMutexLocker locker(&mAudioLock);
|
||||||
return alInDev && mInputInitialized;
|
return d->alInDev && mInputInitialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -522,32 +553,49 @@ Returns true if the output device is open
|
|||||||
bool Audio::isOutputReady()
|
bool Audio::isOutputReady()
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&mAudioLock);
|
QMutexLocker locker(&mAudioLock);
|
||||||
return alOutDev && mOutputInitialized;
|
return d->alOutDev && mOutputInitialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Audio::createSource(ALuint* source)
|
const char* Audio::outDeviceNames()
|
||||||
{
|
{
|
||||||
alGenSources(1, source);
|
const char* pDeviceList;
|
||||||
alSourcef(*source, AL_GAIN, getInstance().outputVolume);
|
if (alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") != AL_FALSE)
|
||||||
}
|
pDeviceList = alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER);
|
||||||
|
|
||||||
void Audio::deleteSource(ALuint* source)
|
|
||||||
{
|
|
||||||
if (alIsSource(*source))
|
|
||||||
alDeleteSources(1, source);
|
|
||||||
else
|
else
|
||||||
qWarning() << "Trying to delete invalid audio source"<<*source;
|
pDeviceList = alcGetString(NULL, ALC_DEVICE_SPECIFIER);
|
||||||
|
|
||||||
|
return pDeviceList;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* Audio::inDeviceNames()
|
||||||
|
{
|
||||||
|
return alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Audio::createSource(quint32* sid)
|
||||||
|
{
|
||||||
|
alGenSources(1, sid);
|
||||||
|
alSourcef(*sid, AL_GAIN, 1.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Audio::deleteSource(quint32 sid)
|
||||||
|
{
|
||||||
|
if (alIsSource(sid)) {
|
||||||
|
alDeleteSources(1, &sid);
|
||||||
|
} else {
|
||||||
|
qWarning() << "Trying to delete invalid audio source" << sid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Audio::startLoop()
|
void Audio::startLoop()
|
||||||
{
|
{
|
||||||
alSourcei(alMainSource, AL_LOOPING, AL_TRUE);
|
alSourcei(d->alMainSource, AL_LOOPING, AL_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Audio::stopLoop()
|
void Audio::stopLoop()
|
||||||
{
|
{
|
||||||
alSourcei(alMainSource, AL_LOOPING, AL_FALSE);
|
alSourcei(d->alMainSource, AL_LOOPING, AL_FALSE);
|
||||||
alSourceStop(alMainSource);
|
alSourceStop(d->alMainSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -557,19 +605,19 @@ bool Audio::tryCaptureSamples(int16_t* buf, int samples)
|
|||||||
{
|
{
|
||||||
QMutexLocker lock(&mAudioLock);
|
QMutexLocker lock(&mAudioLock);
|
||||||
|
|
||||||
if (!(alInDev && mInputInitialized))
|
if (!(d->alInDev && mInputInitialized))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ALint curSamples=0;
|
ALint curSamples=0;
|
||||||
alcGetIntegerv(alInDev, ALC_CAPTURE_SAMPLES, sizeof(curSamples), &curSamples);
|
alcGetIntegerv(d->alInDev, ALC_CAPTURE_SAMPLES, sizeof(curSamples), &curSamples);
|
||||||
if (curSamples < samples)
|
if (curSamples < samples)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
alcCaptureSamples(alInDev, buf, samples);
|
alcCaptureSamples(d->alInDev, buf, samples);
|
||||||
|
|
||||||
for (size_t i = 0; i < samples * AUDIO_CHANNELS; ++i)
|
for (size_t i = 0; i < samples * AUDIO_CHANNELS; ++i)
|
||||||
{
|
{
|
||||||
int sample = buf[i] * pow(inputVolume, 2);
|
int sample = buf[i] * pow(d->inputVolume, 2);
|
||||||
|
|
||||||
if (sample < std::numeric_limits<int16_t>::min())
|
if (sample < std::numeric_limits<int16_t>::min())
|
||||||
sample = std::numeric_limits<int16_t>::min();
|
sample = std::numeric_limits<int16_t>::min();
|
||||||
|
@ -26,17 +26,9 @@
|
|||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#if defined(__APPLE__) && defined(__MACH__)
|
|
||||||
#include <OpenAL/al.h>
|
|
||||||
#include <OpenAL/alc.h>
|
|
||||||
#else
|
|
||||||
#include <AL/al.h>
|
|
||||||
#include <AL/alc.h>
|
|
||||||
#include <AL/alext.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct Tox;
|
struct Tox;
|
||||||
class AudioFilterer;
|
class AudioFilterer;
|
||||||
|
class AudioPrivate;
|
||||||
|
|
||||||
// Public default audio settings
|
// Public default audio settings
|
||||||
static constexpr uint32_t AUDIO_SAMPLE_RATE = 48000; ///< The next best Opus would take is 24k
|
static constexpr uint32_t AUDIO_SAMPLE_RATE = 48000; ///< The next best Opus would take is 24k
|
||||||
@ -56,9 +48,10 @@ public:
|
|||||||
public:
|
public:
|
||||||
void startAudioThread();
|
void startAudioThread();
|
||||||
|
|
||||||
qreal getOutputVolume();
|
qreal outputVolume();
|
||||||
void setOutputVolume(qreal volume);
|
void setOutputVolume(qreal volume);
|
||||||
|
|
||||||
|
qreal inputVolume();
|
||||||
void setInputVolume(qreal volume);
|
void setInputVolume(qreal volume);
|
||||||
|
|
||||||
inline void reinitInput(const QString& inDevDesc)
|
inline void reinitInput(const QString& inDevDesc)
|
||||||
@ -77,8 +70,10 @@ public:
|
|||||||
bool isInputReady();
|
bool isInputReady();
|
||||||
bool isOutputReady();
|
bool isOutputReady();
|
||||||
|
|
||||||
static void createSource(ALuint* source);
|
static const char* outDeviceNames();
|
||||||
static void deleteSource(ALuint* source);
|
static const char* inDeviceNames();
|
||||||
|
void createSource(quint32* sid);
|
||||||
|
void deleteSource(quint32 sid);
|
||||||
|
|
||||||
void startLoop();
|
void startLoop();
|
||||||
void stopLoop();
|
void stopLoop();
|
||||||
@ -86,7 +81,8 @@ public:
|
|||||||
void playMono16Sound(const char* path);
|
void playMono16Sound(const char* path);
|
||||||
bool tryCaptureSamples(int16_t *buf, int samples);
|
bool tryCaptureSamples(int16_t *buf, int samples);
|
||||||
|
|
||||||
static void playAudioBuffer(ALuint alSource, const int16_t *data, int samples, unsigned channels, int sampleRate);
|
void playAudioBuffer(quint32 alSource, const int16_t *data, int samples,
|
||||||
|
unsigned channels, int sampleRate);
|
||||||
|
|
||||||
static void playGroupAudioQueued(void *, int group, int peer, const int16_t* data,
|
static void playGroupAudioQueued(void *, int group, int peer, const int16_t* data,
|
||||||
unsigned samples, uint8_t channels, unsigned sample_rate, void*);
|
unsigned samples, uint8_t channels, unsigned sample_rate, void*);
|
||||||
@ -124,14 +120,8 @@ private:
|
|||||||
QMutex mAudioLock;
|
QMutex mAudioLock;
|
||||||
PtrList inputSubscriptions;
|
PtrList inputSubscriptions;
|
||||||
PtrList outputSubscriptions;
|
PtrList outputSubscriptions;
|
||||||
ALCdevice* alOutDev;
|
|
||||||
ALCdevice* alInDev;
|
|
||||||
bool mInputInitialized;
|
bool mInputInitialized;
|
||||||
bool mOutputInitialized;
|
bool mOutputInitialized;
|
||||||
qreal outputVolume;
|
|
||||||
qreal inputVolume;
|
|
||||||
ALuint alMainSource;
|
|
||||||
ALCcontext* alContext;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // AUDIO_H
|
#endif // AUDIO_H
|
||||||
|
@ -474,8 +474,8 @@ void CoreAV::resetCallSources()
|
|||||||
{
|
{
|
||||||
if (call.alSource)
|
if (call.alSource)
|
||||||
{
|
{
|
||||||
Audio::deleteSource(&call.alSource);
|
Audio::getInstance().deleteSource(call.alSource);
|
||||||
Audio::createSource(&call.alSource);
|
Audio::getInstance().createSource(&call.alSource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -483,8 +483,8 @@ void CoreAV::resetCallSources()
|
|||||||
{
|
{
|
||||||
if (call.alSource)
|
if (call.alSource)
|
||||||
{
|
{
|
||||||
Audio::deleteSource(&call.alSource);
|
Audio::getInstance().deleteSource(call.alSource);
|
||||||
Audio::createSource(&call.alSource);
|
Audio::getInstance().createSource(&call.alSource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -645,9 +645,9 @@ void CoreAV::audioFrameCallback(ToxAV *, uint32_t friendNum, const int16_t *pcm,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (!call.alSource)
|
if (!call.alSource)
|
||||||
alGenSources(1, &call.alSource);
|
Audio::getInstance().createSource(&call.alSource);
|
||||||
|
|
||||||
Audio::playAudioBuffer(call.alSource, pcm, sampleCount, channels, samplingRate);
|
Audio::getInstance().playAudioBuffer(call.alSource, pcm, sampleCount, channels, samplingRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreAV::videoFrameCallback(ToxAV *, uint32_t friendNum, uint16_t w, uint16_t h,
|
void CoreAV::videoFrameCallback(ToxAV *, uint32_t friendNum, uint16_t w, uint16_t h,
|
||||||
|
@ -24,17 +24,8 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <tox/toxav.h>
|
|
||||||
|
|
||||||
#if defined(__APPLE__) && defined(__MACH__)
|
|
||||||
#include <OpenAL/al.h>
|
|
||||||
#include <OpenAL/alc.h>
|
|
||||||
#else
|
|
||||||
#include <AL/al.h>
|
|
||||||
#include <AL/alc.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "src/core/toxcall.h"
|
#include "src/core/toxcall.h"
|
||||||
|
#include <tox/toxav.h>
|
||||||
|
|
||||||
#ifdef QTOX_FILTER_AUDIO
|
#ifdef QTOX_FILTER_AUDIO
|
||||||
class AudioFilterer;
|
class AudioFilterer;
|
||||||
|
@ -54,6 +54,9 @@ ToxCall::ToxCall(ToxCall&& other) noexcept
|
|||||||
|
|
||||||
ToxCall::~ToxCall()
|
ToxCall::~ToxCall()
|
||||||
{
|
{
|
||||||
|
if (alSource)
|
||||||
|
Audio::getInstance().deleteSource(alSource);
|
||||||
|
|
||||||
if (sendAudioTimer)
|
if (sendAudioTimer)
|
||||||
{
|
{
|
||||||
QObject::disconnect(sendAudioTimer, nullptr, nullptr, nullptr);
|
QObject::disconnect(sendAudioTimer, nullptr, nullptr, nullptr);
|
||||||
@ -63,9 +66,6 @@ ToxCall::~ToxCall()
|
|||||||
audio.unsubscribeOutput(this);
|
audio.unsubscribeOutput(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (alSource)
|
|
||||||
Audio::deleteSource(&alSource);
|
|
||||||
|
|
||||||
#ifdef QTOX_FILTER_AUDIO
|
#ifdef QTOX_FILTER_AUDIO
|
||||||
if (filterer)
|
if (filterer)
|
||||||
delete filterer;
|
delete filterer;
|
||||||
|
@ -2,16 +2,9 @@
|
|||||||
#define TOXCALL_H
|
#define TOXCALL_H
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include "src/audio/audio.h"
|
||||||
#include "src/core/indexedlist.h"
|
#include "src/core/indexedlist.h"
|
||||||
|
|
||||||
#if defined(__APPLE__) && defined(__MACH__)
|
|
||||||
#include <OpenAL/al.h>
|
|
||||||
#include <OpenAL/alc.h>
|
|
||||||
#else
|
|
||||||
#include <AL/al.h>
|
|
||||||
#include <AL/alc.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <tox/toxav.h>
|
#include <tox/toxav.h>
|
||||||
|
|
||||||
class QTimer;
|
class QTimer;
|
||||||
@ -41,7 +34,7 @@ public:
|
|||||||
bool inactive; ///< True while we're not participating. (stopped group call, ringing but hasn't started yet, ...)
|
bool inactive; ///< True while we're not participating. (stopped group call, ringing but hasn't started yet, ...)
|
||||||
bool muteMic;
|
bool muteMic;
|
||||||
bool muteVol;
|
bool muteVol;
|
||||||
ALuint alSource;
|
quint32 alSource;
|
||||||
|
|
||||||
#ifdef QTOX_FILTER_AUDIO
|
#ifdef QTOX_FILTER_AUDIO
|
||||||
AudioFilterer* filterer;
|
AudioFilterer* filterer;
|
||||||
|
@ -19,8 +19,8 @@
|
|||||||
|
|
||||||
#include "avform.h"
|
#include "avform.h"
|
||||||
#include "ui_avsettings.h"
|
#include "ui_avsettings.h"
|
||||||
#include "src/persistence/settings.h"
|
|
||||||
#include "src/audio/audio.h"
|
#include "src/audio/audio.h"
|
||||||
|
#include "src/persistence/settings.h"
|
||||||
#include "src/video/camerasource.h"
|
#include "src/video/camerasource.h"
|
||||||
#include "src/video/cameradevice.h"
|
#include "src/video/cameradevice.h"
|
||||||
#include "src/video/videosurface.h"
|
#include "src/video/videosurface.h"
|
||||||
@ -28,14 +28,6 @@
|
|||||||
#include "src/core/core.h"
|
#include "src/core/core.h"
|
||||||
#include "src/core/coreav.h"
|
#include "src/core/coreav.h"
|
||||||
|
|
||||||
#if defined(__APPLE__) && defined(__MACH__)
|
|
||||||
#include <OpenAL/al.h>
|
|
||||||
#include <OpenAL/alc.h>
|
|
||||||
#else
|
|
||||||
#include <AL/alc.h>
|
|
||||||
#include <AL/al.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#ifndef ALC_ALL_DEVICES_SPECIFIER
|
#ifndef ALC_ALL_DEVICES_SPECIFIER
|
||||||
@ -274,7 +266,7 @@ void AVForm::getAudioInDevices()
|
|||||||
bodyUI->inDevCombobox->blockSignals(true);
|
bodyUI->inDevCombobox->blockSignals(true);
|
||||||
bodyUI->inDevCombobox->clear();
|
bodyUI->inDevCombobox->clear();
|
||||||
bodyUI->inDevCombobox->addItem(tr("None"));
|
bodyUI->inDevCombobox->addItem(tr("None"));
|
||||||
const ALchar *pDeviceList = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
|
const char* pDeviceList = Audio::inDeviceNames();
|
||||||
if (pDeviceList)
|
if (pDeviceList)
|
||||||
{
|
{
|
||||||
//prevent currentIndexChanged to be fired while adding items
|
//prevent currentIndexChanged to be fired while adding items
|
||||||
@ -305,11 +297,7 @@ void AVForm::getAudioOutDevices()
|
|||||||
bodyUI->outDevCombobox->blockSignals(true);
|
bodyUI->outDevCombobox->blockSignals(true);
|
||||||
bodyUI->outDevCombobox->clear();
|
bodyUI->outDevCombobox->clear();
|
||||||
bodyUI->outDevCombobox->addItem(tr("None"));
|
bodyUI->outDevCombobox->addItem(tr("None"));
|
||||||
const ALchar *pDeviceList;
|
const char* pDeviceList = Audio::outDeviceNames();
|
||||||
if (alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") != AL_FALSE)
|
|
||||||
pDeviceList = alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER);
|
|
||||||
else
|
|
||||||
pDeviceList = alcGetString(NULL, ALC_DEVICE_SPECIFIER);
|
|
||||||
if (pDeviceList)
|
if (pDeviceList)
|
||||||
{
|
{
|
||||||
//prevent currentIndexChanged to be fired while adding items
|
//prevent currentIndexChanged to be fired while adding items
|
||||||
|
Loading…
x
Reference in New Issue
Block a user