Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qaudioroom.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
"qaudioroom.h"
5
#
include
"qaudioroom_p.h"
6
7
#
include
<
QtCore
/
qspan
.
h
>
8
9
#
include
"platforms/common/room_effects_utils.h"
10
11
QT_BEGIN_NAMESPACE
12
13
namespace
{
14
15
inline
QVector3D
toVector
(QSpan<
const
float
, 3> f)
16
{
17
return
QVector3D(f[0], f[1], f[2]);
18
}
19
20
inline
void
toFloats
(QVector3D v, QSpan<
float
, 3> f)
21
{
22
f[0] = v.x();
23
f[1] = v.y();
24
f[2] = v.z();
25
}
26
27
inline
QQuaternion
toQuaternion
(QSpan<
const
float
, 4> f)
28
{
29
// resonance audio puts the scalar component last
30
return
QQuaternion(f[3], f[0], f[1], f[2]);
31
}
32
33
inline
void
toFloats
(QQuaternion q, QSpan<
float
, 4> f)
34
{
35
f[0] = q.x();
36
f[1] = q.y();
37
f[2] = q.z();
38
f[3] = q.scalar();
39
}
40
41
// Default values for occlusion and dampening of different wall materials.
42
// These values are used as defaults if a wall is only defined by a material
43
// and define how sound passes through the wall.
44
// We define both occlusion and dampening constants to be able to tune the
45
// sound. Dampening only reduces the level of the sound without affecting its
46
// tone, while occlusion will dampen higher frequencies more than lower ones
47
constexpr
struct
{
48
float
occlusion;
49
float
dampening;
50
} occlusionAndDampening[] = {
51
{ 0.f, 1.f },
// Transparent,
52
{ 0.f, .1f },
// AcousticCeilingTiles,
53
{ 2.f, .4f },
// BrickBare,
54
{ 2.f, .4f },
// BrickPainted,
55
{ 4.f, 1.f },
// ConcreteBlockCoarse,
56
{ 4.f, 1.f },
// ConcreteBlockPainted,
57
{ .7f, .7f },
// CurtainHeavy,
58
{ .5f, .5f },
// FiberGlassInsulation,
59
{ .2f, .3f },
// GlassThin,
60
{ .5f, .2f },
// GlassThick,
61
{ 7.f, 1.f },
// Grass,
62
{ 4.f, 1.f },
// LinoleumOnConcrete,
63
{ 4.f, 1.f },
// Marble,
64
{ 0.f, .2f },
// Metal,
65
{ 4.f, 1.f },
// ParquetOnConcrete,
66
{ 2.f, .4f },
// PlasterRough,
67
{ 2.f, .4f },
// PlasterSmooth,
68
{ 1.5f, .2f },
// PlywoodPanel,
69
{ 4.f, 1.f },
// PolishedConcreteOrTile,
70
{ 4.f, 1.f },
// Sheetrock,
71
{ 4.f, 1.f },
// WaterOrIceSurface,
72
{ 1.f, .3f },
// WoodCeiling,
73
{ 1.f, .3f },
// WoodPanel,
74
{ 0.f, .0f },
// UniformMaterial,
75
};
76
77
}
78
79
// make sure the wall definitions agree with resonance audio
80
81
static_assert
(QAudioRoom::LeftWall == 0);
82
static_assert
(QAudioRoom::RightWall == 1);
83
static_assert
(QAudioRoom::Floor == 2);
84
static_assert
(QAudioRoom::Ceiling == 3);
85
static_assert
(QAudioRoom::FrontWall == 4);
86
static_assert
(QAudioRoom::BackWall == 5);
87
88
void
QAudioRoomPrivate::requestUpdate()
89
{
90
dirty =
true
;
91
auto
ep = QAudioEnginePrivate::get(engine);
92
if
(!ep)
93
return
;
94
ep->updateRooms();
95
}
96
97
float
QAudioRoomPrivate::wallOcclusion(QAudioRoom::Wall wall)
const
98
{
99
return
m_wallOcclusion[wall] < 0 ? occlusionAndDampening[roomProperties.material_names[wall]].occlusion : m_wallOcclusion[wall];
100
}
101
102
float
QAudioRoomPrivate::wallDampening(QAudioRoom::Wall wall)
const
103
{
104
return
m_wallDampening[wall] < 0 ? occlusionAndDampening[roomProperties.material_names[wall]].dampening : m_wallDampening[wall];
105
}
106
107
void
QAudioRoomPrivate::update()
108
{
109
if
(!dirty)
110
return
;
111
reflections = vraudio::ComputeReflectionProperties(roomProperties);
112
reverb = vraudio::ComputeReverbProperties(roomProperties);
113
dirty =
false
;
114
}
115
116
117
/*!
118
\class QAudioRoom
119
\inmodule QtSpatialAudio
120
\ingroup spatialaudio
121
\ingroup multimedia_audio
122
123
\brief Defines a room for the spatial audio engine.
124
125
If the listener is inside a room, first order sound reflections and reverb
126
matching the rooms properties will get applied to the sound field.
127
128
A room is always square and defined by its center position, its orientation and dimensions.
129
Each of the 6 walls of the room can be made of different materials that will contribute
130
to the computed reflections and reverb that the listener will experience while being inside
131
the room.
132
133
If multiple rooms cover the same position, the engine will use the room with the smallest
134
volume.
135
*/
136
137
/*!
138
Constructs a QAudioRoom for \a engine.
139
140
\note Must be called with a valid QAudioEngine
141
*/
142
QAudioRoom::QAudioRoom(QAudioEngine *engine) : QObject(*
new
QAudioRoomPrivate)
143
{
144
if
(!engine) {
145
qWarning() <<
"Cannot create QAudioRoom without a valid QAudioEngine"
;
146
return
;
147
}
148
149
Q_D(QAudioRoom);
150
d->engine = engine;
151
auto
*ep = QAudioEnginePrivate::get(engine);
152
if
(!ep)
153
return
;
154
ep->addRoom(
this
);
155
}
156
157
/*!
158
Destroys the room.
159
*/
160
QAudioRoom::~QAudioRoom()
161
{
162
Q_D(QAudioRoom);
163
auto
*ep = QAudioEnginePrivate::get(d->engine);
164
if
(ep)
165
ep->removeRoom(
this
);
166
}
167
168
/*!
169
\enum QAudioRoom::Material
170
171
Defines different materials that can be applied to the different walls of the room.
172
173
\value Transparent The side of the room is open and won't contribute to reflections or reverb.
174
\value AcousticCeilingTiles Acoustic tiles that suppress most reflections and reverb.
175
\value BrickBare Bare brick wall.
176
\value BrickPainted Painted brick wall.
177
\value ConcreteBlockCoarse Raw concrete wall
178
\value ConcreteBlockPainted Painted concrete wall
179
\value CurtainHeavy Heavy curtain. Will mostly reflect low frequencies
180
\value FiberGlassInsulation Fiber glass insulation. Only reflects very low frequencies
181
\value GlassThin Thin glass wall
182
\value GlassThick Thick glass wall
183
\value Grass Grass
184
\value LinoleumOnConcrete Linoleum floor
185
\value Marble Marble floor
186
\value Metal Metal
187
\value ParquetOnConcrete Parquet wooden floor on concrete
188
\value PlasterRough Rough plaster
189
\value PlasterSmooth Smooth plaster
190
\value PlywoodPanel Plywodden panel
191
\value PolishedConcreteOrTile Polished concrete or tiles
192
\value Sheetrock Rock
193
\value WaterOrIceSurface Water or ice
194
\value WoodCeiling Wooden ceiling
195
\value WoodPanel Wooden panel
196
\value UniformMaterial Artificial material giving uniform reflections on all frequencies
197
*/
198
199
/*!
200
\enum QAudioRoom::Wall
201
202
An enum defining the 6 walls of the room
203
204
\value LeftWall Left wall (negative x)
205
\value RightWall Right wall (positive x)
206
\value Floor Bottom wall (negative y)
207
\value Ceiling Top wall (positive y)
208
\value FrontWall Front wall (negative z)
209
\value BackWall Back wall (positive z)
210
*/
211
212
213
/*!
214
\property QAudioRoom::position
215
216
Defines the position of the center of the room in 3D space. Units are in centimeters
217
by default.
218
219
\sa dimensions, QAudioEngine::distanceScale
220
*/
221
void
QAudioRoom::setPosition(QVector3D pos)
222
{
223
Q_D(QAudioRoom);
224
auto
*ep = QAudioEnginePrivate::get(d->engine);
225
if
(!ep)
226
return
;
227
228
pos *= ep->distanceScale();
229
if
(toVector(d->roomProperties.position) == pos)
230
return
;
231
toFloats(pos, d->roomProperties.position);
232
d->requestUpdate();
233
Q_EMIT positionChanged();
234
}
235
236
QVector3D QAudioRoom::position()
const
237
{
238
Q_D(
const
QAudioRoom);
239
auto
*ep = QAudioEnginePrivate::get(d->engine);
240
if
(!ep)
241
return
{};
242
243
auto
pos = toVector(d->roomProperties.position);
244
pos /= ep->distanceScale();
245
return
pos;
246
}
247
248
/*!
249
\property QAudioRoom::dimensions
250
251
Defines the dimensions of the room in 3D space. Units are in centimeters
252
by default.
253
254
\sa position, QAudioEngine::distanceScale
255
*/
256
void
QAudioRoom::setDimensions(QVector3D dim)
257
{
258
Q_D(QAudioRoom);
259
auto
*ep = QAudioEnginePrivate::get(d->engine);
260
if
(!ep)
261
return
;
262
263
dim *= ep->distanceScale();
264
if
(toVector(d->roomProperties.dimensions) == dim)
265
return
;
266
toFloats(dim, d->roomProperties.dimensions);
267
d->requestUpdate();
268
Q_EMIT dimensionsChanged();
269
}
270
271
QVector3D QAudioRoom::dimensions()
const
272
{
273
Q_D(
const
QAudioRoom);
274
auto
*ep = QAudioEnginePrivate::get(d->engine);
275
if
(!ep)
276
return
{};
277
278
auto
dim = toVector(d->roomProperties.dimensions);
279
dim /= ep->distanceScale();
280
return
dim;
281
}
282
283
/*!
284
\property QAudioRoom::rotation
285
286
Defines the orientation of the room in 3D space.
287
*/
288
void
QAudioRoom::setRotation(
const
QQuaternion &q)
289
{
290
Q_D(QAudioRoom);
291
292
if
(toQuaternion(d->roomProperties.rotation) == q)
293
return
;
294
toFloats(q, d->roomProperties.rotation);
295
d->requestUpdate();
296
Q_EMIT rotationChanged();
297
}
298
299
QQuaternion QAudioRoom::rotation()
const
300
{
301
Q_D(
const
QAudioRoom);
302
303
return
toQuaternion(d->roomProperties.rotation);
304
}
305
306
/*!
307
\fn void QAudioRoom::wallsChanged()
308
309
Signals when the wall material changes.
310
*/
311
/*!
312
Sets \a wall to \a material.
313
314
Different wall materials have different reflection and reverb properties
315
that influence the sound of the room.
316
317
\sa wallMaterial(), Material, QAudioRoom::Wall
318
*/
319
void
QAudioRoom::setWallMaterial(Wall wall, Material material)
320
{
321
Q_D(QAudioRoom);
322
323
static_assert
(vraudio::kUniform ==
int
(UniformMaterial));
324
static_assert
(vraudio::kTransparent ==
int
(Transparent));
325
326
if
(d->roomProperties.material_names[
int
(wall)] ==
int
(material))
327
return
;
328
d->roomProperties.material_names[
int
(wall)] = vraudio::MaterialName(
int
(material));
329
d->requestUpdate();
330
Q_EMIT wallsChanged();
331
}
332
333
/*!
334
returns the material being used for \a wall.
335
336
\sa setWallMaterial(), Material, QAudioRoom::Wall
337
*/
338
QAudioRoom::Material QAudioRoom::wallMaterial(Wall wall)
const
339
{
340
Q_D(
const
QAudioRoom);
341
return
Material(d->roomProperties.material_names[
int
(wall)]);
342
}
343
344
/*!
345
\property QAudioRoom::reflectionGain
346
347
A gain factor for reflections generated in this room. A value
348
from 0 to 1 will dampen reflections, while a value larger than 1
349
will apply a gain to reflections, making them louder.
350
351
The default is 1, a factor of 0 disables reflections. Negative
352
values are mapped to 0.
353
*/
354
void
QAudioRoom::setReflectionGain(
float
factor)
355
{
356
Q_D(QAudioRoom);
357
358
if
(factor < 0.)
359
factor = 0.;
360
if
(d->roomProperties.reflection_scalar == factor)
361
return
;
362
d->roomProperties.reflection_scalar = factor;
363
d->requestUpdate();
364
Q_EMIT reflectionGainChanged();
365
}
366
367
float
QAudioRoom::reflectionGain()
const
368
{
369
Q_D(
const
QAudioRoom);
370
return
d->roomProperties.reflection_scalar;
371
}
372
373
/*!
374
\property QAudioRoom::reverbGain
375
376
A gain factor for reverb generated in this room. A value
377
from 0 to 1 will dampen reverb, while a value larger than 1
378
will apply a gain to the reverb, making it louder.
379
380
The default is 1, a factor of 0 disables reverb. Negative
381
values are mapped to 0.
382
*/
383
void
QAudioRoom::setReverbGain(
float
factor)
384
{
385
Q_D(QAudioRoom);
386
387
if
(factor < 0)
388
factor = 0;
389
if
(d->roomProperties.reverb_gain == factor)
390
return
;
391
d->roomProperties.reverb_gain = factor;
392
d->requestUpdate();
393
Q_EMIT reverbGainChanged();
394
}
395
396
float
QAudioRoom::reverbGain()
const
397
{
398
Q_D(
const
QAudioRoom);
399
400
return
d->roomProperties.reverb_gain;
401
}
402
403
/*!
404
\property QAudioRoom::reverbTime
405
406
A factor to be applies to all reverb timings generated for this room.
407
Larger values will lead to longer reverb timings, making the room sound
408
larger.
409
410
The default is 1. Negative values are mapped to 0.
411
*/
412
void
QAudioRoom::setReverbTime(
float
factor)
413
{
414
Q_D(QAudioRoom);
415
416
if
(factor < 0)
417
factor = 0;
418
if
(d->roomProperties.reverb_time == factor)
419
return
;
420
d->roomProperties.reverb_time = factor;
421
d->requestUpdate();
422
Q_EMIT reverbTimeChanged();
423
}
424
425
float
QAudioRoom::reverbTime()
const
426
{
427
Q_D(
const
QAudioRoom);
428
429
return
d->roomProperties.reverb_time;
430
}
431
432
/*!
433
\property QAudioRoom::reverbBrightness
434
435
A brightness factor to be applied to the generated reverb.
436
A positive value will increase reverb for higher frequencies and
437
dampen lower frequencies, a negative value does the reverse.
438
439
The default is 0.
440
*/
441
void
QAudioRoom::setReverbBrightness(
float
factor)
442
{
443
Q_D(QAudioRoom);
444
445
if
(d->roomProperties.reverb_brightness == factor)
446
return
;
447
d->roomProperties.reverb_brightness = factor;
448
d->requestUpdate();
449
Q_EMIT reverbBrightnessChanged();
450
}
451
452
float
QAudioRoom::reverbBrightness()
const
453
{
454
Q_D(
const
QAudioRoom);
455
456
return
d->roomProperties.reverb_brightness;
457
}
458
459
QT_END_NAMESPACE
460
461
#
include
"moc_qaudioroom.cpp"
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
QT_BEGIN_NAMESPACE::toQuaternion
QQuaternion toQuaternion(QSpan< const float, 4 > f)
Definition
qaudioroom.cpp:27
QT_BEGIN_NAMESPACE::toVector
QVector3D toVector(QSpan< const float, 3 > f)
Definition
qaudioroom.cpp:15
QT_BEGIN_NAMESPACE::toFloats
void toFloats(QVector3D v, QSpan< float, 3 > f)
Definition
qaudioroom.cpp:20
qtmultimedia
src
spatialaudio
qaudioroom.cpp
Generated on
for Qt by
1.18.0