michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim:set ts=2 sw=2 sts=2 et cindent: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef PannerNode_h_ michael@0: #define PannerNode_h_ michael@0: michael@0: #include "AudioNode.h" michael@0: #include "mozilla/dom/PannerNodeBinding.h" michael@0: #include "ThreeDPoint.h" michael@0: #include "mozilla/WeakPtr.h" michael@0: #include "mozilla/Preferences.h" michael@0: #include "WebAudioUtils.h" michael@0: #include michael@0: michael@0: namespace mozilla { michael@0: namespace dom { michael@0: michael@0: class AudioContext; michael@0: class AudioBufferSourceNode; michael@0: michael@0: class PannerNode : public AudioNode, michael@0: public SupportsWeakPtr michael@0: { michael@0: public: michael@0: MOZ_DECLARE_REFCOUNTED_TYPENAME(PannerNode) michael@0: explicit PannerNode(AudioContext* aContext); michael@0: virtual ~PannerNode(); michael@0: michael@0: michael@0: virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE; michael@0: michael@0: virtual void DestroyMediaStream() MOZ_OVERRIDE; michael@0: michael@0: virtual void SetChannelCount(uint32_t aChannelCount, ErrorResult& aRv) MOZ_OVERRIDE michael@0: { michael@0: if (aChannelCount > 2) { michael@0: aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); michael@0: return; michael@0: } michael@0: AudioNode::SetChannelCount(aChannelCount, aRv); michael@0: } michael@0: virtual void SetChannelCountModeValue(ChannelCountMode aMode, ErrorResult& aRv) MOZ_OVERRIDE michael@0: { michael@0: if (aMode == ChannelCountMode::Max) { michael@0: aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); michael@0: return; michael@0: } michael@0: AudioNode::SetChannelCountModeValue(aMode, aRv); michael@0: } michael@0: michael@0: NS_DECL_ISUPPORTS_INHERITED michael@0: NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PannerNode, AudioNode) michael@0: michael@0: PanningModelType PanningModel() const michael@0: { michael@0: return mPanningModel; michael@0: } michael@0: void SetPanningModel(PanningModelType aPanningModel) michael@0: { michael@0: if (!Preferences::GetBool("media.webaudio.legacy.PannerNode")) { michael@0: // Do not accept the alternate enum values unless the legacy pref michael@0: // has been turned on. michael@0: switch (aPanningModel) { michael@0: case PanningModelType::_0: michael@0: case PanningModelType::_1: michael@0: // Do nothing in order to emulate setting an invalid enum value. michael@0: return; michael@0: default: michael@0: // Shut up the compiler warning michael@0: break; michael@0: } michael@0: } michael@0: michael@0: // Handle the alternate enum values michael@0: switch (aPanningModel) { michael@0: case PanningModelType::_0: aPanningModel = PanningModelType::Equalpower; break; michael@0: case PanningModelType::_1: aPanningModel = PanningModelType::HRTF; break; michael@0: default: michael@0: // Shut up the compiler warning michael@0: break; michael@0: } michael@0: michael@0: mPanningModel = aPanningModel; michael@0: SendInt32ParameterToStream(PANNING_MODEL, int32_t(mPanningModel)); michael@0: } michael@0: michael@0: DistanceModelType DistanceModel() const michael@0: { michael@0: return mDistanceModel; michael@0: } michael@0: void SetDistanceModel(DistanceModelType aDistanceModel) michael@0: { michael@0: if (!Preferences::GetBool("media.webaudio.legacy.PannerNode")) { michael@0: // Do not accept the alternate enum values unless the legacy pref michael@0: // has been turned on. michael@0: switch (aDistanceModel) { michael@0: case DistanceModelType::_0: michael@0: case DistanceModelType::_1: michael@0: case DistanceModelType::_2: michael@0: // Do nothing in order to emulate setting an invalid enum value. michael@0: return; michael@0: default: michael@0: // Shut up the compiler warning michael@0: break; michael@0: } michael@0: } michael@0: michael@0: // Handle the alternate enum values michael@0: switch (aDistanceModel) { michael@0: case DistanceModelType::_0: aDistanceModel = DistanceModelType::Linear; break; michael@0: case DistanceModelType::_1: aDistanceModel = DistanceModelType::Inverse; break; michael@0: case DistanceModelType::_2: aDistanceModel = DistanceModelType::Exponential; break; michael@0: default: michael@0: // Shut up the compiler warning michael@0: break; michael@0: } michael@0: michael@0: mDistanceModel = aDistanceModel; michael@0: SendInt32ParameterToStream(DISTANCE_MODEL, int32_t(mDistanceModel)); michael@0: } michael@0: michael@0: void SetPosition(double aX, double aY, double aZ) michael@0: { michael@0: if (WebAudioUtils::FuzzyEqual(mPosition.x, aX) && michael@0: WebAudioUtils::FuzzyEqual(mPosition.y, aY) && michael@0: WebAudioUtils::FuzzyEqual(mPosition.z, aZ)) { michael@0: return; michael@0: } michael@0: mPosition.x = aX; michael@0: mPosition.y = aY; michael@0: mPosition.z = aZ; michael@0: SendThreeDPointParameterToStream(POSITION, mPosition); michael@0: } michael@0: michael@0: void SetOrientation(double aX, double aY, double aZ) michael@0: { michael@0: ThreeDPoint orientation(aX, aY, aZ); michael@0: if (!orientation.IsZero()) { michael@0: orientation.Normalize(); michael@0: } michael@0: if (mOrientation.FuzzyEqual(orientation)) { michael@0: return; michael@0: } michael@0: mOrientation = orientation; michael@0: SendThreeDPointParameterToStream(ORIENTATION, mOrientation); michael@0: } michael@0: michael@0: void SetVelocity(double aX, double aY, double aZ) michael@0: { michael@0: if (WebAudioUtils::FuzzyEqual(mVelocity.x, aX) && michael@0: WebAudioUtils::FuzzyEqual(mVelocity.y, aY) && michael@0: WebAudioUtils::FuzzyEqual(mVelocity.z, aZ)) { michael@0: return; michael@0: } michael@0: mVelocity.x = aX; michael@0: mVelocity.y = aY; michael@0: mVelocity.z = aZ; michael@0: SendThreeDPointParameterToStream(VELOCITY, mVelocity); michael@0: SendDopplerToSourcesIfNeeded(); michael@0: } michael@0: michael@0: double RefDistance() const michael@0: { michael@0: return mRefDistance; michael@0: } michael@0: void SetRefDistance(double aRefDistance) michael@0: { michael@0: if (WebAudioUtils::FuzzyEqual(mRefDistance, aRefDistance)) { michael@0: return; michael@0: } michael@0: mRefDistance = aRefDistance; michael@0: SendDoubleParameterToStream(REF_DISTANCE, mRefDistance); michael@0: } michael@0: michael@0: double MaxDistance() const michael@0: { michael@0: return mMaxDistance; michael@0: } michael@0: void SetMaxDistance(double aMaxDistance) michael@0: { michael@0: if (WebAudioUtils::FuzzyEqual(mMaxDistance, aMaxDistance)) { michael@0: return; michael@0: } michael@0: mMaxDistance = aMaxDistance; michael@0: SendDoubleParameterToStream(MAX_DISTANCE, mMaxDistance); michael@0: } michael@0: michael@0: double RolloffFactor() const michael@0: { michael@0: return mRolloffFactor; michael@0: } michael@0: void SetRolloffFactor(double aRolloffFactor) michael@0: { michael@0: if (WebAudioUtils::FuzzyEqual(mRolloffFactor, aRolloffFactor)) { michael@0: return; michael@0: } michael@0: mRolloffFactor = aRolloffFactor; michael@0: SendDoubleParameterToStream(ROLLOFF_FACTOR, mRolloffFactor); michael@0: } michael@0: michael@0: double ConeInnerAngle() const michael@0: { michael@0: return mConeInnerAngle; michael@0: } michael@0: void SetConeInnerAngle(double aConeInnerAngle) michael@0: { michael@0: if (WebAudioUtils::FuzzyEqual(mConeInnerAngle, aConeInnerAngle)) { michael@0: return; michael@0: } michael@0: mConeInnerAngle = aConeInnerAngle; michael@0: SendDoubleParameterToStream(CONE_INNER_ANGLE, mConeInnerAngle); michael@0: } michael@0: michael@0: double ConeOuterAngle() const michael@0: { michael@0: return mConeOuterAngle; michael@0: } michael@0: void SetConeOuterAngle(double aConeOuterAngle) michael@0: { michael@0: if (WebAudioUtils::FuzzyEqual(mConeOuterAngle, aConeOuterAngle)) { michael@0: return; michael@0: } michael@0: mConeOuterAngle = aConeOuterAngle; michael@0: SendDoubleParameterToStream(CONE_OUTER_ANGLE, mConeOuterAngle); michael@0: } michael@0: michael@0: double ConeOuterGain() const michael@0: { michael@0: return mConeOuterGain; michael@0: } michael@0: void SetConeOuterGain(double aConeOuterGain) michael@0: { michael@0: if (WebAudioUtils::FuzzyEqual(mConeOuterGain, aConeOuterGain)) { michael@0: return; michael@0: } michael@0: mConeOuterGain = aConeOuterGain; michael@0: SendDoubleParameterToStream(CONE_OUTER_GAIN, mConeOuterGain); michael@0: } michael@0: michael@0: float ComputeDopplerShift(); michael@0: void SendDopplerToSourcesIfNeeded(); michael@0: void FindConnectedSources(); michael@0: void FindConnectedSources(AudioNode* aNode, nsTArray& aSources, std::set& aSeenNodes); michael@0: michael@0: virtual const char* NodeType() const michael@0: { michael@0: return "PannerNode"; michael@0: } michael@0: michael@0: virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE; michael@0: virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE; michael@0: michael@0: private: michael@0: friend class AudioListener; michael@0: friend class PannerNodeEngine; michael@0: enum EngineParameters { michael@0: LISTENER_POSITION, michael@0: LISTENER_FRONT_VECTOR, // unit length michael@0: LISTENER_RIGHT_VECTOR, // unit length, orthogonal to LISTENER_FRONT_VECTOR michael@0: LISTENER_VELOCITY, michael@0: LISTENER_DOPPLER_FACTOR, michael@0: LISTENER_SPEED_OF_SOUND, michael@0: PANNING_MODEL, michael@0: DISTANCE_MODEL, michael@0: POSITION, michael@0: ORIENTATION, // unit length or zero michael@0: VELOCITY, michael@0: REF_DISTANCE, michael@0: MAX_DISTANCE, michael@0: ROLLOFF_FACTOR, michael@0: CONE_INNER_ANGLE, michael@0: CONE_OUTER_ANGLE, michael@0: CONE_OUTER_GAIN michael@0: }; michael@0: michael@0: private: michael@0: PanningModelType mPanningModel; michael@0: DistanceModelType mDistanceModel; michael@0: ThreeDPoint mPosition; michael@0: ThreeDPoint mOrientation; michael@0: ThreeDPoint mVelocity; michael@0: double mRefDistance; michael@0: double mMaxDistance; michael@0: double mRolloffFactor; michael@0: double mConeInnerAngle; michael@0: double mConeOuterAngle; michael@0: double mConeOuterGain; michael@0: michael@0: // An array of all the AudioBufferSourceNode connected directly or indirectly michael@0: // to this AudioPannerNode. michael@0: nsTArray mSources; michael@0: }; michael@0: michael@0: } michael@0: } michael@0: michael@0: #endif michael@0: