@@ -5,24 +5,36 @@ import type { _WebAudioEngine } from "../webAudioEngine";
5
5
6
6
const TmpMatrix = Matrix . Zero ( ) ;
7
7
const TmpQuaternion = new Quaternion ( ) ;
8
- const TmpVector = Vector3 . Zero ( ) ;
8
+ const TmpVector1 = Vector3 . Zero ( ) ;
9
+ const TmpVector2 = Vector3 . Zero ( ) ;
9
10
10
11
/** @internal */
11
12
export function _CreateSpatialAudioListener ( engine : _WebAudioEngine , autoUpdate : boolean , minUpdateTime : number ) : _SpatialAudioListener {
12
- return new _SpatialWebAudioListener ( engine , autoUpdate , minUpdateTime ) ;
13
+ const listener = engine . _audioContext . listener ;
14
+ if (
15
+ listener . forwardX &&
16
+ listener . forwardY &&
17
+ listener . forwardZ &&
18
+ listener . positionX &&
19
+ listener . positionY &&
20
+ listener . positionZ &&
21
+ listener . upX &&
22
+ listener . upY &&
23
+ listener . upZ
24
+ ) {
25
+ return new _SpatialWebAudioListener ( engine , autoUpdate , minUpdateTime ) ;
26
+ } else {
27
+ return new _SpatialWebAudioListenerFallback ( engine , autoUpdate , minUpdateTime ) ;
28
+ }
13
29
}
14
30
15
- /**
16
- * This sub property is not backed by a sub node and all properties are set directly on the audio context listener.
17
- *
18
- * @internal
19
- */
20
- class _SpatialWebAudioListener extends _SpatialAudioListener {
21
- private _audioContext : AudioContext ;
22
- private _lastPosition : Vector3 = Vector3 . Zero ( ) ;
23
- private _lastRotation : Vector3 = Vector3 . Zero ( ) ;
24
- private _lastRotationQuaternion : Quaternion = new Quaternion ( ) ;
25
- private _updaterComponent : _SpatialWebAudioUpdaterComponent ;
31
+ abstract class _AbstractSpatialWebAudioListener extends _SpatialAudioListener {
32
+ protected readonly _listener : AudioListener ;
33
+
34
+ protected _lastPosition : Vector3 = Vector3 . Zero ( ) ;
35
+ protected _lastRotation : Vector3 = Vector3 . Zero ( ) ;
36
+ protected _lastRotationQuaternion : Quaternion = new Quaternion ( ) ;
37
+ protected _updaterComponent : _SpatialWebAudioUpdaterComponent ;
26
38
27
39
/** @internal */
28
40
public readonly engine : _WebAudioEngine ;
@@ -38,12 +50,20 @@ class _SpatialWebAudioListener extends _SpatialAudioListener {
38
50
public constructor ( engine : _WebAudioEngine , autoUpdate : boolean , minUpdateTime : number ) {
39
51
super ( ) ;
40
52
53
+ this . _listener = engine . _audioContext . listener ;
41
54
this . engine = engine ;
42
55
43
- this . _audioContext = engine . _audioContext ;
44
56
this . _updaterComponent = new _SpatialWebAudioUpdaterComponent ( this , autoUpdate , minUpdateTime ) ;
45
57
}
46
58
59
+ /** @internal */
60
+ public override dispose ( ) : void {
61
+ super . dispose ( ) ;
62
+
63
+ this . _updaterComponent . dispose ( ) ;
64
+ this . _updaterComponent = null ! ;
65
+ }
66
+
47
67
/** @internal */
48
68
public get minUpdateTime ( ) : number {
49
69
return this . _updaterComponent . minUpdateTime ;
@@ -54,14 +74,6 @@ class _SpatialWebAudioListener extends _SpatialAudioListener {
54
74
this . _updaterComponent . minUpdateTime = value ;
55
75
}
56
76
57
- /** @internal */
58
- public override dispose ( ) : void {
59
- super . dispose ( ) ;
60
-
61
- this . _updaterComponent . dispose ( ) ;
62
- this . _updaterComponent = null ! ;
63
- }
64
-
65
77
/** @internal */
66
78
public update ( ) : void {
67
79
if ( this . isAttached ) {
@@ -72,22 +84,16 @@ class _SpatialWebAudioListener extends _SpatialAudioListener {
72
84
}
73
85
}
74
86
75
- /** @internal */
76
87
public _updatePosition ( ) : void {
77
88
if ( this . _lastPosition . equalsWithEpsilon ( this . position ) ) {
78
89
return ;
79
90
}
80
91
81
- const listener = this . _audioContext . listener ;
82
-
83
- this . engine . _setAudioParam ( listener . positionX , this . position . x ) ;
84
- this . engine . _setAudioParam ( listener . positionY , this . position . y ) ;
85
- this . engine . _setAudioParam ( listener . positionZ , this . position . z ) ;
92
+ this . _setWebAudioPosition ( this . position ) ;
86
93
87
94
this . _lastPosition . copyFrom ( this . position ) ;
88
95
}
89
96
90
- /** @internal */
91
97
public _updateRotation ( ) : void {
92
98
if ( ! this . _lastRotationQuaternion . equalsWithEpsilon ( this . rotationQuaternion ) ) {
93
99
TmpQuaternion . copyFrom ( this . rotationQuaternion ) ;
@@ -100,17 +106,68 @@ class _SpatialWebAudioListener extends _SpatialAudioListener {
100
106
}
101
107
102
108
Matrix . FromQuaternionToRef ( TmpQuaternion , TmpMatrix ) ;
103
- const listener = this . _audioContext . listener ;
104
109
105
110
// NB: The WebAudio API is right-handed.
106
- Vector3 . TransformNormalToRef ( Vector3 . RightHandedForwardReadOnly , TmpMatrix , TmpVector ) ;
107
- this . engine . _setAudioParam ( listener . forwardX , TmpVector . x ) ;
108
- this . engine . _setAudioParam ( listener . forwardY , TmpVector . y ) ;
109
- this . engine . _setAudioParam ( listener . forwardZ , TmpVector . z ) ;
110
-
111
- Vector3 . TransformNormalToRef ( Vector3 . Up ( ) , TmpMatrix , TmpVector ) ;
112
- this . engine . _setAudioParam ( listener . upX , TmpVector . x ) ;
113
- this . engine . _setAudioParam ( listener . upY , TmpVector . y ) ;
114
- this . engine . _setAudioParam ( listener . upZ , TmpVector . z ) ;
111
+ Vector3 . TransformNormalToRef ( Vector3 . RightHandedForwardReadOnly , TmpMatrix , TmpVector1 ) ;
112
+ Vector3 . TransformNormalToRef ( Vector3 . Up ( ) , TmpMatrix , TmpVector2 ) ;
113
+
114
+ this . _setWebAudioOrientation ( TmpVector1 , TmpVector2 ) ;
115
+ }
116
+
117
+ protected abstract _setWebAudioPosition ( position : Vector3 ) : void ;
118
+ protected abstract _setWebAudioOrientation ( forward : Vector3 , up : Vector3 ) : void ;
119
+ }
120
+
121
+ /**
122
+ * Full-featured spatial audio listener for the Web Audio API.
123
+ *
124
+ * Used in browsers that support the `forwardX/Y/Z`, `positionX/Y/Z`, and `upX/Y/Z` properties on the AudioContext listener.
125
+ *
126
+ * NB: Firefox falls back to using this implementation.
127
+ *
128
+ * @see _SpatialWebAudioListenerFallback for the implementation used if only `setPosition` and `setOrientation` are available.
129
+ *
130
+ * NB: This sub property is not backed by a sub node and all properties are set directly on the audio context listener.
131
+ *
132
+ * @internal
133
+ */
134
+ class _SpatialWebAudioListener extends _AbstractSpatialWebAudioListener {
135
+ protected override _setWebAudioPosition ( position : Vector3 ) : void {
136
+ this . engine . _setAudioParam ( this . _listener . positionX , position . x ) ;
137
+ this . engine . _setAudioParam ( this . _listener . positionY , position . y ) ;
138
+ this . engine . _setAudioParam ( this . _listener . positionZ , position . z ) ;
139
+ }
140
+
141
+ protected override _setWebAudioOrientation ( forward : Vector3 , up : Vector3 ) : void {
142
+ this . engine . _setAudioParam ( this . _listener . forwardX , forward . x ) ;
143
+ this . engine . _setAudioParam ( this . _listener . forwardY , forward . y ) ;
144
+ this . engine . _setAudioParam ( this . _listener . forwardZ , forward . z ) ;
145
+
146
+ this . engine . _setAudioParam ( this . _listener . upX , up . x ) ;
147
+ this . engine . _setAudioParam ( this . _listener . upY , up . y ) ;
148
+ this . engine . _setAudioParam ( this . _listener . upZ , up . z ) ;
149
+ }
150
+ }
151
+
152
+ /**
153
+ * Fallback spatial audio listener for the Web Audio API.
154
+ *
155
+ * Used in browsers that do not support the `forwardX/Y/Z`, `positionX/Y/Z`, and `upX/Y/Z` properties on the
156
+ * AudioContext listener.
157
+ *
158
+ * @see _SpatialWebAudioListener for the implementation used if the `forwardX/Y/Z`, `positionX/Y/Z`, and `upX/Y/Z`
159
+ * properties are available.
160
+ *
161
+ * NB: This sub property is not backed by a sub node and all properties are set directly on the audio context listener.
162
+ *
163
+ * @internal
164
+ */
165
+ class _SpatialWebAudioListenerFallback extends _AbstractSpatialWebAudioListener {
166
+ protected override _setWebAudioPosition ( position : Vector3 ) : void {
167
+ this . _listener . setPosition ( this . position . x , this . position . y , this . position . z ) ;
168
+ }
169
+
170
+ protected override _setWebAudioOrientation ( forward : Vector3 , up : Vector3 ) : void {
171
+ this . _listener . setOrientation ( forward . x , forward . y , forward . z , up . x , up . y , up . z ) ;
115
172
}
116
173
}
0 commit comments