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#include "qaudiolistener.h"
4#include "qaudioengine_p.h"
5#include "resonance_audio.h"
6#include <qaudiosink.h>
7#include <qurl.h>
8#include <qdebug.h>
9#include <qaudiodecoder.h>
10
11QT_BEGIN_NAMESPACE
12
13class QAudioListenerPrivate
14{
15public:
16 QAudioEngine *engine = nullptr;
17 QVector3D pos;
18 QQuaternion rotation;
19};
20
21/*!
22 \class QAudioListener
23 \inmodule QtSpatialAudio
24 \ingroup spatialaudio
25 \ingroup multimedia_audio
26
27 \brief Defines the position and orientation of the person listening to a sound field
28 defined by QAudioEngine.
29
30 A QAudioEngine can have exactly one listener that defines the position and orientation
31 of the person listening to the sound field.
32 */
33
34/*!
35 Creates a listener for the spatial audio engine for \a engine.
36 */
37QAudioListener::QAudioListener(QAudioEngine *engine)
38 : d(new QAudioListenerPrivate)
39{
40 setEngine(engine);
41}
42
43/*!
44 Destroys the listener.
45 */
46QAudioListener::~QAudioListener()
47{
48 delete d;
49}
50
51/*!
52 Sets the listener's position in 3D space to \a pos. Units are in centimeters
53 by default.
54
55 \sa QAudioEngine::distanceScale
56 */
57void QAudioListener::setPosition(QVector3D pos)
58{
59 auto *ep = QAudioEnginePrivate::get(engine: d->engine);
60 pos *= ep->distanceScale;
61 if (d->pos == pos)
62 return;
63
64 d->pos = pos;
65 if (ep && ep->resonanceAudio->api) {
66 ep->resonanceAudio->api->SetHeadPosition(x: pos.x(), y: pos.y(), z: pos.z());
67 ep->listenerPositionDirty = true;
68 }
69}
70
71/*!
72 Returns the current position of the listener.
73 */
74QVector3D QAudioListener::position() const
75{
76 auto *ep = QAudioEnginePrivate::get(engine: d->engine);
77 return d->pos/ep->distanceScale;
78}
79
80/*!
81 Sets the listener's orientation in 3D space to \a q.
82 */
83void QAudioListener::setRotation(const QQuaternion &q)
84{
85 d->rotation = q;
86 auto *ep = QAudioEnginePrivate::get(engine: d->engine);
87 if (ep && ep->resonanceAudio->api)
88 ep->resonanceAudio->api->SetHeadRotation(x: d->rotation.x(), y: d->rotation.y(), z: d->rotation.z(), w: d->rotation.scalar());
89}
90
91/*!
92 Returns the listener's orientation in 3D space.
93 */
94QQuaternion QAudioListener::rotation() const
95{
96 return d->rotation;
97}
98
99/*!
100 \internal
101 */
102void QAudioListener::setEngine(QAudioEngine *engine)
103{
104 if (d->engine) {
105 auto *ed = QAudioEnginePrivate::get(engine: d->engine);
106 ed->listener = nullptr;
107 }
108 d->engine = engine;
109 if (d->engine) {
110 auto *ed = QAudioEnginePrivate::get(engine: d->engine);
111 if (ed->listener) {
112 qWarning() << "Ignoring attempt to add a second listener to the spatial audio engine.";
113 d->engine = nullptr;
114 return;
115 }
116 ed->listener = this;
117 }
118}
119
120/*!
121 Returns the engine associated with this listener.
122 */
123QAudioEngine *QAudioListener::engine() const
124{
125 return d->engine;
126}
127
128QT_END_NAMESPACE
129

source code of qtmultimedia/src/spatialaudio/qaudiolistener.cpp