7#include <QtMultimedia/private/qmultimedia_ranges_p.h>
8#include <QtSpatialAudio/private/qaudioengine_threaded_p.h>
9#include <QtSpatialAudio/private/qaudioengine_withplayer_p.h>
10#include <QtSpatialAudio/private/qaudioroom_p.h>
11#include <QtCore/qspan.h>
13#include <QtMultimedia/qaudiosink.h>
14#include <QtMultimedia/qmediadevices.h>
15#include <QtMultimedia/private/qaudiosystem_p.h>
16#include <QtMultimedia/private/qplatformaudiodevices_p.h>
17#include <QtMultimedia/private/qplatformmediaintegration_p.h>
21#include <resonance_audio.h>
25QAudioEnginePrivate::QAudioEnginePrivate(
int sampleRate)
26 : m_sampleRate(sampleRate),
28 std::make_unique<vraudio::ResonanceAudio>(2, qToUnderlying(framesPerBuffer), sampleRate),
31 resonanceAudio->api->SetStereoSpeakerMode(outputMode() != QAudioEngine::Headphone);
32 resonanceAudio->api->SetMasterVolume(masterVolume());
39 if (scale == m_distanceScale)
41 m_distanceScale = scale;
43 emit q->distanceScaleChanged();
48 return m_distanceScale;
56 resonanceAudio->api->SetMasterVolume(volume);
58 emit q->masterVolumeChanged();
68 if (pos == m_position)
73 QVector3D posValue = pos.value_or(QVector3D{});
74 resonanceAudio->api->SetHeadPosition(posValue.x(), posValue.y(), posValue.z());
81 resonanceAudio->api->SetHeadRotation(rotation.x(), rotation.y(), rotation.z(),
87 if (resonanceAudio->roomEffectsEnabled == enabled)
89 resonanceAudio->roomEffectsEnabled = enabled;
94 return resonanceAudio->roomEffectsEnabled;
99 if (m_outputMode == mode)
102 resonanceAudio->api->SetStereoSpeakerMode(mode != QAudioEngine::Headphone);
105 emit q->outputModeChanged();
115 Q_ASSERT(!QtMultimediaPrivate::ranges::contains(rooms, room));
116 rooms.push_back(room);
121 Q_ASSERT(QtMultimediaPrivate::ranges::contains(rooms, room));
122 q20::erase(rooms, room);
127 return m_currentRoom;
135 bool roomDirty =
false;
136 for (
const auto &room : rooms) {
137 auto *rd = QAudioRoomPrivate::get(room);
144 auto inferredRoom = findSmallestRoomForListener(rooms);
145 if (inferredRoom.room != m_currentRoom)
147 const bool previousRoom = m_currentRoom;
148 m_currentRoom = inferredRoom.room;
154 if (!m_currentRoom) {
155 resonanceAudio->api->EnableRoomEffects(
false);
159 resonanceAudio->api->EnableRoomEffects(
true);
161 QAudioRoomPrivate *rp = QAudioRoomPrivate::get(m_currentRoom);
162 resonanceAudio->api->SetReflectionProperties(rp->reflections);
163 resonanceAudio->api->SetReverbProperties(rp->reverb);
172 const std::optional<QVector3D> listenerPos = listenerPosition();
180 std::optional<
float> roomVolume;
181 QAudioRoom *room =
nullptr;
183 for (QAudioRoom *r : std::as_const(rooms)) {
184 QVector3D dim2 = r->dimensions() / 2.;
185 float vol = dim2.x() * dim2.y() * dim2.z();
186 if (roomVolume && vol > roomVolume)
188 QVector3D dist = r->position() - *listenerPos;
190 dist = r->rotation().rotatedVector(dist);
191 if (qAbs(dist.x()) <= dim2.x() && qAbs(dist.y()) <= dim2.y()
192 && qAbs(dist.z()) <= dim2.z()) {
200 roomVolume.value_or(0.f),
208 bool hasCallbackApi = QPlatformMediaIntegration::instance()->audioDevices()->hasCallbackApi();
210 return new QAudioEngineWithPlayer(sampleRate);
212 return new QAudioEngineThreaded(sampleRate);
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277QAudioEngine::QAudioEngine(
int sampleRate, QObject *parent)
278 : QObject(*makeAudioEnginePrivate(sampleRate), parent)
283
284
285QAudioEngine::~QAudioEngine()
291
292
293
294
295
296
297
298
299
302
303
304
305
306
307
308void QAudioEngine::setOutputMode(OutputMode mode)
311 d->setOutputMode(mode);
314QAudioEngine::OutputMode QAudioEngine::outputMode()
const
316 Q_D(
const QAudioEngine);
317 return d->outputMode();
321
322
323int QAudioEngine::sampleRate()
const
325 Q_D(
const QAudioEngine);
326 return d->sampleRate();
330
331
332
333
334void QAudioEngine::setOutputDevice(
const QAudioDevice &device)
337 d->setOutputDevice(device);
340QAudioDevice QAudioEngine::outputDevice()
const
342 Q_D(
const QAudioEngine);
343 return d->outputDevice();
347
348
349
350
351void QAudioEngine::setMasterVolume(
float volume)
354 return d->setMasterVolume(volume);
357float QAudioEngine::masterVolume()
const
359 Q_D(
const QAudioEngine);
360 return d->masterVolume();
364
365
366void QAudioEngine::start()
373
374
375void QAudioEngine::stop()
382
383
384
385
386void QAudioEngine::setPaused(
bool paused)
389 d->setPaused(paused);
392bool QAudioEngine::paused()
const
394 Q_D(
const QAudioEngine);
395 return d->isPaused();
399
400
401
402
403
404
405
406void QAudioEngine::setRoomEffectsEnabled(
bool enabled)
409 d->setRoomEffectsEnabled(enabled);
413
414
415bool QAudioEngine::roomEffectsEnabled()
const
417 Q_D(
const QAudioEngine);
418 return d->roomEffectsEnabled();
422
423
424
425
426
427
428
429
430void QAudioEngine::setDistanceScale(
float scale)
436 qWarning() <<
"QAudioEngine: Invalid distance scale.";
439 d->setDistanceScale(scale);
442float QAudioEngine::distanceScale()
const
444 Q_D(
const QAudioEngine);
445 return d->distanceScale() * 100.f;
449
450
451
452
454
455
456
457
459
460
461
463
464
465
469#include "moc_qaudioengine.cpp"
void removeRoom(QAudioRoom *)
void setMasterVolume(float)
virtual void updateRoomEffects()=0
void addRoom(QAudioRoom *)
bool roomEffectsEnabled() const
float distanceScale() const
QAudioRoom * currentRoom() const
virtual void setOutputMode(QAudioEngine::OutputMode)
SmallestRoomForListenerResult findSmallestRoomForListener(QSpan< QAudioRoom * > rooms) const
void setListenerPosition(std::optional< QVector3D >)
float masterVolume() const
void setDistanceScale(float scale)
void setListenerRotation(const QQuaternion &)
~QAudioEnginePrivate() override
void setRoomEffectsEnabled(bool)