summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2022-05-13 10:33:07 +0200
committerLars Knoll <lars.knoll@qt.io>2022-05-23 09:36:00 +0200
commit616e78c68b524cf5487947762bfe24784b40b66c (patch)
tree3a5c36e8073ce611a4ebab7d69064449b9772434
parent8df415d5bcf23462bedb4cb7601b909851ee15dd (diff)
spatial audio: Use centimeters by default
Qt Quick 3D uses a centimeters by default for positions and distances. Align our API with that choice. Add a distanceScale property to enable the user to choose a different scale. Store all our data internally in meters, to be aligned with the data expected by resonance audio and to make sure we don't mess up the existing configuration when the distance scale changes. Change-Id: Id06cb49bd152bfa7920c096c662ff103041261e0 Reviewed-by: Rafael Roquetto <rafael.roquetto@qt.io>
-rw-r--r--examples/multimedia/spatialaudio/main.cpp23
-rw-r--r--src/multimedia/spatial/qspatialaudioengine.cpp28
-rw-r--r--src/multimedia/spatial/qspatialaudioengine.h8
-rw-r--r--src/multimedia/spatial/qspatialaudioengine_p.h5
-rw-r--r--src/multimedia/spatial/qspatialaudiolistener.cpp12
-rw-r--r--src/multimedia/spatial/qspatialaudioroom.cpp27
-rw-r--r--src/multimedia/spatial/qspatialaudiosoundsource.cpp34
-rw-r--r--src/multimedia/spatial/qspatialaudiosoundsource.h4
-rw-r--r--src/multimediaquick3d/qquick3dspatialaudioroom.cpp6
9 files changed, 109 insertions, 38 deletions
diff --git a/examples/multimedia/spatialaudio/main.cpp b/examples/multimedia/spatialaudio/main.cpp
index e7ba56962..4fcd5fe8f 100644
--- a/examples/multimedia/spatialaudio/main.cpp
+++ b/examples/multimedia/spatialaudio/main.cpp
@@ -74,8 +74,8 @@ public:
grid->addWidget(new QLabel(tr("Elevation (-90 - 90 degree)")), 2, 0);
grid->addWidget(elevation, 2, 1);
distance = new QSlider(Qt::Horizontal);
- distance->setRange(0, 100);
- distance->setValue(10);
+ distance->setRange(0, 1000);
+ distance->setValue(100);
grid->addWidget(new QLabel(tr("Distance (0 - 10 meter):")), 3, 0);
grid->addWidget(distance, 3, 1);
occlusion = new QSlider(Qt::Horizontal);
@@ -84,8 +84,8 @@ public:
grid->addWidget(occlusion, 4, 1);
roomDimension = new QSlider(Qt::Horizontal);
- roomDimension->setRange(0, 100);
- roomDimension->setValue(5);
+ roomDimension->setRange(0, 10000);
+ roomDimension->setValue(500);
grid->addWidget(new QLabel(tr("Room dimension (0 - 100 meter):")), 5, 0);
grid->addWidget(roomDimension, 5, 1);
@@ -107,9 +107,9 @@ public:
connect(fileEdit, &QLineEdit::textChanged, this, &AudioWidget::fileChanged);
connect(fileDialogButton, &QPushButton::clicked, this, &AudioWidget::openFileDialog);
- connect(azimuth, &QSlider::valueChanged, this, &AudioWidget::newPosition);
- connect(elevation, &QSlider::valueChanged, this, &AudioWidget::newPosition);
- connect(distance, &QSlider::valueChanged, this, &AudioWidget::newPosition);
+ connect(azimuth, &QSlider::valueChanged, this, &AudioWidget::updatePosition);
+ connect(elevation, &QSlider::valueChanged, this, &AudioWidget::updatePosition);
+ connect(distance, &QSlider::valueChanged, this, &AudioWidget::updatePosition);
connect(occlusion, &QSlider::valueChanged, this, &AudioWidget::newOcclusion);
connect(roomDimension, &QSlider::valueChanged, this, &AudioWidget::updateRoom);
@@ -135,16 +135,15 @@ public:
engine.start();
sound = new QSpatialAudioSoundSource(&engine);
-
- distance->setValue(1);
+ updatePosition();
}
void setFile(const QString &file) { fileEdit->setText(file); }
private slots:
- void newPosition()
+ void updatePosition()
{
float az = azimuth->value()/180.*M_PI;
float el = elevation->value()/180.*M_PI;
- float d = distance->value()/10.;
+ float d = distance->value();
float x = d*sin(az)*cos(el);
float y = d*cos(az)*cos(el);
@@ -172,7 +171,7 @@ private slots:
void updateRoom()
{
float d = roomDimension->value();
- room->setDimensions(QVector3D(d, d, 4));
+ room->setDimensions(QVector3D(d, d, 400));
room->setReflectionGain(float(reflectionGain->value())/100);
room->setReverbGain(float(reverbGain->value())/100);
}
diff --git a/src/multimedia/spatial/qspatialaudioengine.cpp b/src/multimedia/spatial/qspatialaudioengine.cpp
index d81294f05..7ab89c1fa 100644
--- a/src/multimedia/spatial/qspatialaudioengine.cpp
+++ b/src/multimedia/spatial/qspatialaudioengine.cpp
@@ -514,6 +514,34 @@ bool QSpatialAudioEngine::roomEffectsEnabled() const
return d->roomEffectsEnabled;
}
+/*!
+ \property QSpatialAudioEngine::distanceScale
+
+ Defines the scale of the coordinate system being used by the spatial audio engine.
+ By default, all units are in centimeters, in line with the default units being
+ used by Qt Quick 3D.
+
+ Set the distance scale to QSpatialAudioEngine::DistanceScaleMeter to get units in meters.
+*/
+void QSpatialAudioEngine::setDistanceScale(float scale)
+{
+ // multiply with 100, to get the conversion to meters that resonance audio uses
+ scale /= 100.f;
+ if (scale <= 0.0f) {
+ qWarning() << "QSpatialAudioEngine: Invalid distance scale.";
+ return;
+ }
+ if (scale == d->distanceScale)
+ return;
+ d->distanceScale = scale;
+ emit distanceScaleChanged();
+}
+
+float QSpatialAudioEngine::distanceScale() const
+{
+ return d->distanceScale*100.f;
+}
+
/*! \class QSpatialAudioSound
\internal
diff --git a/src/multimedia/spatial/qspatialaudioengine.h b/src/multimedia/spatial/qspatialaudioengine.h
index 43bfef056..f67ce5726 100644
--- a/src/multimedia/spatial/qspatialaudioengine.h
+++ b/src/multimedia/spatial/qspatialaudioengine.h
@@ -53,6 +53,7 @@ class Q_MULTIMEDIA_EXPORT QSpatialAudioEngine : public QObject
Q_PROPERTY(QAudioDevice outputDevice READ outputDevice WRITE setOutputDevice NOTIFY outputDeviceChanged)
Q_PROPERTY(float masterVolume READ masterVolume WRITE setMasterVolume NOTIFY masterVolumeChanged)
Q_PROPERTY(bool paused READ paused WRITE setPaused NOTIFY pausedChanged)
+ Q_PROPERTY(float distanceScale READ distanceScale WRITE setDistanceScale NOTIFY distanceScaleChanged)
public:
explicit QSpatialAudioEngine(QObject *parent = nullptr, int sampleRate = 44100);
~QSpatialAudioEngine();
@@ -83,11 +84,18 @@ public:
void setRoomEffectsEnabled(bool enabled);
bool roomEffectsEnabled() const;
+ static constexpr float DistanceScaleCentimeter = 1.f;
+ static constexpr float DistanceScaleMeter = 100.f;
+
+ void setDistanceScale(float scale);
+ float distanceScale() const;
+
Q_SIGNALS:
void outputModeChanged();
void outputDeviceChanged();
void masterVolumeChanged();
void pausedChanged();
+ void distanceScaleChanged();
public Q_SLOTS:
void pause() { setPaused(true); }
diff --git a/src/multimedia/spatial/qspatialaudioengine_p.h b/src/multimedia/spatial/qspatialaudioengine_p.h
index b5df68451..3163f0c86 100644
--- a/src/multimedia/spatial/qspatialaudioengine_p.h
+++ b/src/multimedia/spatial/qspatialaudioengine_p.h
@@ -88,6 +88,11 @@ public:
QSpatialAudioEngine::OutputMode outputMode = QSpatialAudioEngine::Normal;
bool roomEffectsEnabled = true;
+ // Resonance Audio uses meters internally, while Qt Quick 3D and our API uses cm by default.
+ // To make things independent from the scale setting, we store all distances in meters internally
+ // and convert in the setters and getters.
+ float distanceScale = 0.01f;
+
QMutex mutex;
QAudioFormat format;
QAudioDevice device;
diff --git a/src/multimedia/spatial/qspatialaudiolistener.cpp b/src/multimedia/spatial/qspatialaudiolistener.cpp
index 2ee796030..c93e7a1e5 100644
--- a/src/multimedia/spatial/qspatialaudiolistener.cpp
+++ b/src/multimedia/spatial/qspatialaudiolistener.cpp
@@ -82,16 +82,19 @@ QSpatialAudioListener::~QSpatialAudioListener()
}
/*!
- Sets the listener's position in 3D space to \a pos. Units are assumed to
- represent meters.
+ Sets the listener's position in 3D space to \a pos. Units are in centimeters
+ by default.
+
+ \sa QSpatialAudioEngine::distanceScale
*/
void QSpatialAudioListener::setPosition(QVector3D pos)
{
+ auto *ep = QSpatialAudioEnginePrivate::get(d->engine);
+ pos *= ep->distanceScale;
if (d->pos == pos)
return;
d->pos = pos;
- auto *ep = QSpatialAudioEnginePrivate::get(d->engine);
if (ep && ep->api) {
ep->api->SetHeadPosition(pos.x(), pos.y(), pos.z());
ep->listenerPositionDirty = true;
@@ -103,7 +106,8 @@ void QSpatialAudioListener::setPosition(QVector3D pos)
*/
QVector3D QSpatialAudioListener::position() const
{
- return d->pos;
+ auto *ep = QSpatialAudioEnginePrivate::get(d->engine);
+ return d->pos/ep->distanceScale;
}
/*!
diff --git a/src/multimedia/spatial/qspatialaudioroom.cpp b/src/multimedia/spatial/qspatialaudioroom.cpp
index 342127466..9e091c43f 100644
--- a/src/multimedia/spatial/qspatialaudioroom.cpp
+++ b/src/multimedia/spatial/qspatialaudioroom.cpp
@@ -148,6 +148,7 @@ void QSpatialAudioRoomPrivate::update()
QSpatialAudioRoom::QSpatialAudioRoom(QSpatialAudioEngine *engine)
: d(new QSpatialAudioRoomPrivate)
{
+ Q_ASSERT(engine);
d->engine = engine;
auto *ep = QSpatialAudioEnginePrivate::get(engine);
ep->addRoom(this);
@@ -212,11 +213,15 @@ QSpatialAudioRoom::~QSpatialAudioRoom()
/*!
\property QSpatialAudioRoom::position
- Defines the position of the center of the room in 3D space. All units are
- assumed to be in meters.
+ Defines the position of the center of the room in 3D space. Units are in centimeters
+ by default.
+
+ \sa dimensions, QSpatialAudioEngine::distanceScale
*/
void QSpatialAudioRoom::setPosition(QVector3D pos)
{
+ auto *ep = QSpatialAudioEnginePrivate::get(d->engine);
+ pos *= ep->distanceScale;
if (toVector(d->roomProperties.position) == pos)
return;
toFloats(pos, d->roomProperties.position);
@@ -226,17 +231,24 @@ void QSpatialAudioRoom::setPosition(QVector3D pos)
QVector3D QSpatialAudioRoom::position() const
{
- return toVector(d->roomProperties.position);
+ auto *ep = QSpatialAudioEnginePrivate::get(d->engine);
+ auto pos = toVector(d->roomProperties.position);
+ pos /= ep->distanceScale;
+ return pos;
}
/*!
\property QSpatialAudioRoom::dimensions
- Defines the dimensions of the room in 3D space. All units are
- assumed to be in meters.
+ Defines the dimensions of the room in 3D space. Units are in centimeters
+ by default.
+
+ \sa position, QSpatialAudioEngine::distanceScale
*/
void QSpatialAudioRoom::setDimensions(QVector3D dim)
{
+ auto *ep = QSpatialAudioEnginePrivate::get(d->engine);
+ dim *= ep->distanceScale;
if (toVector(d->roomProperties.dimensions) == dim)
return;
toFloats(dim, d->roomProperties.dimensions);
@@ -246,7 +258,10 @@ void QSpatialAudioRoom::setDimensions(QVector3D dim)
QVector3D QSpatialAudioRoom::dimensions() const
{
- return toVector(d->roomProperties.dimensions);
+ auto *ep = QSpatialAudioEnginePrivate::get(d->engine);
+ auto dim = toVector(d->roomProperties.dimensions);
+ dim /= ep->distanceScale;
+ return dim;
}
/*!
diff --git a/src/multimedia/spatial/qspatialaudiosoundsource.cpp b/src/multimedia/spatial/qspatialaudiosoundsource.cpp
index 7384d85ee..c86e6351b 100644
--- a/src/multimedia/spatial/qspatialaudiosoundsource.cpp
+++ b/src/multimedia/spatial/qspatialaudiosoundsource.cpp
@@ -83,13 +83,16 @@ QSpatialAudioSoundSource::~QSpatialAudioSoundSource()
/*!
\property QSpatialAudioSoundSource::position
- Defines the position of the sound source in 3D space. All units are
- assumed to be in meters.
+ Defines the position of the sound source in 3D space. Units are in centimeters
+ by default.
+
+ \sa QSpatialAudioEngine::distanceScale
*/
void QSpatialAudioSoundSource::setPosition(QVector3D pos)
{
- d->pos = pos;
auto *ep = QSpatialAudioEnginePrivate::get(d->engine);
+ pos *= ep->distanceScale;
+ d->pos = pos;
if (ep)
ep->api->SetSourcePosition(d->sourceId, pos.x(), pos.y(), pos.z());
d->updateRoomEffects();
@@ -98,7 +101,8 @@ void QSpatialAudioSoundSource::setPosition(QVector3D pos)
QVector3D QSpatialAudioSoundSource::position() const
{
- return d->pos;
+ auto *ep = QSpatialAudioEnginePrivate::get(d->engine);
+ return d->pos/ep->distanceScale;
}
/*!
@@ -311,11 +315,13 @@ QSpatialAudioSoundSource::DistanceModel QSpatialAudioSoundSource::distanceModel(
object than the size, volume will stay constant. The size is also used to for
occlusion calculations, where large sources can be partially occluded by a wall.
*/
-void QSpatialAudioSoundSource::setSize(float min)
+void QSpatialAudioSoundSource::setSize(float size)
{
- if (d->size == min)
+ auto *ep = QSpatialAudioEnginePrivate::get(d->engine);
+ size *= ep->distanceScale;
+ if (d->size == size)
return;
- d->size = min;
+ d->size = size;
d->updateDistanceModel();
emit sizeChanged();
@@ -323,7 +329,8 @@ void QSpatialAudioSoundSource::setSize(float min)
float QSpatialAudioSoundSource::size() const
{
- return d->size;
+ auto *ep = QSpatialAudioEnginePrivate::get(d->engine);
+ return d->size/ep->distanceScale;
}
/*!
@@ -333,11 +340,13 @@ float QSpatialAudioSoundSource::size() const
If the listener is further away from the sound object than the cutoff
distance it won't be audible anymore.
*/
-void QSpatialAudioSoundSource::setDistanceCutoff(float max)
+void QSpatialAudioSoundSource::setDistanceCutoff(float cutoff)
{
- if (d->distanceCutoff == max)
+ auto *ep = QSpatialAudioEnginePrivate::get(d->engine);
+ cutoff *= ep->distanceScale;
+ if (d->distanceCutoff == cutoff)
return;
- d->distanceCutoff = max;
+ d->distanceCutoff = cutoff;
d->updateDistanceModel();
emit distanceCutoffChanged();
@@ -345,7 +354,8 @@ void QSpatialAudioSoundSource::setDistanceCutoff(float max)
float QSpatialAudioSoundSource::distanceCutoff() const
{
- return d->distanceCutoff;
+ auto *ep = QSpatialAudioEnginePrivate::get(d->engine);
+ return d->distanceCutoff/ep->distanceScale;
}
/*!
diff --git a/src/multimedia/spatial/qspatialaudiosoundsource.h b/src/multimedia/spatial/qspatialaudiosoundsource.h
index e4e8d010c..cd0d8fe75 100644
--- a/src/multimedia/spatial/qspatialaudiosoundsource.h
+++ b/src/multimedia/spatial/qspatialaudiosoundsource.h
@@ -105,10 +105,10 @@ public:
void setDistanceModel(DistanceModel model);
DistanceModel distanceModel() const;
- void setSize(float min);
+ void setSize(float size);
float size() const;
- void setDistanceCutoff(float max);
+ void setDistanceCutoff(float cutoff);
float distanceCutoff() const;
void setManualAttenuation(float attenuation);
diff --git a/src/multimediaquick3d/qquick3dspatialaudioroom.cpp b/src/multimediaquick3d/qquick3dspatialaudioroom.cpp
index 1578a050e..979ecc67d 100644
--- a/src/multimediaquick3d/qquick3dspatialaudioroom.cpp
+++ b/src/multimediaquick3d/qquick3dspatialaudioroom.cpp
@@ -82,8 +82,10 @@ QQuick3DSpatialAudioRoom::~QQuick3DSpatialAudioRoom()
/*!
\qmlproperty vector3D SpatialAudioRoom::dimensions
- Defines the dimensions of the room in 3D space. All units are
- assumed to be in meters.
+ Defines the dimensions of the room in 3D space. Units are in centimeters
+ by default.
+
+ \sa position, QSpatialAudioEngine::distanceScale
*/
void QQuick3DSpatialAudioRoom::setDimensions(QVector3D dim)
{