|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */ |
|
3 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #include "AudioListener.h" |
|
8 #include "AudioContext.h" |
|
9 #include "mozilla/dom/AudioListenerBinding.h" |
|
10 |
|
11 namespace mozilla { |
|
12 namespace dom { |
|
13 |
|
14 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(AudioListener, mContext) |
|
15 |
|
16 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(AudioListener, AddRef) |
|
17 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AudioListener, Release) |
|
18 |
|
19 AudioListener::AudioListener(AudioContext* aContext) |
|
20 : mContext(aContext) |
|
21 , mPosition() |
|
22 , mFrontVector(0., 0., -1.) |
|
23 , mRightVector(1., 0., 0.) |
|
24 , mVelocity() |
|
25 , mDopplerFactor(1.) |
|
26 , mSpeedOfSound(343.3) // meters/second |
|
27 { |
|
28 MOZ_ASSERT(aContext); |
|
29 SetIsDOMBinding(); |
|
30 } |
|
31 |
|
32 JSObject* |
|
33 AudioListener::WrapObject(JSContext* aCx) |
|
34 { |
|
35 return AudioListenerBinding::Wrap(aCx, this); |
|
36 } |
|
37 |
|
38 void |
|
39 AudioListener::SetOrientation(double aX, double aY, double aZ, |
|
40 double aXUp, double aYUp, double aZUp) |
|
41 { |
|
42 ThreeDPoint front(aX, aY, aZ); |
|
43 // The panning effect and the azimuth and elevation calculation in the Web |
|
44 // Audio spec becomes undefined with linearly dependent vectors, so keep |
|
45 // existing state in these situations. |
|
46 if (front.IsZero()) { |
|
47 return; |
|
48 } |
|
49 // Normalize before using CrossProduct() to avoid overflow. |
|
50 front.Normalize(); |
|
51 ThreeDPoint up(aXUp, aYUp, aZUp); |
|
52 if (up.IsZero()) { |
|
53 return; |
|
54 } |
|
55 up.Normalize(); |
|
56 ThreeDPoint right = front.CrossProduct(up); |
|
57 if (right.IsZero()) { |
|
58 return; |
|
59 } |
|
60 right.Normalize(); |
|
61 |
|
62 if (!mFrontVector.FuzzyEqual(front)) { |
|
63 mFrontVector = front; |
|
64 SendThreeDPointParameterToStream(PannerNode::LISTENER_FRONT_VECTOR, front); |
|
65 } |
|
66 if (!mRightVector.FuzzyEqual(right)) { |
|
67 mRightVector = right; |
|
68 SendThreeDPointParameterToStream(PannerNode::LISTENER_RIGHT_VECTOR, right); |
|
69 } |
|
70 } |
|
71 |
|
72 void |
|
73 AudioListener::RegisterPannerNode(PannerNode* aPannerNode) |
|
74 { |
|
75 mPanners.AppendElement(aPannerNode->asWeakPtr()); |
|
76 |
|
77 // Let the panner node know about our parameters |
|
78 aPannerNode->SendThreeDPointParameterToStream(PannerNode::LISTENER_POSITION, mPosition); |
|
79 aPannerNode->SendThreeDPointParameterToStream(PannerNode::LISTENER_FRONT_VECTOR, mFrontVector); |
|
80 aPannerNode->SendThreeDPointParameterToStream(PannerNode::LISTENER_RIGHT_VECTOR, mRightVector); |
|
81 aPannerNode->SendThreeDPointParameterToStream(PannerNode::LISTENER_VELOCITY, mVelocity); |
|
82 aPannerNode->SendDoubleParameterToStream(PannerNode::LISTENER_DOPPLER_FACTOR, mDopplerFactor); |
|
83 aPannerNode->SendDoubleParameterToStream(PannerNode::LISTENER_SPEED_OF_SOUND, mSpeedOfSound); |
|
84 UpdatePannersVelocity(); |
|
85 } |
|
86 |
|
87 void AudioListener::UnregisterPannerNode(PannerNode* aPannerNode) |
|
88 { |
|
89 mPanners.RemoveElement(aPannerNode); |
|
90 } |
|
91 |
|
92 void |
|
93 AudioListener::SendDoubleParameterToStream(uint32_t aIndex, double aValue) |
|
94 { |
|
95 for (uint32_t i = 0; i < mPanners.Length(); ++i) { |
|
96 if (mPanners[i]) { |
|
97 mPanners[i]->SendDoubleParameterToStream(aIndex, aValue); |
|
98 } |
|
99 } |
|
100 } |
|
101 |
|
102 void |
|
103 AudioListener::SendThreeDPointParameterToStream(uint32_t aIndex, const ThreeDPoint& aValue) |
|
104 { |
|
105 for (uint32_t i = 0; i < mPanners.Length(); ++i) { |
|
106 if (mPanners[i]) { |
|
107 mPanners[i]->SendThreeDPointParameterToStream(aIndex, aValue); |
|
108 } |
|
109 } |
|
110 } |
|
111 |
|
112 void AudioListener::UpdatePannersVelocity() |
|
113 { |
|
114 for (uint32_t i = 0; i < mPanners.Length(); ++i) { |
|
115 if (mPanners[i]) { |
|
116 mPanners[i]->SendDopplerToSourcesIfNeeded(); |
|
117 } |
|
118 } |
|
119 } |
|
120 |
|
121 size_t |
|
122 AudioListener::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const |
|
123 { |
|
124 size_t amount = aMallocSizeOf(this); |
|
125 // AudioNodes are tracked separately |
|
126 amount += mPanners.SizeOfExcludingThis(aMallocSizeOf); |
|
127 return amount; |
|
128 } |
|
129 |
|
130 } |
|
131 } |
|
132 |