summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2022-05-30 15:21:32 +0200
committerLars Knoll <lars.knoll@qt.io>2022-05-31 11:31:41 +0200
commit0eede8f08dc06e3c46eb2ffddd765fbc37184187 (patch)
tree10430ce2f736e22c00f245d967695feb3e8a2e3f
parent5853819466e36396be4ea155a694549857609026 (diff)
Spatial Audio: Implement support for room reverb in surround mode
Resonance audio doesn't calculate any reverb when we ask for ambisonic output. The reason is that reverb is purely calculated using mono sources and a stereo output and is directly connected to the stereo mixer at the end of the pipeline. To fix this, gain access to private parts of resonance audio by compiling it with -Dprivate=public. That's ok, as we compile it purely as an internal library anyway. After that retrieve the audio data for the reverb component from the graph manager and add it at the end of the processing pipeline (after ambisonic decoding) to the different surround channels. Change-Id: Iaeeec8df7a963858b6ec0399948a55f89136964e Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
-rw-r--r--src/multimedia/spatial/qambientsound.cpp6
-rw-r--r--src/multimedia/spatial/qambisonicdecoder.cpp72
-rw-r--r--src/multimedia/spatial/qambisonicdecoder_p.h4
-rw-r--r--src/multimedia/spatial/qaudioengine.cpp48
-rw-r--r--src/multimedia/spatial/qaudioengine_p.h4
-rw-r--r--src/multimedia/spatial/qaudiolistener.cpp10
-rw-r--r--src/multimedia/spatial/qaudioroom_p.h2
-rw-r--r--src/multimedia/spatial/qspatialsound.cpp38
-rw-r--r--src/resonance-audio/CMakeLists.txt2
-rw-r--r--src/resonance-audio/resonance_audio.cpp (renamed from src/resonance-audio/resonance_audio_api_extensions.cpp)24
-rw-r--r--src/resonance-audio/resonance_audio.h (renamed from src/resonance-audio/resonance_audio_api_extensions.h)24
11 files changed, 168 insertions, 66 deletions
diff --git a/src/multimedia/spatial/qambientsound.cpp b/src/multimedia/spatial/qambientsound.cpp
index 410f699b2..7f9023d3a 100644
--- a/src/multimedia/spatial/qambientsound.cpp
+++ b/src/multimedia/spatial/qambientsound.cpp
@@ -36,7 +36,7 @@
****************************************************************************/
#include "qambientsound.h"
#include "qaudioengine_p.h"
-#include "api/resonance_audio_api.h"
+#include "resonance_audio.h"
#include <qaudiosink.h>
#include <qurl.h>
#include <qdebug.h>
@@ -86,7 +86,7 @@ void QAmbientSound::setVolume(float volume)
d->volume = volume;
auto *ep = QAudioEnginePrivate::get(d->engine);
if (ep)
- ep->api->SetSourceVolume(d->sourceId, d->volume);
+ ep->resonanceAudio->api->SetSourceVolume(d->sourceId, d->volume);
emit volumeChanged();
}
@@ -197,7 +197,7 @@ void QAmbientSound::setEngine(QAudioEngine *engine)
ep = QAudioEnginePrivate::get(engine);
if (ep) {
ep->addStereoSound(this);
- ep->api->SetSourceVolume(d->sourceId, d->volume);
+ ep->resonanceAudio->api->SetSourceVolume(d->sourceId, d->volume);
}
}
diff --git a/src/multimedia/spatial/qambisonicdecoder.cpp b/src/multimedia/spatial/qambisonicdecoder.cpp
index 6a4081194..922656538 100644
--- a/src/multimedia/spatial/qambisonicdecoder.cpp
+++ b/src/multimedia/spatial/qambisonicdecoder.cpp
@@ -61,25 +61,53 @@ struct QAmbisonicDecoderData
QAudioFormat::ChannelConfig config;
const float *lf[3];
const float *hf[3];
+ const float *reverb;
+};
+
+const float reverb_x_0[] =
+{
+ 1.f, 0.f, // L
+ 0.f, 1.f, // R
+ .7f, .7f, // C
+ 1.f, 0.f, // Ls
+ 0.f, 1.f, // Rs
+ 1.f, 0.f, // Lb
+ 0.f, 1.f, // Rb
+};
+
+const float reverb_x_1[] =
+{
+ 1.f, 0.f, // L
+ 0.f, 1.f, // R
+ .7f, .7f, // C
+ .0f, .0f, // LFE
+ 1.f, 0.f, // Ls
+ 0.f, 1.f, // Rs
+ 1.f, 0.f, // Lb
+ 0.f, 1.f, // Rb
};
static const QAmbisonicDecoderData decoderMap[] =
{
{ QAudioFormat::ChannelConfigSurround5Dot0,
{ decoderMatrix_5dot0_1_lf, decoderMatrix_5dot0_2_lf, decoderMatrix_5dot0_3_lf },
- { decoderMatrix_5dot0_1_hf, decoderMatrix_5dot0_2_hf, decoderMatrix_5dot0_3_hf }
+ { decoderMatrix_5dot0_1_hf, decoderMatrix_5dot0_2_hf, decoderMatrix_5dot0_3_hf },
+ reverb_x_0
},
{ QAudioFormat::ChannelConfigSurround5Dot1,
{ decoderMatrix_5dot1_1_lf, decoderMatrix_5dot1_2_lf, decoderMatrix_5dot1_3_lf },
- { decoderMatrix_5dot1_1_hf, decoderMatrix_5dot1_2_hf, decoderMatrix_5dot1_3_hf }
+ { decoderMatrix_5dot1_1_hf, decoderMatrix_5dot1_2_hf, decoderMatrix_5dot1_3_hf },
+ reverb_x_1
},
{ QAudioFormat::ChannelConfigSurround7Dot0,
{ decoderMatrix_7dot0_1_lf, decoderMatrix_7dot0_2_lf, decoderMatrix_7dot0_3_lf },
- { decoderMatrix_7dot0_1_hf, decoderMatrix_7dot0_2_hf, decoderMatrix_7dot0_3_hf }
+ { decoderMatrix_7dot0_1_hf, decoderMatrix_7dot0_2_hf, decoderMatrix_7dot0_3_hf },
+ reverb_x_0
},
{ QAudioFormat::ChannelConfigSurround7Dot1,
{ decoderMatrix_7dot1_1_lf, decoderMatrix_7dot1_2_lf, decoderMatrix_7dot1_3_lf },
- { decoderMatrix_7dot1_1_hf, decoderMatrix_7dot1_2_hf, decoderMatrix_7dot1_3_hf }
+ { decoderMatrix_7dot1_1_hf, decoderMatrix_7dot1_2_hf, decoderMatrix_7dot1_3_hf },
+ reverb_x_1
}
};
@@ -175,25 +203,37 @@ QAmbisonicDecoder::QAmbisonicDecoder(AmbisonicLevel ambisonicLevel, const QAudio
// Center gets 50% W and 50% Y
// LFE gets 50% W
simpleDecoderFactors = new float[4*outputChannels];
+ float *r = new float[2*outputChannels]; // reverb output is in stereo
float *f = simpleDecoderFactors;
+ reverbFactors = r;
if (channelConfig & QAudioFormat::channelConfig(QAudioFormat::FrontLeft)) {
f[0] = 0.5f; f[1] = 0.5f; f[2] = 0.; f[3] = 0.f;
f += 4;
+ r[0] = 1.; r[1] = 0.;
+ r += 2;
}
if (channelConfig & QAudioFormat::channelConfig(QAudioFormat::FrontRight)) {
f[0] = 0.5f; f[1] = -0.5f; f[2] = 0.; f[3] = 0.f;
f += 4;
+ r[0] = 0.; r[1] = 1.;
+ r += 2;
}
if (channelConfig & QAudioFormat::channelConfig(QAudioFormat::FrontCenter)) {
f[0] = 0.5f; f[1] = -0.f; f[2] = 0.; f[3] = 0.5f;
f += 4;
+ r[0] = .5; r[1] = .5;
+ r += 2;
}
if (channelConfig & QAudioFormat::channelConfig(QAudioFormat::LFE)) {
f[0] = 0.5f; f[1] = -0.f; f[2] = 0.; f[3] = 0.0f;
f += 4;
+ r[0] = 0.; r[1] = 0.;
+ r += 2;
}
Q_UNUSED(f);
+ Q_UNUSED(r);
Q_ASSERT((f - simpleDecoderFactors) == 4*outputChannels);
+ Q_ASSERT((r - reverbFactors) == 2*outputChannels);
return;
}
@@ -201,6 +241,7 @@ QAmbisonicDecoder::QAmbisonicDecoder(AmbisonicLevel ambisonicLevel, const QAudio
for (const auto &d : decoderMap) {
if (d.config == channelConfig) {
decoderData = &d;
+ reverbFactors = decoderData->reverb;
break;
}
}
@@ -217,7 +258,10 @@ QAmbisonicDecoder::QAmbisonicDecoder(AmbisonicLevel ambisonicLevel, const QAudio
QAmbisonicDecoder::~QAmbisonicDecoder()
{
- delete simpleDecoderFactors;
+ if (simpleDecoderFactors) {
+ delete simpleDecoderFactors;
+ delete reverbFactors;
+ }
}
void QAmbisonicDecoder::processBuffer(const float *input[], float *output, int nSamples)
@@ -252,6 +296,12 @@ void QAmbisonicDecoder::processBuffer(const float *input[], float *output, int n
void QAmbisonicDecoder::processBuffer(const float *input[], short *output, int nSamples)
{
+ const float *reverb[] = { nullptr, nullptr };
+ return processBufferWithReverb(input, reverb, output, nSamples);
+}
+
+void QAmbisonicDecoder::processBufferWithReverb(const float *input[], const float *reverb[], short *output, int nSamples)
+{
if (simpleDecoderFactors) {
for (int i = 0; i < nSamples; ++i) {
float o[4] = {};
@@ -259,6 +309,12 @@ void QAmbisonicDecoder::processBuffer(const float *input[], short *output, int n
for (int j = 0; j < 4; ++j)
o[k] += simpleDecoderFactors[k*4 + j]*input[j][i];
}
+ if (reverb[0]) {
+ for (int k = 0; k < outputChannels; ++k) {
+ o[k] += reverb[0][i]*reverbFactors[2*k] + reverb[1][i]*reverbFactors[2*k+1];
+ }
+ }
+
for (int k = 0; k < outputChannels; ++k)
output[k] = static_cast<short>(o[k]*32768.);
output += outputChannels;
@@ -278,10 +334,16 @@ void QAmbisonicDecoder::processBuffer(const float *input[], short *output, int n
for (int k = 0; k < outputChannels; ++k)
o[k] += matrix_lo[k*inputChannels + j]*buf[j].lf + matrix_hi[k*inputChannels + j]*buf[j].hf;
}
+ if (reverb[0]) {
+ for (int k = 0; k < outputChannels; ++k) {
+ o[k] += reverb[0][i]*reverbFactors[2*k] + reverb[1][i]*reverbFactors[2*k+1];
+ }
+ }
for (int k = 0; k < outputChannels; ++k)
output[k] = static_cast<short>(o[k]*32768.);
output += outputChannels;
}
+
}
QT_END_NAMESPACE
diff --git a/src/multimedia/spatial/qambisonicdecoder_p.h b/src/multimedia/spatial/qambisonicdecoder_p.h
index e52419f2d..a94fdd444 100644
--- a/src/multimedia/spatial/qambisonicdecoder_p.h
+++ b/src/multimedia/spatial/qambisonicdecoder_p.h
@@ -84,6 +84,8 @@ public:
void processBuffer(const float *input[], float *output, int nSamples);
void processBuffer(const float *input[], short *output, int nSamples);
+ void processBufferWithReverb(const float *input[], const float *reverb[2], short *output, int nSamples);
+
static constexpr int maxAmbisonicChannels = 16;
static constexpr int maxAmbisonicLevel = 3;
private:
@@ -94,7 +96,7 @@ private:
const QAmbisonicDecoderData *decoderData = nullptr;
QAmbisonicDecoderFilter *filters = nullptr;
float *simpleDecoderFactors = nullptr;
-
+ const float *reverbFactors = nullptr;
};
diff --git a/src/multimedia/spatial/qaudioengine.cpp b/src/multimedia/spatial/qaudioengine.cpp
index 7c8c3a994..b405be0c8 100644
--- a/src/multimedia/spatial/qaudioengine.cpp
+++ b/src/multimedia/spatial/qaudioengine.cpp
@@ -39,7 +39,7 @@
#include <qambientsound.h>
#include <qaudioroom_p.h>
#include <qaudiolistener.h>
-#include <resonance_audio_api_extensions.h>
+#include <resonance_audio.h>
#include <qambisonicdecoder_p.h>
#include <qaudiodecoder.h>
#include <qmediadevices.h>
@@ -152,22 +152,23 @@ qint64 QAudioOutputStream::readData(char *data, qint64 len)
auto *sp = QSpatialSoundPrivate::get(source);
float buf[QAudioEnginePrivate::bufferSize];
sp->getBuffer(buf, QAudioEnginePrivate::bufferSize, 1);
- d->api->SetInterleavedBuffer(sp->sourceId, buf, 1, QAudioEnginePrivate::bufferSize);
+ d->resonanceAudio->api->SetInterleavedBuffer(sp->sourceId, buf, 1, QAudioEnginePrivate::bufferSize);
}
for (auto *source : qAsConst(d->stereoSources)) {
auto *sp = QAmbientSoundPrivate::get(source);
float buf[2*QAudioEnginePrivate::bufferSize];
sp->getBuffer(buf, QAudioEnginePrivate::bufferSize, 2);
- d->api->SetInterleavedBuffer(sp->sourceId, buf, 2, QAudioEnginePrivate::bufferSize);
+ d->resonanceAudio->api->SetInterleavedBuffer(sp->sourceId, buf, 2, QAudioEnginePrivate::bufferSize);
}
if (d->ambisonicDecoder && d->outputMode == QAudioEngine::Surround) {
const float *channels[QAmbisonicDecoder::maxAmbisonicChannels];
- int nSamples = vraudio::getAmbisonicOutput(d->api, channels, d->ambisonicDecoder->nInputChannels());
+ const float *reverbBuffers[2];
+ int nSamples = d->resonanceAudio->getAmbisonicOutput(channels, reverbBuffers, d->ambisonicDecoder->nInputChannels());
Q_ASSERT(d->ambisonicDecoder->nOutputChannels() <= 8);
- d->ambisonicDecoder->processBuffer(channels, fd, nSamples);
+ d->ambisonicDecoder->processBufferWithReverb(channels, reverbBuffers, fd, nSamples);
} else {
- ok = d->api->FillInterleavedOutputBuffer(2, QAudioEnginePrivate::bufferSize, fd);
+ ok = d->resonanceAudio->api->FillInterleavedOutputBuffer(2, QAudioEnginePrivate::bufferSize, fd);
if (!ok) {
qWarning() << " Reading failed!";
break;
@@ -190,14 +191,14 @@ QAudioEnginePrivate::QAudioEnginePrivate()
QAudioEnginePrivate::~QAudioEnginePrivate()
{
- delete api;
+ delete resonanceAudio;
}
void QAudioEnginePrivate::addSpatialSound(QSpatialSound *sound)
{
QAmbientSoundPrivate *sd = QAmbientSoundPrivate::get(sound);
- sd->sourceId = api->CreateSoundObjectSource(vraudio::kBinauralHighQuality);
+ sd->sourceId = resonanceAudio->api->CreateSoundObjectSource(vraudio::kBinauralHighQuality);
sources.append(sound);
}
@@ -205,7 +206,7 @@ void QAudioEnginePrivate::removeSpatialSound(QSpatialSound *sound)
{
QAmbientSoundPrivate *sd = QAmbientSoundPrivate::get(sound);
- api->DestroySource(sd->sourceId);
+ resonanceAudio->api->DestroySource(sd->sourceId);
sd->sourceId = vraudio::ResonanceAudioApi::kInvalidSourceId;
sources.removeOne(sound);
}
@@ -214,7 +215,7 @@ void QAudioEnginePrivate::addStereoSound(QAmbientSound *sound)
{
QAmbientSoundPrivate *sd = QAmbientSoundPrivate::get(sound);
- sd->sourceId = api->CreateStereoSource(2);
+ sd->sourceId = resonanceAudio->api->CreateStereoSource(2);
stereoSources.append(sound);
}
@@ -222,7 +223,7 @@ void QAudioEnginePrivate::removeStereoSound(QAmbientSound *sound)
{
QAmbientSoundPrivate *sd = QAmbientSoundPrivate::get(sound);
- api->DestroySource(sd->sourceId);
+ resonanceAudio->api->DestroySource(sd->sourceId);
sd->sourceId = vraudio::ResonanceAudioApi::kInvalidSourceId;
stereoSources.removeOne(sound);
}
@@ -286,12 +287,12 @@ void QAudioEnginePrivate::updateRooms()
// apply room to engine
if (!currentRoom) {
- api->EnableRoomEffects(false);
+ resonanceAudio->api->EnableRoomEffects(false);
return;
}
QAudioRoomPrivate *rp = QAudioRoomPrivate::get(room);
- api->SetReflectionProperties(rp->reflections);
- api->SetReverbProperties(rp->reverb);
+ resonanceAudio->api->SetReflectionProperties(rp->reflections);
+ resonanceAudio->api->SetReverbProperties(rp->reverb);
// update room effects for all sound sources
for (auto *s : qAsConst(sources)) {
@@ -363,7 +364,7 @@ QAudioEngine::QAudioEngine(QObject *parent, int sampleRate)
, d(new QAudioEnginePrivate)
{
d->sampleRate = sampleRate;
- d->api = vraudio::CreateResonanceAudioApi(2, QAudioEnginePrivate::bufferSize, d->sampleRate);
+ d->resonanceAudio = new vraudio::ResonanceAudio(2, QAudioEnginePrivate::bufferSize, d->sampleRate);
}
/*!
@@ -397,8 +398,8 @@ void QAudioEngine::setOutputMode(OutputMode mode)
if (d->outputMode == mode)
return;
d->outputMode = mode;
- if (d->api)
- d->api->SetStereoSpeakerMode(mode != Headphone);
+ if (d->resonanceAudio->api)
+ d->resonanceAudio->api->SetStereoSpeakerMode(mode != Headphone);
QMetaObject::invokeMethod(d->outputStream.get(), "restartOutput", Qt::BlockingQueuedConnection);
@@ -427,7 +428,7 @@ void QAudioEngine::setOutputDevice(const QAudioDevice &device)
{
if (d->device == device)
return;
- if (d->api) {
+ if (d->resonanceAudio->api) {
qWarning() << "Changing device on a running engine not implemented";
return;
}
@@ -450,7 +451,7 @@ void QAudioEngine::setMasterVolume(float volume)
if (d->masterVolume == volume)
return;
d->masterVolume = volume;
- d->api->SetMasterVolume(volume);
+ d->resonanceAudio->api->SetMasterVolume(volume);
emit masterVolumeChanged();
}
@@ -468,8 +469,8 @@ void QAudioEngine::start()
// already started
return;
- d->api->SetStereoSpeakerMode(d->outputMode != Headphone);
- d->api->SetMasterVolume(d->masterVolume);
+ d->resonanceAudio->api->SetStereoSpeakerMode(d->outputMode != Headphone);
+ d->resonanceAudio->api->SetMasterVolume(d->masterVolume);
d->outputStream.reset(new QAudioOutputStream(d));
d->outputStream->moveToThread(&d->audioThread);
@@ -487,8 +488,8 @@ void QAudioEngine::stop()
d->outputStream.reset();
d->audioThread.exit(0);
d->audioThread.wait();
- delete d->api;
- d->api = nullptr;
+ delete d->resonanceAudio->api;
+ d->resonanceAudio->api = nullptr;
}
/*!
@@ -524,6 +525,7 @@ void QAudioEngine::setRoomEffectsEnabled(bool enabled)
if (d->roomEffectsEnabled == enabled)
return;
d->roomEffectsEnabled = enabled;
+ d->resonanceAudio->roomEffectsEnabled = enabled;
}
/*!
diff --git a/src/multimedia/spatial/qaudioengine_p.h b/src/multimedia/spatial/qaudioengine_p.h
index 27fa50e9c..dce6f5171 100644
--- a/src/multimedia/spatial/qaudioengine_p.h
+++ b/src/multimedia/spatial/qaudioengine_p.h
@@ -59,7 +59,7 @@
#include <qvector3d.h>
namespace vraudio {
-class ResonanceAudioApi;
+class ResonanceAudio;
}
QT_BEGIN_NAMESPACE
@@ -82,7 +82,7 @@ public:
QAudioEnginePrivate();
~QAudioEnginePrivate();
- vraudio::ResonanceAudioApi *api = nullptr;
+ vraudio::ResonanceAudio *resonanceAudio = nullptr;
int sampleRate = 44100;
float masterVolume = 1.;
QAudioEngine::OutputMode outputMode = QAudioEngine::Surround;
diff --git a/src/multimedia/spatial/qaudiolistener.cpp b/src/multimedia/spatial/qaudiolistener.cpp
index e968b6b11..eb1f4a79c 100644
--- a/src/multimedia/spatial/qaudiolistener.cpp
+++ b/src/multimedia/spatial/qaudiolistener.cpp
@@ -36,7 +36,7 @@
****************************************************************************/
#include "qaudiolistener.h"
#include "qaudioengine_p.h"
-#include "api/resonance_audio_api.h"
+#include "resonance_audio.h"
#include <qaudiosink.h>
#include <qurl.h>
#include <qdebug.h>
@@ -95,8 +95,8 @@ void QAudioListener::setPosition(QVector3D pos)
return;
d->pos = pos;
- if (ep && ep->api) {
- ep->api->SetHeadPosition(pos.x(), pos.y(), pos.z());
+ if (ep && ep->resonanceAudio->api) {
+ ep->resonanceAudio->api->SetHeadPosition(pos.x(), pos.y(), pos.z());
ep->listenerPositionDirty = true;
}
}
@@ -117,8 +117,8 @@ void QAudioListener::setRotation(const QQuaternion &q)
{
d->rotation = q;
auto *ep = QAudioEnginePrivate::get(d->engine);
- if (ep && ep->api)
- ep->api->SetHeadRotation(d->rotation.x(), d->rotation.y(), d->rotation.z(), d->rotation.scalar());
+ if (ep && ep->resonanceAudio->api)
+ ep->resonanceAudio->api->SetHeadRotation(d->rotation.x(), d->rotation.y(), d->rotation.z(), d->rotation.scalar());
}
/*!
diff --git a/src/multimedia/spatial/qaudioroom_p.h b/src/multimedia/spatial/qaudioroom_p.h
index b2cc7c2e3..ae5f46efb 100644
--- a/src/multimedia/spatial/qaudioroom_p.h
+++ b/src/multimedia/spatial/qaudioroom_p.h
@@ -51,7 +51,7 @@
#include <qaudioengine_p.h>
#include <QtGui/qquaternion.h>
-#include <resonance_audio_api_extensions.h>
+#include <resonance_audio.h>
#include "platforms/common/room_effects_utils.h"
#include "platforms/common/room_properties.h"
diff --git a/src/multimedia/spatial/qspatialsound.cpp b/src/multimedia/spatial/qspatialsound.cpp
index 8614eaa3b..cb002a8a1 100644
--- a/src/multimedia/spatial/qspatialsound.cpp
+++ b/src/multimedia/spatial/qspatialsound.cpp
@@ -38,7 +38,7 @@
#include "qspatialsound_p.h"
#include "qaudiolistener.h"
#include "qaudioengine_p.h"
-#include "api/resonance_audio_api.h"
+#include "resonance_audio.h"
#include <qaudiosink.h>
#include <qurl.h>
#include <qdebug.h>
@@ -93,7 +93,7 @@ void QSpatialSound::setPosition(QVector3D pos)
pos *= ep->distanceScale;
d->pos = pos;
if (ep)
- ep->api->SetSourcePosition(d->sourceId, pos.x(), pos.y(), pos.z());
+ ep->resonanceAudio->api->SetSourcePosition(d->sourceId, pos.x(), pos.y(), pos.z());
d->updateRoomEffects();
emit positionChanged();
}
@@ -114,7 +114,7 @@ void QSpatialSound::setRotation(const QQuaternion &q)
d->rotation = q;
auto *ep = QAudioEnginePrivate::get(d->engine);
if (ep)
- ep->api->SetSourceRotation(d->sourceId, q.x(), q.y(), q.z(), q.scalar());
+ ep->resonanceAudio->api->SetSourceRotation(d->sourceId, q.x(), q.y(), q.z(), q.scalar());
emit rotationChanged();
}
@@ -138,7 +138,7 @@ void QSpatialSound::setVolume(float volume)
d->volume = volume;
auto *ep = QAudioEnginePrivate::get(d->engine);
if (ep)
- ep->api->SetSourceVolume(d->sourceId, d->volume*d->wallDampening);
+ ep->resonanceAudio->api->SetSourceVolume(d->sourceId, d->volume*d->wallDampening);
emit volumeChanged();
}
@@ -195,7 +195,7 @@ void QSpatialSoundPrivate::updateDistanceModel()
break;
}
- ep->api->SetSourceDistanceModel(sourceId, dm, size, distanceCutoff);
+ ep->resonanceAudio->api->SetSourceDistanceModel(sourceId, dm, size, distanceCutoff);
}
void QSpatialSoundPrivate::updateRoomEffects()
@@ -217,7 +217,7 @@ void QSpatialSoundPrivate::updateRoomEffects()
qAbs(dist.y()) <= roomDim2.y() &&
qAbs(dist.z()) <= roomDim2.z()) {
// Source is inside room, apply
- ep->api->SetSourceRoomEffectsGain(sourceId, 1);
+ ep->resonanceAudio->api->SetSourceRoomEffectsGain(sourceId, 1);
wallDampening = 1.;
wallOcclusion = 0.;
} else {
@@ -296,10 +296,10 @@ void QSpatialSoundPrivate::updateRoomEffects()
}
// qDebug() << "intersection with wall" << walls[0] << walls[1] << walls[2] << factors[0] << factors[1] << factors[2] << wallDampening << wallOcclusion;
- ep->api->SetSourceRoomEffectsGain(sourceId, 0);
+ ep->resonanceAudio->api->SetSourceRoomEffectsGain(sourceId, 0);
}
- ep->api->SetSoundObjectOcclusionIntensity(sourceId, occlusionIntensity + wallOcclusion);
- ep->api->SetSourceVolume(sourceId, volume*wallDampening);
+ ep->resonanceAudio->api->SetSoundObjectOcclusionIntensity(sourceId, occlusionIntensity + wallOcclusion);
+ ep->resonanceAudio->api->SetSourceVolume(sourceId, volume*wallDampening);
}
QSpatialSound::DistanceModel QSpatialSound::distanceModel() const
@@ -370,7 +370,7 @@ void QSpatialSound::setManualAttenuation(float attenuation)
d->manualAttenuation = attenuation;
auto *ep = QAudioEnginePrivate::get(d->engine);
if (ep)
- ep->api->SetSourceDistanceAttenuation(d->sourceId, d->manualAttenuation);
+ ep->resonanceAudio->api->SetSourceDistanceAttenuation(d->sourceId, d->manualAttenuation);
emit manualAttenuationChanged();
}
@@ -402,7 +402,7 @@ void QSpatialSound::setOcclusionIntensity(float occlusion)
d->occlusionIntensity = occlusion;
auto *ep = QAudioEnginePrivate::get(d->engine);
if (ep)
- ep->api->SetSoundObjectOcclusionIntensity(d->sourceId, d->occlusionIntensity + d->wallOcclusion);
+ ep->resonanceAudio->api->SetSoundObjectOcclusionIntensity(d->sourceId, d->occlusionIntensity + d->wallOcclusion);
emit occlusionIntensityChanged();
}
@@ -429,7 +429,7 @@ void QSpatialSound::setDirectivity(float alpha)
auto *ep = QAudioEnginePrivate::get(d->engine);
if (ep)
- ep->api->SetSoundObjectDirectivity(d->sourceId, d->directivity, d->directivityOrder);
+ ep->resonanceAudio->api->SetSoundObjectDirectivity(d->sourceId, d->directivity, d->directivityOrder);
emit directivityChanged();
}
@@ -456,7 +456,7 @@ void QSpatialSound::setDirectivityOrder(float order)
auto *ep = QAudioEnginePrivate::get(d->engine);
if (ep)
- ep->api->SetSoundObjectDirectivity(d->sourceId, d->directivity, d->directivityOrder);
+ ep->resonanceAudio->api->SetSoundObjectDirectivity(d->sourceId, d->directivity, d->directivityOrder);
emit directivityChanged();
}
@@ -482,7 +482,7 @@ void QSpatialSound::setNearFieldGain(float gain)
auto *ep = QAudioEnginePrivate::get(d->engine);
if (ep)
- ep->api->SetSoundObjectNearFieldEffectGain(d->sourceId, d->nearFieldGain/9.);
+ ep->resonanceAudio->api->SetSoundObjectNearFieldEffectGain(d->sourceId, d->nearFieldGain/9.);
emit nearFieldGainChanged();
@@ -594,11 +594,11 @@ void QSpatialSound::setEngine(QAudioEngine *engine)
ep = QAudioEnginePrivate::get(engine);
if (ep) {
ep->addSpatialSound(this);
- ep->api->SetSourcePosition(d->sourceId, d->pos.x(), d->pos.y(), d->pos.z());
- ep->api->SetSourceRotation(d->sourceId, d->rotation.x(), d->rotation.y(), d->rotation.z(), d->rotation.scalar());
- ep->api->SetSourceVolume(d->sourceId, d->volume);
- ep->api->SetSoundObjectDirectivity(d->sourceId, d->directivity, d->directivityOrder);
- ep->api->SetSoundObjectNearFieldEffectGain(d->sourceId, d->nearFieldGain);
+ ep->resonanceAudio->api->SetSourcePosition(d->sourceId, d->pos.x(), d->pos.y(), d->pos.z());
+ ep->resonanceAudio->api->SetSourceRotation(d->sourceId, d->rotation.x(), d->rotation.y(), d->rotation.z(), d->rotation.scalar());
+ ep->resonanceAudio->api->SetSourceVolume(d->sourceId, d->volume);
+ ep->resonanceAudio->api->SetSoundObjectDirectivity(d->sourceId, d->directivity, d->directivityOrder);
+ ep->resonanceAudio->api->SetSoundObjectNearFieldEffectGain(d->sourceId, d->nearFieldGain);
d->updateDistanceModel();
}
}
diff --git a/src/resonance-audio/CMakeLists.txt b/src/resonance-audio/CMakeLists.txt
index 3f959464c..1d26cfd9e 100644
--- a/src/resonance-audio/CMakeLists.txt
+++ b/src/resonance-audio/CMakeLists.txt
@@ -198,7 +198,7 @@ qt_internal_add_3rdparty_library(BundledResonanceAudio
${RA_SOURCES}
${PFFFT_SOURCE}
${SADIE_HRTFS_SOURCE}
- resonance_audio_api_extensions.h resonance_audio_api_extensions.cpp
+ resonance_audio.h resonance_audio.cpp
INCLUDE_DIRECTORIES
${RA_TOPLEVEL_DIR}
${RA_SOURCE_DIR}
diff --git a/src/resonance-audio/resonance_audio_api_extensions.cpp b/src/resonance-audio/resonance_audio.cpp
index 2f5beb07d..a61725833 100644
--- a/src/resonance-audio/resonance_audio_api_extensions.cpp
+++ b/src/resonance-audio/resonance_audio.cpp
@@ -34,16 +34,26 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#include "resonance_audio_api_extensions.h"
+#include "resonance_audio.h"
#include "graph/resonance_audio_api_impl.h"
+#include "graph/graph_manager.h"
namespace vraudio
{
-int getAmbisonicOutput(ResonanceAudioApi *api, const float *buffers[], int nChannels)
+ResonanceAudio::ResonanceAudio(size_t num_channels, size_t frames_per_buffer, int sample_rate_hz)
{
- ResonanceAudioApiImpl *impl = static_cast<ResonanceAudioApiImpl *>(api);
+ api = CreateResonanceAudioApi(num_channels, frames_per_buffer, sample_rate_hz);
+ impl = static_cast<ResonanceAudioApiImpl *>(api);
+}
+
+ResonanceAudio::~ResonanceAudio()
+{
+ delete api;
+}
+int ResonanceAudio::getAmbisonicOutput(const float *buffers[], const float *reverb[], int nChannels)
+{
impl->ProcessNextBuffer();
auto *buffer = impl->GetAmbisonicOutputBuffer();
if (nChannels != buffer->num_channels())
@@ -52,6 +62,14 @@ int getAmbisonicOutput(ResonanceAudioApi *api, const float *buffers[], int nChan
for (int i = 0; i < nChannels; ++i) {
buffers[i] = buffer->begin()[i].begin();
}
+
+ if (roomEffectsEnabled) {
+ const vraudio::AudioBuffer *reverbBuffer = impl->GetReverbBuffer();
+ for (int i = 0; i < 2; ++i) {
+ reverb[i] = reverbBuffer->begin()[i].begin();
+ }
+ }
+
return buffer->num_frames();
}
diff --git a/src/resonance-audio/resonance_audio_api_extensions.h b/src/resonance-audio/resonance_audio.h
index 7e186c655..35dbd86ee 100644
--- a/src/resonance-audio/resonance_audio_api_extensions.h
+++ b/src/resonance-audio/resonance_audio.h
@@ -34,15 +34,33 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#ifndef RESONANCE_AUDIO_API_EXTENSIONS_H
-#define RESONANCE_AUDIO_API_EXTENSIONS_H
+#ifndef RESONANCE_AUDIO_H
+#define RESONANCE_AUDIO_H
#include <api/resonance_audio_api.h>
namespace vraudio
{
-EXPORT_API int getAmbisonicOutput(ResonanceAudioApi *api, const float *buffers[], int nChannels);
+class ResonanceAudioExtensions;
+class ResonanceAudioApiImpl;
+
+class EXPORT_API ResonanceAudio
+{
+public:
+ ResonanceAudio(size_t num_channels, size_t frames_per_buffer, int sample_rate_hz);
+ ~ResonanceAudio();
+
+ // reverb is only calculated in stereo. We get it here as well, and our ambisonic
+ // decoder will then add it to the generated surround signal.
+ int getAmbisonicOutput(const float *buffers[], const float *reverb[], int nChannels);
+
+ ResonanceAudioApi *api = nullptr;
+ ResonanceAudioApiImpl *impl = nullptr;
+ bool roomEffectsEnabled = true;
+};
+
+
}