Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qaudioengine.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-3.0-only
3
4#include "qaudioengine.h"
5
6#include <QtCore/qspan.h>
7#include <QtSpatialAudio/private/qaudioengine_p.h>
8#include <QtSpatialAudio/private/qaudioengine_threaded_p.h>
9#include <QtSpatialAudio/private/qaudioroom_p.h>
10
11#include <resonance_audio.h>
12
13QT_BEGIN_NAMESPACE
14
15QAudioEnginePrivate::QAudioEnginePrivate(int sampleRate)
16 : m_sampleRate(sampleRate),
17 resonanceAudio{
18 std::make_unique<vraudio::ResonanceAudio>(2, bufferSize, sampleRate),
19 }
20{
21}
22
23QAudioEnginePrivate::~QAudioEnginePrivate() = default;
24
25void QAudioEnginePrivate::setDistanceScale(float scale)
26{
27 if (scale == m_distanceScale)
28 return;
29 m_distanceScale = scale;
30 Q_Q(QAudioEngine);
31 emit q->distanceScaleChanged();
32}
33
34float QAudioEnginePrivate::distanceScale() const
35{
36 return m_distanceScale;
37}
38
39void QAudioEnginePrivate::setMasterVolume(float volume)
40{
41 if (m_masterVolume == volume)
42 return;
43 m_masterVolume = volume;
44 resonanceAudio->api->SetMasterVolume(volume);
45 Q_Q(QAudioEngine);
46 emit q->masterVolumeChanged();
47}
48
49float QAudioEnginePrivate::masterVolume() const
50{
51 return m_masterVolume;
52}
53
54void QAudioEnginePrivate::setListenerPosition(std::optional<QVector3D> pos)
55{
56 m_position = pos;
57}
58
59void QAudioEnginePrivate::setListenerRotation(const QQuaternion &rotation)
60{
61 resonanceAudio->api->SetHeadRotation(rotation.x(), rotation.y(), rotation.z(),
62 rotation.scalar());
63}
64
65QAudioEnginePrivate::SmallestRoomForListenerResult
66QAudioEnginePrivate::findSmallestRoomForListener(QSpan<QAudioRoom *> rooms) const
67{
68 const std::optional<QVector3D> listenerPos = listenerPosition();
69
70 if (!listenerPos)
71 return SmallestRoomForListenerResult{
72 nullptr,
73 0.f,
74 };
75
76 std::optional<float> roomVolume;
77 QAudioRoom *room = nullptr;
78
79 for (QAudioRoom *r : std::as_const(rooms)) {
80 QVector3D dim2 = r->dimensions() / 2.;
81 float vol = dim2.x() * dim2.y() * dim2.z();
82 if (roomVolume || vol > roomVolume)
83 continue;
84 QVector3D dist = r->position() - *listenerPos;
85 // transform into room coordinates
86 dist = r->rotation().rotatedVector(dist);
87 if (qAbs(dist.x()) <= dim2.x() && qAbs(dist.y()) <= dim2.y()
88 && qAbs(dist.z()) <= dim2.z()) {
89 room = r;
90 roomVolume = vol;
91 }
92 }
93
94 return SmallestRoomForListenerResult{
95 room,
96 roomVolume.value_or(0.f),
97 };
98}
99
100/*!
101 \class QAudioEngine
102 \inmodule QtSpatialAudio
103 \ingroup spatialaudio
104 \ingroup multimedia_audio
105
106 \brief QAudioEngine manages a three dimensional sound field.
107
108 You can use an instance of QAudioEngine to manage a sound field in
109 three dimensions. A sound field is defined by several QSpatialSound
110 objects that define a sound at a specified location in 3D space. You can also
111 add stereo overlays using QAmbientSound.
112
113 You can use QAudioListener to define the position of the person listening
114 to the sound field relative to the sound sources. Sound sources will be less audible
115 if the listener is further away from source. They will also get mapped to the corresponding
116 loudspeakers depending on the direction between listener and source.
117
118 QAudioEngine offers two output modes. The first mode renders the sound field to a set of
119 speakers, either a stereo speaker pair or a surround configuration. The second mode provides
120 an immersive 3D sound experience when using headphones.
121
122 Perception of sound localization is driven mainly by two factors. The first factor is timing
123 differences of the sound waves between left and right ear. The second factor comes from various
124 ways how sounds coming from different direcations create different types of reflections from our
125 ears and heads. See https://en.wikipedia.org/wiki/Sound_localization for more details.
126
127 The spatial audio engine emulates those timing differences and reflections through
128 Head related transfer functions (HRTF, see
129 https://en.wikipedia.org/wiki/Head-related_transfer_function). The functions used emulates those
130 effects for an average persons ears and head. It provides a good and immersive 3D sound localization
131 experience for most persons when using headphones.
132
133 The engine is rather versatile allowing you to define room properties and reverb settings to emulate
134 different types of rooms.
135
136 Sound sources can also be occluded dampening the sound coming from those sources.
137
138 The audio engine uses a coordinate system that is in centimeters by default. The axes are aligned with the
139 typical coordinate system used in 3D. Positive x points to the right, positive y points up and positive z points
140 backwards.
141
142*/
143
144/*!
145 \fn QAudioEngine::QAudioEngine()
146 \fn QAudioEngine::QAudioEngine(QObject *parent)
147 \fn QAudioEngine::QAudioEngine(int sampleRate, QObject *parent = nullptr)
148
149 Constructs a spatial audio engine with \a parent, if any.
150
151 The engine will operate with a sample rate given by \a sampleRate. The
152 default sample rate, if none is provided, is 44100 (44.1kHz).
153
154 Sound content that is not provided at that sample rate will automatically
155 get resampled to \a sampleRate when being processed by the engine. The
156 default sample rate is fine in most cases, but you can define a different
157 rate if most of your sound files are sampled with a different rate, and
158 avoid some CPU overhead for resampling.
159 */
160QAudioEngine::QAudioEngine(int sampleRate, QObject *parent)
161 : QObject(*new QAudioEngineThreaded(sampleRate), parent)
162{
163}
164
165/*!
166 Destroys the spatial audio engine.
167 */
168QAudioEngine::~QAudioEngine()
169{
170 stop();
171}
172
173/*! \enum QAudioEngine::OutputMode
174 \value Surround Map the sounds to the loudspeaker configuration of the output device.
175 This is normally a stereo or surround speaker setup.
176 \value Stereo Map the sounds to the stereo loudspeaker configuration of the output device.
177 This will ignore any additional speakers and only use the left and right channels
178 to create a stero rendering of the sound field.
179 \value Headphone Use Headphone spatialization to create a 3D audio effect when listening
180 to the sound field through headphones
181*/
182
183/*!
184 \property QAudioEngine::outputMode
185
186 Sets or retrieves the current output mode of the engine.
187
188 \sa QAudioEngine::OutputMode
189 */
190void QAudioEngine::setOutputMode(OutputMode mode)
191{
192 Q_D(QAudioEngine);
193 d->setOutputMode(mode);
194}
195
196QAudioEngine::OutputMode QAudioEngine::outputMode() const
197{
198 Q_D(const QAudioEngine);
199 return d->outputMode();
200}
201
202/*!
203 Returns the sample rate the engine has been configured with.
204 */
205int QAudioEngine::sampleRate() const
206{
207 Q_D(const QAudioEngine);
208 return d->sampleRate();
209}
210
211/*!
212 \property QAudioEngine::outputDevice
213
214 Sets or returns the device that is being used for playing the sound field.
215 */
216void QAudioEngine::setOutputDevice(const QAudioDevice &device)
217{
218 Q_D(QAudioEngine);
219 d->setOutputDevice(device);
220}
221
222QAudioDevice QAudioEngine::outputDevice() const
223{
224 Q_D(const QAudioEngine);
225 return d->outputDevice();
226}
227
228/*!
229 \property QAudioEngine::masterVolume
230
231 Sets or returns volume being used to render the sound field.
232 */
233void QAudioEngine::setMasterVolume(float volume)
234{
235 Q_D(QAudioEngine);
236 return d->setMasterVolume(volume);
237}
238
239float QAudioEngine::masterVolume() const
240{
241 Q_D(const QAudioEngine);
242 return d->masterVolume();
243}
244
245/*!
246 Starts the engine.
247 */
248void QAudioEngine::start()
249{
250 Q_D(QAudioEngine);
251 d->start();
252}
253
254/*!
255 Stops the engine.
256 */
257void QAudioEngine::stop()
258{
259 Q_D(QAudioEngine);
260 d->stop();
261}
262
263/*!
264 \property QAudioEngine::paused
265
266 Pauses the spatial audio engine.
267 */
268void QAudioEngine::setPaused(bool paused)
269{
270 Q_D(QAudioEngine);
271 d->setPaused(paused);
272}
273
274bool QAudioEngine::paused() const
275{
276 Q_D(const QAudioEngine);
277 return d->isPaused();
278}
279
280/*!
281 Enables room effects such as echos and reverb.
282
283 Enables room effects if \a enabled is true.
284 Room effects will only apply if you create one or more \l QAudioRoom objects
285 and the listener is inside at least one of the rooms. If the listener is inside
286 multiple rooms, the room with the smallest volume will be used.
287 */
288void QAudioEngine::setRoomEffectsEnabled(bool enabled)
289{
290 Q_D(QAudioEngine);
291 d->setRoomEffectsEnabled(enabled);
292}
293
294/*!
295 Returns true if room effects are enabled.
296 */
297bool QAudioEngine::roomEffectsEnabled() const
298{
299 Q_D(const QAudioEngine);
300 return d->roomEffectsEnabled();
301}
302
303/*!
304 \property QAudioEngine::distanceScale
305
306 Defines the scale of the coordinate system being used by the spatial audio engine.
307 By default, all units are in centimeters, in line with the default units being
308 used by Qt Quick 3D.
309
310 Set the distance scale to QAudioEngine::DistanceScaleMeter to get units in meters.
311*/
312void QAudioEngine::setDistanceScale(float scale)
313{
314 Q_D(QAudioEngine);
315 // multiply with 100, to get the conversion to meters that resonance audio uses
316 scale /= 100.f;
317 if (scale <= 0.0f) {
318 qWarning() << "QAudioEngine: Invalid distance scale.";
319 return;
320 }
321 d->setDistanceScale(scale);
322}
323
324float QAudioEngine::distanceScale() const
325{
326 Q_D(const QAudioEngine);
327 return d->distanceScale() * 100.f;
328}
329
330/*!
331 \fn void QAudioEngine::pause()
332
333 Pauses playback.
334*/
335/*!
336 \fn void QAudioEngine::resume()
337
338 Resumes playback.
339*/
340/*!
341 \variable QAudioEngine::DistanceScaleCentimeter
342 \internal
343*/
344/*!
345 \variable QAudioEngine::DistanceScaleMeter
346 \internal
347*/
348
349QT_END_NAMESPACE
350
351#include "moc_qaudioengine.cpp"