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 #ifndef PannerNode_h_
8 #define PannerNode_h_
9 
10 #include "AudioNode.h"
11 #include "AudioParam.h"
12 #include "nsPrintfCString.h"
13 #include "mozilla/dom/PannerNodeBinding.h"
14 #include "ThreeDPoint.h"
15 #include <limits>
16 #include <set>
17 
18 namespace mozilla {
19 namespace dom {
20 
21 class AudioContext;
22 class AudioBufferSourceNode;
23 struct PannerOptions;
24 
25 class PannerNode final : public AudioNode {
26  public:
27   static already_AddRefed<PannerNode> Create(AudioContext& aAudioContext,
28                                              const PannerOptions& aOptions,
29                                              ErrorResult& aRv);
30 
Constructor(const GlobalObject & aGlobal,AudioContext & aAudioContext,const PannerOptions & aOptions,ErrorResult & aRv)31   static already_AddRefed<PannerNode> Constructor(const GlobalObject& aGlobal,
32                                                   AudioContext& aAudioContext,
33                                                   const PannerOptions& aOptions,
34                                                   ErrorResult& aRv) {
35     return Create(aAudioContext, aOptions, aRv);
36   }
37 
38   JSObject* WrapObject(JSContext* aCx,
39                        JS::Handle<JSObject*> aGivenProto) override;
40 
SetChannelCount(uint32_t aChannelCount,ErrorResult & aRv)41   void SetChannelCount(uint32_t aChannelCount, ErrorResult& aRv) override {
42     if (aChannelCount > 2) {
43       aRv.ThrowNotSupportedError(
44           nsPrintfCString("%u is greater than 2", aChannelCount));
45       return;
46     }
47     AudioNode::SetChannelCount(aChannelCount, aRv);
48   }
SetChannelCountModeValue(ChannelCountMode aMode,ErrorResult & aRv)49   void SetChannelCountModeValue(ChannelCountMode aMode,
50                                 ErrorResult& aRv) override {
51     if (aMode == ChannelCountMode::Max) {
52       aRv.ThrowNotSupportedError("Cannot set channel count mode to \"max\"");
53       return;
54     }
55     AudioNode::SetChannelCountModeValue(aMode, aRv);
56   }
57 
58   NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PannerNode,AudioNode)59   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PannerNode, AudioNode)
60 
61   PanningModelType PanningModel() const { return mPanningModel; }
62   void SetPanningModel(PanningModelType aPanningModel);
63 
DistanceModel()64   DistanceModelType DistanceModel() const { return mDistanceModel; }
SetDistanceModel(DistanceModelType aDistanceModel)65   void SetDistanceModel(DistanceModelType aDistanceModel) {
66     mDistanceModel = aDistanceModel;
67     SendInt32ParameterToTrack(DISTANCE_MODEL, int32_t(mDistanceModel));
68   }
69 
70   void SetPosition(double aX, double aY, double aZ, ErrorResult& aRv);
71   void SetOrientation(double aX, double aY, double aZ, ErrorResult& aRv);
72 
RefDistance()73   double RefDistance() const { return mRefDistance; }
SetRefDistance(double aRefDistance,ErrorResult & aRv)74   void SetRefDistance(double aRefDistance, ErrorResult& aRv) {
75     if (WebAudioUtils::FuzzyEqual(mRefDistance, aRefDistance)) {
76       return;
77     }
78 
79     if (aRefDistance < 0) {
80       aRv.ThrowRangeError(
81           "The refDistance value passed to PannerNode must not be negative.");
82       return;
83     }
84 
85     mRefDistance = aRefDistance;
86     SendDoubleParameterToTrack(REF_DISTANCE, mRefDistance);
87   }
88 
MaxDistance()89   double MaxDistance() const { return mMaxDistance; }
SetMaxDistance(double aMaxDistance,ErrorResult & aRv)90   void SetMaxDistance(double aMaxDistance, ErrorResult& aRv) {
91     if (WebAudioUtils::FuzzyEqual(mMaxDistance, aMaxDistance)) {
92       return;
93     }
94 
95     if (aMaxDistance <= 0) {
96       aRv.ThrowRangeError(
97           "The maxDistance value passed to PannerNode must be positive.");
98       return;
99     }
100 
101     mMaxDistance = aMaxDistance;
102     SendDoubleParameterToTrack(MAX_DISTANCE, mMaxDistance);
103   }
104 
RolloffFactor()105   double RolloffFactor() const { return mRolloffFactor; }
SetRolloffFactor(double aRolloffFactor,ErrorResult & aRv)106   void SetRolloffFactor(double aRolloffFactor, ErrorResult& aRv) {
107     if (WebAudioUtils::FuzzyEqual(mRolloffFactor, aRolloffFactor)) {
108       return;
109     }
110 
111     if (aRolloffFactor < 0) {
112       aRv.ThrowRangeError(
113           "The rolloffFactor value passed to PannerNode must not be negative.");
114       return;
115     }
116 
117     mRolloffFactor = aRolloffFactor;
118     SendDoubleParameterToTrack(ROLLOFF_FACTOR, mRolloffFactor);
119   }
120 
ConeInnerAngle()121   double ConeInnerAngle() const { return mConeInnerAngle; }
SetConeInnerAngle(double aConeInnerAngle)122   void SetConeInnerAngle(double aConeInnerAngle) {
123     if (WebAudioUtils::FuzzyEqual(mConeInnerAngle, aConeInnerAngle)) {
124       return;
125     }
126     mConeInnerAngle = aConeInnerAngle;
127     SendDoubleParameterToTrack(CONE_INNER_ANGLE, mConeInnerAngle);
128   }
129 
ConeOuterAngle()130   double ConeOuterAngle() const { return mConeOuterAngle; }
SetConeOuterAngle(double aConeOuterAngle)131   void SetConeOuterAngle(double aConeOuterAngle) {
132     if (WebAudioUtils::FuzzyEqual(mConeOuterAngle, aConeOuterAngle)) {
133       return;
134     }
135     mConeOuterAngle = aConeOuterAngle;
136     SendDoubleParameterToTrack(CONE_OUTER_ANGLE, mConeOuterAngle);
137   }
138 
ConeOuterGain()139   double ConeOuterGain() const { return mConeOuterGain; }
SetConeOuterGain(double aConeOuterGain,ErrorResult & aRv)140   void SetConeOuterGain(double aConeOuterGain, ErrorResult& aRv) {
141     if (WebAudioUtils::FuzzyEqual(mConeOuterGain, aConeOuterGain)) {
142       return;
143     }
144 
145     if (aConeOuterGain < 0 || aConeOuterGain > 1) {
146       aRv.ThrowInvalidStateError(
147           nsPrintfCString("%g is not in the range [0, 1]", aConeOuterGain));
148       return;
149     }
150 
151     mConeOuterGain = aConeOuterGain;
152     SendDoubleParameterToTrack(CONE_OUTER_GAIN, mConeOuterGain);
153   }
154 
PositionX()155   AudioParam* PositionX() { return mPositionX; }
156 
PositionY()157   AudioParam* PositionY() { return mPositionY; }
158 
PositionZ()159   AudioParam* PositionZ() { return mPositionZ; }
160 
OrientationX()161   AudioParam* OrientationX() { return mOrientationX; }
162 
OrientationY()163   AudioParam* OrientationY() { return mOrientationY; }
164 
OrientationZ()165   AudioParam* OrientationZ() { return mOrientationZ; }
166 
NodeType()167   const char* NodeType() const override { return "PannerNode"; }
168 
169   size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override;
170   size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override;
171 
172  private:
173   explicit PannerNode(AudioContext* aContext);
174   ~PannerNode() = default;
175 
176   friend class AudioListener;
177   friend class PannerNodeEngine;
178   enum EngineParameters {
179     PANNING_MODEL,
180     DISTANCE_MODEL,
181     POSITION,
182     POSITIONX,
183     POSITIONY,
184     POSITIONZ,
185     ORIENTATION,  // unit length or zero
186     ORIENTATIONX,
187     ORIENTATIONY,
188     ORIENTATIONZ,
189     REF_DISTANCE,
190     MAX_DISTANCE,
191     ROLLOFF_FACTOR,
192     CONE_INNER_ANGLE,
193     CONE_OUTER_ANGLE,
194     CONE_OUTER_GAIN
195   };
196 
ConvertAudioParamTo3DP(RefPtr<AudioParam> aX,RefPtr<AudioParam> aY,RefPtr<AudioParam> aZ)197   ThreeDPoint ConvertAudioParamTo3DP(RefPtr<AudioParam> aX,
198                                      RefPtr<AudioParam> aY,
199                                      RefPtr<AudioParam> aZ) {
200     return ThreeDPoint(aX->GetValue(), aY->GetValue(), aZ->GetValue());
201   }
202 
203   PanningModelType mPanningModel;
204   DistanceModelType mDistanceModel;
205   RefPtr<AudioParam> mPositionX;
206   RefPtr<AudioParam> mPositionY;
207   RefPtr<AudioParam> mPositionZ;
208   RefPtr<AudioParam> mOrientationX;
209   RefPtr<AudioParam> mOrientationY;
210   RefPtr<AudioParam> mOrientationZ;
211 
212   double mRefDistance;
213   double mMaxDistance;
214   double mRolloffFactor;
215   double mConeInnerAngle;
216   double mConeOuterAngle;
217   double mConeOuterGain;
218 };
219 
220 }  // namespace dom
221 }  // namespace mozilla
222 
223 #endif
224