1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/media/webaudio/PannerNode.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,301 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim:set ts=2 sw=2 sts=2 et cindent: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef PannerNode_h_ 1.11 +#define PannerNode_h_ 1.12 + 1.13 +#include "AudioNode.h" 1.14 +#include "mozilla/dom/PannerNodeBinding.h" 1.15 +#include "ThreeDPoint.h" 1.16 +#include "mozilla/WeakPtr.h" 1.17 +#include "mozilla/Preferences.h" 1.18 +#include "WebAudioUtils.h" 1.19 +#include <set> 1.20 + 1.21 +namespace mozilla { 1.22 +namespace dom { 1.23 + 1.24 +class AudioContext; 1.25 +class AudioBufferSourceNode; 1.26 + 1.27 +class PannerNode : public AudioNode, 1.28 + public SupportsWeakPtr<PannerNode> 1.29 +{ 1.30 +public: 1.31 + MOZ_DECLARE_REFCOUNTED_TYPENAME(PannerNode) 1.32 + explicit PannerNode(AudioContext* aContext); 1.33 + virtual ~PannerNode(); 1.34 + 1.35 + 1.36 + virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE; 1.37 + 1.38 + virtual void DestroyMediaStream() MOZ_OVERRIDE; 1.39 + 1.40 + virtual void SetChannelCount(uint32_t aChannelCount, ErrorResult& aRv) MOZ_OVERRIDE 1.41 + { 1.42 + if (aChannelCount > 2) { 1.43 + aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); 1.44 + return; 1.45 + } 1.46 + AudioNode::SetChannelCount(aChannelCount, aRv); 1.47 + } 1.48 + virtual void SetChannelCountModeValue(ChannelCountMode aMode, ErrorResult& aRv) MOZ_OVERRIDE 1.49 + { 1.50 + if (aMode == ChannelCountMode::Max) { 1.51 + aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); 1.52 + return; 1.53 + } 1.54 + AudioNode::SetChannelCountModeValue(aMode, aRv); 1.55 + } 1.56 + 1.57 + NS_DECL_ISUPPORTS_INHERITED 1.58 + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PannerNode, AudioNode) 1.59 + 1.60 + PanningModelType PanningModel() const 1.61 + { 1.62 + return mPanningModel; 1.63 + } 1.64 + void SetPanningModel(PanningModelType aPanningModel) 1.65 + { 1.66 + if (!Preferences::GetBool("media.webaudio.legacy.PannerNode")) { 1.67 + // Do not accept the alternate enum values unless the legacy pref 1.68 + // has been turned on. 1.69 + switch (aPanningModel) { 1.70 + case PanningModelType::_0: 1.71 + case PanningModelType::_1: 1.72 + // Do nothing in order to emulate setting an invalid enum value. 1.73 + return; 1.74 + default: 1.75 + // Shut up the compiler warning 1.76 + break; 1.77 + } 1.78 + } 1.79 + 1.80 + // Handle the alternate enum values 1.81 + switch (aPanningModel) { 1.82 + case PanningModelType::_0: aPanningModel = PanningModelType::Equalpower; break; 1.83 + case PanningModelType::_1: aPanningModel = PanningModelType::HRTF; break; 1.84 + default: 1.85 + // Shut up the compiler warning 1.86 + break; 1.87 + } 1.88 + 1.89 + mPanningModel = aPanningModel; 1.90 + SendInt32ParameterToStream(PANNING_MODEL, int32_t(mPanningModel)); 1.91 + } 1.92 + 1.93 + DistanceModelType DistanceModel() const 1.94 + { 1.95 + return mDistanceModel; 1.96 + } 1.97 + void SetDistanceModel(DistanceModelType aDistanceModel) 1.98 + { 1.99 + if (!Preferences::GetBool("media.webaudio.legacy.PannerNode")) { 1.100 + // Do not accept the alternate enum values unless the legacy pref 1.101 + // has been turned on. 1.102 + switch (aDistanceModel) { 1.103 + case DistanceModelType::_0: 1.104 + case DistanceModelType::_1: 1.105 + case DistanceModelType::_2: 1.106 + // Do nothing in order to emulate setting an invalid enum value. 1.107 + return; 1.108 + default: 1.109 + // Shut up the compiler warning 1.110 + break; 1.111 + } 1.112 + } 1.113 + 1.114 + // Handle the alternate enum values 1.115 + switch (aDistanceModel) { 1.116 + case DistanceModelType::_0: aDistanceModel = DistanceModelType::Linear; break; 1.117 + case DistanceModelType::_1: aDistanceModel = DistanceModelType::Inverse; break; 1.118 + case DistanceModelType::_2: aDistanceModel = DistanceModelType::Exponential; break; 1.119 + default: 1.120 + // Shut up the compiler warning 1.121 + break; 1.122 + } 1.123 + 1.124 + mDistanceModel = aDistanceModel; 1.125 + SendInt32ParameterToStream(DISTANCE_MODEL, int32_t(mDistanceModel)); 1.126 + } 1.127 + 1.128 + void SetPosition(double aX, double aY, double aZ) 1.129 + { 1.130 + if (WebAudioUtils::FuzzyEqual(mPosition.x, aX) && 1.131 + WebAudioUtils::FuzzyEqual(mPosition.y, aY) && 1.132 + WebAudioUtils::FuzzyEqual(mPosition.z, aZ)) { 1.133 + return; 1.134 + } 1.135 + mPosition.x = aX; 1.136 + mPosition.y = aY; 1.137 + mPosition.z = aZ; 1.138 + SendThreeDPointParameterToStream(POSITION, mPosition); 1.139 + } 1.140 + 1.141 + void SetOrientation(double aX, double aY, double aZ) 1.142 + { 1.143 + ThreeDPoint orientation(aX, aY, aZ); 1.144 + if (!orientation.IsZero()) { 1.145 + orientation.Normalize(); 1.146 + } 1.147 + if (mOrientation.FuzzyEqual(orientation)) { 1.148 + return; 1.149 + } 1.150 + mOrientation = orientation; 1.151 + SendThreeDPointParameterToStream(ORIENTATION, mOrientation); 1.152 + } 1.153 + 1.154 + void SetVelocity(double aX, double aY, double aZ) 1.155 + { 1.156 + if (WebAudioUtils::FuzzyEqual(mVelocity.x, aX) && 1.157 + WebAudioUtils::FuzzyEqual(mVelocity.y, aY) && 1.158 + WebAudioUtils::FuzzyEqual(mVelocity.z, aZ)) { 1.159 + return; 1.160 + } 1.161 + mVelocity.x = aX; 1.162 + mVelocity.y = aY; 1.163 + mVelocity.z = aZ; 1.164 + SendThreeDPointParameterToStream(VELOCITY, mVelocity); 1.165 + SendDopplerToSourcesIfNeeded(); 1.166 + } 1.167 + 1.168 + double RefDistance() const 1.169 + { 1.170 + return mRefDistance; 1.171 + } 1.172 + void SetRefDistance(double aRefDistance) 1.173 + { 1.174 + if (WebAudioUtils::FuzzyEqual(mRefDistance, aRefDistance)) { 1.175 + return; 1.176 + } 1.177 + mRefDistance = aRefDistance; 1.178 + SendDoubleParameterToStream(REF_DISTANCE, mRefDistance); 1.179 + } 1.180 + 1.181 + double MaxDistance() const 1.182 + { 1.183 + return mMaxDistance; 1.184 + } 1.185 + void SetMaxDistance(double aMaxDistance) 1.186 + { 1.187 + if (WebAudioUtils::FuzzyEqual(mMaxDistance, aMaxDistance)) { 1.188 + return; 1.189 + } 1.190 + mMaxDistance = aMaxDistance; 1.191 + SendDoubleParameterToStream(MAX_DISTANCE, mMaxDistance); 1.192 + } 1.193 + 1.194 + double RolloffFactor() const 1.195 + { 1.196 + return mRolloffFactor; 1.197 + } 1.198 + void SetRolloffFactor(double aRolloffFactor) 1.199 + { 1.200 + if (WebAudioUtils::FuzzyEqual(mRolloffFactor, aRolloffFactor)) { 1.201 + return; 1.202 + } 1.203 + mRolloffFactor = aRolloffFactor; 1.204 + SendDoubleParameterToStream(ROLLOFF_FACTOR, mRolloffFactor); 1.205 + } 1.206 + 1.207 + double ConeInnerAngle() const 1.208 + { 1.209 + return mConeInnerAngle; 1.210 + } 1.211 + void SetConeInnerAngle(double aConeInnerAngle) 1.212 + { 1.213 + if (WebAudioUtils::FuzzyEqual(mConeInnerAngle, aConeInnerAngle)) { 1.214 + return; 1.215 + } 1.216 + mConeInnerAngle = aConeInnerAngle; 1.217 + SendDoubleParameterToStream(CONE_INNER_ANGLE, mConeInnerAngle); 1.218 + } 1.219 + 1.220 + double ConeOuterAngle() const 1.221 + { 1.222 + return mConeOuterAngle; 1.223 + } 1.224 + void SetConeOuterAngle(double aConeOuterAngle) 1.225 + { 1.226 + if (WebAudioUtils::FuzzyEqual(mConeOuterAngle, aConeOuterAngle)) { 1.227 + return; 1.228 + } 1.229 + mConeOuterAngle = aConeOuterAngle; 1.230 + SendDoubleParameterToStream(CONE_OUTER_ANGLE, mConeOuterAngle); 1.231 + } 1.232 + 1.233 + double ConeOuterGain() const 1.234 + { 1.235 + return mConeOuterGain; 1.236 + } 1.237 + void SetConeOuterGain(double aConeOuterGain) 1.238 + { 1.239 + if (WebAudioUtils::FuzzyEqual(mConeOuterGain, aConeOuterGain)) { 1.240 + return; 1.241 + } 1.242 + mConeOuterGain = aConeOuterGain; 1.243 + SendDoubleParameterToStream(CONE_OUTER_GAIN, mConeOuterGain); 1.244 + } 1.245 + 1.246 + float ComputeDopplerShift(); 1.247 + void SendDopplerToSourcesIfNeeded(); 1.248 + void FindConnectedSources(); 1.249 + void FindConnectedSources(AudioNode* aNode, nsTArray<AudioBufferSourceNode*>& aSources, std::set<AudioNode*>& aSeenNodes); 1.250 + 1.251 + virtual const char* NodeType() const 1.252 + { 1.253 + return "PannerNode"; 1.254 + } 1.255 + 1.256 + virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE; 1.257 + virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE; 1.258 + 1.259 +private: 1.260 + friend class AudioListener; 1.261 + friend class PannerNodeEngine; 1.262 + enum EngineParameters { 1.263 + LISTENER_POSITION, 1.264 + LISTENER_FRONT_VECTOR, // unit length 1.265 + LISTENER_RIGHT_VECTOR, // unit length, orthogonal to LISTENER_FRONT_VECTOR 1.266 + LISTENER_VELOCITY, 1.267 + LISTENER_DOPPLER_FACTOR, 1.268 + LISTENER_SPEED_OF_SOUND, 1.269 + PANNING_MODEL, 1.270 + DISTANCE_MODEL, 1.271 + POSITION, 1.272 + ORIENTATION, // unit length or zero 1.273 + VELOCITY, 1.274 + REF_DISTANCE, 1.275 + MAX_DISTANCE, 1.276 + ROLLOFF_FACTOR, 1.277 + CONE_INNER_ANGLE, 1.278 + CONE_OUTER_ANGLE, 1.279 + CONE_OUTER_GAIN 1.280 + }; 1.281 + 1.282 +private: 1.283 + PanningModelType mPanningModel; 1.284 + DistanceModelType mDistanceModel; 1.285 + ThreeDPoint mPosition; 1.286 + ThreeDPoint mOrientation; 1.287 + ThreeDPoint mVelocity; 1.288 + double mRefDistance; 1.289 + double mMaxDistance; 1.290 + double mRolloffFactor; 1.291 + double mConeInnerAngle; 1.292 + double mConeOuterAngle; 1.293 + double mConeOuterGain; 1.294 + 1.295 + // An array of all the AudioBufferSourceNode connected directly or indirectly 1.296 + // to this AudioPannerNode. 1.297 + nsTArray<AudioBufferSourceNode*> mSources; 1.298 +}; 1.299 + 1.300 +} 1.301 +} 1.302 + 1.303 +#endif 1.304 +