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>
27QAudioEnginePrivate::QAudioEnginePrivate(
int sampleRate)
28 : m_sampleRate(sampleRate),
30 std::make_unique<vraudio::ResonanceAudio>(2, qToUnderlying(framesPerBuffer), sampleRate),
33 resonanceAudio->api->SetStereoSpeakerMode(outputMode() != QAudioEngine::Headphone);
34 resonanceAudio->api->SetMasterVolume(masterVolume());
41 if (scale == m_distanceScale)
43 m_distanceScale = scale;
45 emit q->distanceScaleChanged();
50 return m_distanceScale;
58 resonanceAudio->api->SetMasterVolume(volume);
60 emit q->masterVolumeChanged();
70 if (pos == m_position)
75 QVector3D posValue = pos.value_or(QVector3D{});
76 resonanceAudio->api->SetHeadPosition(posValue.x(), posValue.y(), posValue.z());
83 resonanceAudio->api->SetHeadRotation(rotation.x(), rotation.y(), rotation.z(),
89 if (resonanceAudio->roomEffectsEnabled == enabled)
91 resonanceAudio->roomEffectsEnabled = enabled;
96 return resonanceAudio->roomEffectsEnabled;
101 if (m_outputMode == mode)
104 resonanceAudio->api->SetStereoSpeakerMode(mode != QAudioEngine::Headphone);
107 emit q->outputModeChanged();
117 Q_ASSERT(!QtMultimediaPrivate::ranges::contains(rooms, room));
118 rooms.push_back(room);
123 Q_ASSERT(QtMultimediaPrivate::ranges::contains(rooms, room));
124 q20::erase(rooms, room);
129 return m_currentRoom;
137 bool roomDirty =
false;
138 for (
const auto &room : rooms) {
139 auto *rd = QAudioRoomPrivate::get(room);
146 auto inferredRoom = findSmallestRoomForListener(rooms);
147 if (inferredRoom.room != m_currentRoom)
149 const bool previousRoom = m_currentRoom;
150 m_currentRoom = inferredRoom.room;
156 if (!m_currentRoom) {
157 resonanceAudio->api->EnableRoomEffects(
false);
161 resonanceAudio->api->EnableRoomEffects(
true);
163 QAudioRoomPrivate *rp = QAudioRoomPrivate::get(m_currentRoom);
164 resonanceAudio->api->SetReflectionProperties(rp->reflections);
165 resonanceAudio->api->SetReverbProperties(rp->reverb);
174 const std::optional<QVector3D> listenerPos = listenerPosition();
182 std::optional<
float> roomVolume;
183 QAudioRoom *room =
nullptr;
185 for (QAudioRoom *r : std::as_const(rooms)) {
186 QVector3D dim2 = r->dimensions() / 2.;
187 float vol = dim2.x() * dim2.y() * dim2.z();
188 if (roomVolume && vol > roomVolume)
190 QVector3D dist = r->position() - *listenerPos;
192 dist = r->rotation().rotatedVector(dist);
193 if (qAbs(dist.x()) <= dim2.x() && qAbs(dist.y()) <= dim2.y()
194 && qAbs(dist.z()) <= dim2.z()) {
202 roomVolume.value_or(0.f),
210 bool hasCallbackApi = QPlatformMediaIntegration::instance()->audioDevices()->hasCallbackApi();
212 return new QAudioEngineWithPlayer(sampleRate);
214 return new QAudioEngineThreaded(sampleRate);
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
260
261
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279QAudioEngine::QAudioEngine(
int sampleRate, QObject *parent)
280 : QObject(*makeAudioEnginePrivate(sampleRate), parent)
285
286
287QAudioEngine::~QAudioEngine()
293
294
295
296
297
298
299
300
301
304
305
306
307
308
309
310void QAudioEngine::setOutputMode(OutputMode mode)
313 d->setOutputMode(mode);
316QAudioEngine::OutputMode QAudioEngine::outputMode()
const
318 Q_D(
const QAudioEngine);
319 return d->outputMode();
323
324
325int QAudioEngine::sampleRate()
const
327 Q_D(
const QAudioEngine);
328 return d->sampleRate();
332
333
334
335
336void QAudioEngine::setOutputDevice(
const QAudioDevice &device)
339 d->setOutputDevice(device);
342QAudioDevice QAudioEngine::outputDevice()
const
344 Q_D(
const QAudioEngine);
345 return d->outputDevice();
349
350
351
352
353void QAudioEngine::setMasterVolume(
float volume)
356 return d->setMasterVolume(volume);
359float QAudioEngine::masterVolume()
const
361 Q_D(
const QAudioEngine);
362 return d->masterVolume();
366
367
368void QAudioEngine::start()
375
376
377void QAudioEngine::stop()
384
385
386
387
388void QAudioEngine::setPaused(
bool paused)
391 d->setPaused(paused);
394bool QAudioEngine::paused()
const
396 Q_D(
const QAudioEngine);
397 return d->isPaused();
401
402
403
404
405
406
407
408void QAudioEngine::setRoomEffectsEnabled(
bool enabled)
411 d->setRoomEffectsEnabled(enabled);
415
416
417bool QAudioEngine::roomEffectsEnabled()
const
419 Q_D(
const QAudioEngine);
420 return d->roomEffectsEnabled();
424
425
426
427
428
429
430
431
432void QAudioEngine::setDistanceScale(
float scale)
438 qWarning() <<
"QAudioEngine: Invalid distance scale.";
441 d->setDistanceScale(scale);
444float QAudioEngine::distanceScale()
const
446 Q_D(
const QAudioEngine);
447 return d->distanceScale() * 100.f;
451
452
453
454
456
457
458
459
461
462
463
465
466
467
471#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)
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")