--- a/dom/media/webaudio/AudioBufferSourceNode.cpp
+++ b/dom/media/webaudio/AudioBufferSourceNode.cpp
@@ -664,19 +664,16 @@ AudioBufferSourceNode::Create(JSContext*
void
AudioBufferSourceNode::DestroyMediaStream()
{
bool hadStream = mStream;
if (hadStream) {
mStream->RemoveMainThreadListener(this);
}
AudioNode::DestroyMediaStream();
- if (hadStream && Context()) {
- Context()->UnregisterAudioBufferSourceNode(this);
- }
}
size_t
AudioBufferSourceNode::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
{
size_t amount = AudioNode::SizeOfExcludingThis(aMallocSizeOf);
/* mBuffer can be shared and is accounted for separately. */
--- a/dom/media/webaudio/AudioContext.cpp
+++ b/dom/media/webaudio/AudioContext.cpp
@@ -88,17 +88,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Au
NS_IMPL_CYCLE_COLLECTION_UNLINK(mListener)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPromiseGripArray)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingResumePromises)
if (!tmp->mIsStarted) {
NS_IMPL_CYCLE_COLLECTION_UNLINK(mActiveNodes)
}
// mDecodeJobs owns the WebAudioDecodeJob objects whose lifetime is managed explicitly.
// mAllNodes is an array of weak pointers, ignore it here.
- // mPannerNodes is an array of weak pointers, ignore it here.
// mBasicWaveFormCache cannot participate in cycles, ignore it here.
// Remove weak reference on the global window as the context is not usable
// without mDestination.
tmp->DisconnectFromWindow();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(AudioContext,
@@ -109,17 +108,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingResumePromises)
if (!tmp->mIsStarted) {
MOZ_ASSERT(tmp->mIsOffline,
"Online AudioContexts should always be started");
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mActiveNodes)
}
// mDecodeJobs owns the WebAudioDecodeJob objects whose lifetime is managed explicitly.
// mAllNodes is an array of weak pointers, ignore it here.
- // mPannerNodes is an array of weak pointers, ignore it here.
// mBasicWaveFormCache cannot participate in cycles, ignore it here.
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_ADDREF_INHERITED(AudioContext, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(AudioContext, DOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AudioContext)
NS_INTERFACE_MAP_ENTRY(nsIMemoryReporter)
@@ -650,39 +648,16 @@ AudioContext::RegisterActiveNode(AudioNo
}
void
AudioContext::UnregisterActiveNode(AudioNode* aNode)
{
mActiveNodes.RemoveEntry(aNode);
}
-void
-AudioContext::UnregisterAudioBufferSourceNode(AudioBufferSourceNode* aNode)
-{
- UpdatePannerSource();
-}
-
-void
-AudioContext::UnregisterPannerNode(PannerNode* aNode)
-{
- mPannerNodes.RemoveEntry(aNode);
- if (mListener) {
- mListener->UnregisterPannerNode(aNode);
- }
-}
-
-void
-AudioContext::UpdatePannerSource()
-{
- for (auto iter = mPannerNodes.Iter(); !iter.Done(); iter.Next()) {
- iter.Get()->GetKey()->FindConnectedSources();
- }
-}
-
uint32_t
AudioContext::MaxChannelCount() const
{
return std::min<uint32_t>(WebAudioUtils::MaxChannelCount,
mIsOffline ? mNumberOfChannels : CubebUtils::MaxNumberOfChannels());
}
uint32_t
@@ -1197,17 +1172,16 @@ AudioContext::SizeOfIncludingThis(mozill
if (mListener) {
amount += mListener->SizeOfIncludingThis(aMallocSizeOf);
}
amount += mDecodeJobs.ShallowSizeOfExcludingThis(aMallocSizeOf);
for (uint32_t i = 0; i < mDecodeJobs.Length(); ++i) {
amount += mDecodeJobs[i]->SizeOfIncludingThis(aMallocSizeOf);
}
amount += mActiveNodes.ShallowSizeOfExcludingThis(aMallocSizeOf);
- amount += mPannerNodes.ShallowSizeOfExcludingThis(aMallocSizeOf);
return amount;
}
NS_IMETHODIMP
AudioContext::CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData, bool aAnonymize)
{
const nsLiteralCString
--- a/dom/media/webaudio/AudioContext.h
+++ b/dom/media/webaudio/AudioContext.h
@@ -304,20 +304,16 @@ public:
// Nodes unregister when they have finished producing sound for the
// foreseeable future.
// Do NOT call UnregisterActiveNode from an AudioNode destructor.
// If the destructor is called, then the Node has already been unregistered.
// The destructor may be called during hashtable enumeration, during which
// unregistering would not be safe.
void UnregisterActiveNode(AudioNode* aNode);
- void UnregisterAudioBufferSourceNode(AudioBufferSourceNode* aNode);
- void UnregisterPannerNode(PannerNode* aNode);
- void UpdatePannerSource();
-
uint32_t MaxChannelCount() const;
uint32_t ActiveNodeCount() const;
void Mute() const;
void Unmute() const;
JSObject* GetGlobalJSObject() const;
@@ -366,19 +362,16 @@ private:
// is not allowed to play, the promise would be pending in this array and be
// resolved until audio context has been allowed and user call resume() again.
nsTArray<RefPtr<Promise>> mPendingResumePromises;
// See RegisterActiveNode. These will keep the AudioContext alive while it
// is rendering and the window remains alive.
nsTHashtable<nsRefPtrHashKey<AudioNode> > mActiveNodes;
// Raw (non-owning) references to all AudioNodes for this AudioContext.
nsTHashtable<nsPtrHashKey<AudioNode> > mAllNodes;
- // Hashsets containing all the PannerNodes, to compute the doppler shift.
- // These are weak pointers.
- nsTHashtable<nsPtrHashKey<PannerNode> > mPannerNodes;
// Cache to avoid recomputing basic waveforms all the time.
RefPtr<BasicWaveFormCache> mBasicWaveFormCache;
// Number of channels passed in the OfflineAudioContext ctor.
uint32_t mNumberOfChannels;
bool mIsOffline;
bool mIsStarted;
bool mIsShutDown;
// Close has been called, reject suspend and resume call.
--- a/dom/media/webaudio/AudioListener.cpp
+++ b/dom/media/webaudio/AudioListener.cpp
@@ -16,19 +16,16 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Au
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(AudioListener, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AudioListener, Release)
AudioListener::AudioListener(AudioContext* aContext)
: mContext(aContext)
, mPosition()
, mFrontVector(0., 0., -1.)
, mRightVector(1., 0., 0.)
- , mVelocity()
- , mDopplerFactor(1.)
- , mSpeedOfSound(343.3) // meters/second
{
MOZ_ASSERT(aContext);
}
JSObject*
AudioListener::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return AudioListener_Binding::Wrap(aCx, this, aGivenProto);
@@ -55,77 +52,23 @@ AudioListener::SetOrientation(double aX,
ThreeDPoint right = front.CrossProduct(up);
if (right.IsZero()) {
return;
}
right.Normalize();
if (!mFrontVector.FuzzyEqual(front)) {
mFrontVector = front;
- SendThreeDPointParameterToStream(PannerNode::LISTENER_FRONT_VECTOR, front);
}
if (!mRightVector.FuzzyEqual(right)) {
mRightVector = right;
- SendThreeDPointParameterToStream(PannerNode::LISTENER_RIGHT_VECTOR, right);
- }
-}
-
-void
-AudioListener::RegisterPannerNode(PannerNode* aPannerNode)
-{
- mPanners.AppendElement(aPannerNode);
-
- // Let the panner node know about our parameters
- aPannerNode->SendThreeDPointParameterToStream(PannerNode::LISTENER_POSITION, mPosition);
- aPannerNode->SendThreeDPointParameterToStream(PannerNode::LISTENER_FRONT_VECTOR, mFrontVector);
- aPannerNode->SendThreeDPointParameterToStream(PannerNode::LISTENER_RIGHT_VECTOR, mRightVector);
- aPannerNode->SendThreeDPointParameterToStream(PannerNode::LISTENER_VELOCITY, mVelocity);
- aPannerNode->SendDoubleParameterToStream(PannerNode::LISTENER_DOPPLER_FACTOR, mDopplerFactor);
- aPannerNode->SendDoubleParameterToStream(PannerNode::LISTENER_SPEED_OF_SOUND, mSpeedOfSound);
- UpdatePannersVelocity();
-}
-
-void AudioListener::UnregisterPannerNode(PannerNode* aPannerNode)
-{
- mPanners.RemoveElement(aPannerNode);
-}
-
-void
-AudioListener::SendDoubleParameterToStream(uint32_t aIndex, double aValue)
-{
- for (uint32_t i = 0; i < mPanners.Length(); ++i) {
- if (mPanners[i]) {
- mPanners[i]->SendDoubleParameterToStream(aIndex, aValue);
- }
- }
-}
-
-void
-AudioListener::SendThreeDPointParameterToStream(uint32_t aIndex, const ThreeDPoint& aValue)
-{
- for (uint32_t i = 0; i < mPanners.Length(); ++i) {
- if (mPanners[i]) {
- mPanners[i]->SendThreeDPointParameterToStream(aIndex, aValue);
- }
- }
-}
-
-void AudioListener::UpdatePannersVelocity()
-{
- for (uint32_t i = 0; i < mPanners.Length(); ++i) {
- if (mPanners[i]) {
- mPanners[i]->SendDopplerToSourcesIfNeeded();
- }
}
}
size_t
AudioListener::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
{
- size_t amount = aMallocSizeOf(this);
- // AudioNodes are tracked separately
- amount += mPanners.ShallowSizeOfExcludingThis(aMallocSizeOf);
- return amount;
+ return aMallocSizeOf(this);
}
} // namespace dom
} // namespace mozilla
--- a/dom/media/webaudio/AudioListener.h
+++ b/dom/media/webaudio/AudioListener.h
@@ -33,101 +33,53 @@ public:
AudioContext* GetParentObject() const
{
return mContext;
}
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
- double DopplerFactor() const
- {
- return mDopplerFactor;
- }
- void SetDopplerFactor(double aDopplerFactor)
- {
- if (WebAudioUtils::FuzzyEqual(mDopplerFactor, aDopplerFactor)) {
- return;
- }
- mDopplerFactor = aDopplerFactor;
- SendDoubleParameterToStream(PannerNode::LISTENER_DOPPLER_FACTOR, mDopplerFactor);
- }
-
- double SpeedOfSound() const
- {
- return mSpeedOfSound;
- }
- void SetSpeedOfSound(double aSpeedOfSound)
- {
- if (WebAudioUtils::FuzzyEqual(mSpeedOfSound, aSpeedOfSound)) {
- return;
- }
- mSpeedOfSound = aSpeedOfSound;
- SendDoubleParameterToStream(PannerNode::LISTENER_SPEED_OF_SOUND, mSpeedOfSound);
- }
-
void SetPosition(double aX, double aY, double aZ)
{
if (WebAudioUtils::FuzzyEqual(mPosition.x, aX) &&
WebAudioUtils::FuzzyEqual(mPosition.y, aY) &&
WebAudioUtils::FuzzyEqual(mPosition.z, aZ)) {
return;
}
mPosition.x = aX;
mPosition.y = aY;
mPosition.z = aZ;
- SendThreeDPointParameterToStream(PannerNode::LISTENER_POSITION, mPosition);
}
const ThreeDPoint& Position() const
{
return mPosition;
}
void SetOrientation(double aX, double aY, double aZ,
double aXUp, double aYUp, double aZUp);
- const ThreeDPoint& Velocity() const
- {
- return mVelocity;
+ const ThreeDPoint& FrontVector() {
+ return mFrontVector;
}
- void SetVelocity(double aX, double aY, double aZ)
- {
- if (WebAudioUtils::FuzzyEqual(mVelocity.x, aX) &&
- WebAudioUtils::FuzzyEqual(mVelocity.y, aY) &&
- WebAudioUtils::FuzzyEqual(mVelocity.z, aZ)) {
- return;
- }
- mVelocity.x = aX;
- mVelocity.y = aY;
- mVelocity.z = aZ;
- SendThreeDPointParameterToStream(PannerNode::LISTENER_VELOCITY, mVelocity);
- UpdatePannersVelocity();
+ const ThreeDPoint& RightVector() {
+ return mRightVector;
}
- void RegisterPannerNode(PannerNode* aPannerNode);
- void UnregisterPannerNode(PannerNode* aPannerNode);
-
private:
~AudioListener() {}
- void SendDoubleParameterToStream(uint32_t aIndex, double aValue);
void SendThreeDPointParameterToStream(uint32_t aIndex, const ThreeDPoint& aValue);
- void UpdatePannersVelocity();
-
private:
friend class PannerNode;
RefPtr<AudioContext> mContext;
ThreeDPoint mPosition;
ThreeDPoint mFrontVector;
ThreeDPoint mRightVector;
- ThreeDPoint mVelocity;
- double mDopplerFactor;
- double mSpeedOfSound;
- nsTArray<WeakPtr<PannerNode> > mPanners;
};
} // namespace dom
} // namespace mozilla
#endif
--- a/dom/media/webaudio/AudioNode.cpp
+++ b/dom/media/webaudio/AudioNode.cpp
@@ -239,19 +239,16 @@ AudioNode::Connect(AudioNode& aDestinati
MOZ_ASSERT(aOutput <= UINT16_MAX, "Unexpected large output port number");
input->mStreamPort = destinationStream->
AllocateInputPort(mStream, AudioNodeStream::AUDIO_TRACK, TRACK_ANY,
static_cast<uint16_t>(aInput),
static_cast<uint16_t>(aOutput));
}
aDestination.NotifyInputsChanged();
- // This connection may have connected a panner and a source.
- Context()->UpdatePannerSource();
-
return &aDestination;
}
void
AudioNode::Connect(AudioParam& aDestination, uint32_t aOutput,
ErrorResult& aRv)
{
if (aOutput >= NumberOfOutputs()) {
@@ -449,19 +446,16 @@ AudioNode::Disconnect(ErrorResult& aRv)
for (int32_t outputIndex = mOutputParams.Length() - 1;
outputIndex >= 0; --outputIndex) {
DisconnectMatchingDestinationInputs<AudioParam>(outputIndex,
[](const InputNode&) {
return true;
});
}
-
- // This disconnection may have disconnected a panner and a source.
- Context()->UpdatePannerSource();
}
void
AudioNode::Disconnect(uint32_t aOutput, ErrorResult& aRv)
{
if (aOutput >= NumberOfOutputs()) {
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
return;
@@ -479,19 +473,16 @@ AudioNode::Disconnect(uint32_t aOutput,
for (int32_t outputIndex = mOutputParams.Length() - 1;
outputIndex >= 0; --outputIndex) {
DisconnectMatchingDestinationInputs<AudioParam>(
outputIndex,
[aOutput](const InputNode& aInputNode) {
return aInputNode.mOutputPort == aOutput;
});
}
-
- // This disconnection may have disconnected a panner and a source.
- Context()->UpdatePannerSource();
}
void
AudioNode::Disconnect(AudioNode& aDestination, ErrorResult& aRv)
{
bool wasConnected = false;
for (int32_t outputIndex = mOutputNodes.Length() - 1;
@@ -505,19 +496,16 @@ AudioNode::Disconnect(AudioNode& aDestin
return true;
});
}
if (!wasConnected) {
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
return;
}
-
- // This disconnection may have disconnected a panner and a source.
- Context()->UpdatePannerSource();
}
void
AudioNode::Disconnect(AudioNode& aDestination,
uint32_t aOutput,
ErrorResult& aRv)
{
if (aOutput >= NumberOfOutputs()) {
@@ -539,19 +527,16 @@ AudioNode::Disconnect(AudioNode& aDestin
return aInputNode.mOutputPort == aOutput;
});
}
if (!wasConnected) {
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
return;
}
-
- // This disconnection may have disconnected a panner and a source.
- Context()->UpdatePannerSource();
}
void
AudioNode::Disconnect(AudioNode& aDestination,
uint32_t aOutput,
uint32_t aInput,
ErrorResult& aRv)
{
@@ -580,19 +565,16 @@ AudioNode::Disconnect(AudioNode& aDestin
aInputNode.mInputPort == aInput;
});
}
if (!wasConnected) {
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
return;
}
-
- // This disconnection may have disconnected a panner and a source.
- Context()->UpdatePannerSource();
}
void
AudioNode::Disconnect(AudioParam& aDestination, ErrorResult& aRv)
{
bool wasConnected = false;
for (int32_t outputIndex = mOutputParams.Length() - 1;
--- a/dom/media/webaudio/PannerNode.cpp
+++ b/dom/media/webaudio/PannerNode.cpp
@@ -22,57 +22,50 @@ using WebCore::HRTFPanner;
namespace mozilla {
namespace dom {
using namespace std;
NS_IMPL_CYCLE_COLLECTION_CLASS(PannerNode)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PannerNode, AudioNode)
- if (tmp->Context()) {
- tmp->Context()->UnregisterPannerNode(tmp);
- }
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPositionX, mPositionY, mPositionZ, mOrientationX, mOrientationY, mOrientationZ)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PannerNode, AudioNode)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPositionX, mPositionY, mPositionZ, mOrientationX, mOrientationY, mOrientationZ)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PannerNode)
NS_INTERFACE_MAP_END_INHERITING(AudioNode)
NS_IMPL_ADDREF_INHERITED(PannerNode, AudioNode)
NS_IMPL_RELEASE_INHERITED(PannerNode, AudioNode)
class PannerNodeEngine final : public AudioNodeEngine
{
public:
- explicit PannerNodeEngine(AudioNode* aNode, AudioDestinationNode* aDestination)
+ explicit PannerNodeEngine(AudioNode* aNode, AudioDestinationNode* aDestination, AudioListener* aListener)
: AudioNodeEngine(aNode)
, mDestination(aDestination->Stream())
+ , mListener(aListener)
// Please keep these default values consistent with PannerNode::PannerNode below.
, mPanningModelFunction(&PannerNodeEngine::EqualPowerPanningFunction)
, mDistanceModelFunction(&PannerNodeEngine::InverseGainFunction)
, mPositionX(0.)
, mPositionY(0.)
, mPositionZ(0.)
, mOrientationX(1.)
, mOrientationY(0.)
, mOrientationZ(0.)
- , mVelocity()
, mRefDistance(1.)
, mMaxDistance(10000.)
, mRolloffFactor(1.)
, mConeInnerAngle(360.)
, mConeOuterAngle(360.)
, mConeOuterGain(0.)
- // These will be initialized when a PannerNode is created, so just initialize them
- // to some dummy values here.
- , mListenerDopplerFactor(0.)
- , mListenerSpeedOfSound(0.)
, mLeftOverData(INT_MIN)
{
}
void RecvTimelineEvent(uint32_t aIndex, AudioTimelineEvent& aEvent) override
{
MOZ_ASSERT(mDestination);
WebAudioUtils::ConvertAudioTimelineEventToTicks(aEvent,
@@ -147,40 +140,33 @@ public:
break;
default:
NS_ERROR("Bad PannerNodeEngine Int32Parameter");
}
}
void SetThreeDPointParameter(uint32_t aIndex, const ThreeDPoint& aParam) override
{
switch (aIndex) {
- case PannerNode::LISTENER_POSITION: mListenerPosition = aParam; break;
- case PannerNode::LISTENER_FRONT_VECTOR: mListenerFrontVector = aParam; break;
- case PannerNode::LISTENER_RIGHT_VECTOR: mListenerRightVector = aParam; break;
- case PannerNode::LISTENER_VELOCITY: mListenerVelocity = aParam; break;
case PannerNode::POSITION:
mPositionX.SetValue(aParam.x);
mPositionY.SetValue(aParam.y);
mPositionZ.SetValue(aParam.z);
break;
case PannerNode::ORIENTATION:
mOrientationX.SetValue(aParam.x);
mOrientationY.SetValue(aParam.y);
mOrientationZ.SetValue(aParam.z);
break;
- case PannerNode::VELOCITY: mVelocity = aParam; break;
default:
NS_ERROR("Bad PannerNodeEngine ThreeDPointParameter");
}
}
void SetDoubleParameter(uint32_t aIndex, double aParam) override
{
switch (aIndex) {
- case PannerNode::LISTENER_DOPPLER_FACTOR: mListenerDopplerFactor = aParam; break;
- case PannerNode::LISTENER_SPEED_OF_SOUND: mListenerSpeedOfSound = aParam; break;
case PannerNode::REF_DISTANCE: mRefDistance = aParam; break;
case PannerNode::MAX_DISTANCE: mMaxDistance = aParam; break;
case PannerNode::ROLLOFF_FACTOR: mRolloffFactor = aParam; break;
case PannerNode::CONE_INNER_ANGLE: mConeInnerAngle = aParam; break;
case PannerNode::CONE_OUTER_ANGLE: mConeOuterAngle = aParam; break;
case PannerNode::CONE_OUTER_GAIN: mConeOuterGain = aParam; break;
default:
NS_ERROR("Bad PannerNodeEngine DoubleParameter");
@@ -262,39 +248,33 @@ public:
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
}
RefPtr<AudioNodeStream> mDestination;
// This member is set on the main thread, but is not accessed on the rendering
// thread untile mPanningModelFunction has changed, and this happens strictly
// later, via a MediaStreamGraph ControlMessage.
nsAutoPtr<HRTFPanner> mHRTFPanner;
+ RefPtr<AudioListener> mListener;
typedef void (PannerNodeEngine::*PanningModelFunction)(const AudioBlock& aInput, AudioBlock* aOutput, StreamTime tick);
PanningModelFunction mPanningModelFunction;
typedef float (PannerNodeEngine::*DistanceModelFunction)(double aDistance);
DistanceModelFunction mDistanceModelFunction;
AudioParamTimeline mPositionX;
AudioParamTimeline mPositionY;
AudioParamTimeline mPositionZ;
AudioParamTimeline mOrientationX;
AudioParamTimeline mOrientationY;
AudioParamTimeline mOrientationZ;
- ThreeDPoint mVelocity;
double mRefDistance;
double mMaxDistance;
double mRolloffFactor;
double mConeInnerAngle;
double mConeOuterAngle;
double mConeOuterGain;
- ThreeDPoint mListenerPosition;
- ThreeDPoint mListenerFrontVector;
- ThreeDPoint mListenerRightVector;
- ThreeDPoint mListenerVelocity;
- double mListenerDopplerFactor;
- double mListenerSpeedOfSound;
int mLeftOverData;
};
PannerNode::PannerNode(AudioContext* aContext)
: AudioNode(aContext,
2,
ChannelCountMode::Clamped_max,
ChannelInterpretation::Speakers)
@@ -302,38 +282,31 @@ PannerNode::PannerNode(AudioContext* aCo
, mPanningModel(PanningModelType::Equalpower)
, mDistanceModel(DistanceModelType::Inverse)
, mPositionX(new AudioParam(this, PannerNode::POSITIONX, this->NodeType(), 0.f))
, mPositionY(new AudioParam(this, PannerNode::POSITIONY, this->NodeType(), 0.f))
, mPositionZ(new AudioParam(this, PannerNode::POSITIONZ, this->NodeType(), 0.f))
, mOrientationX(new AudioParam(this, PannerNode::ORIENTATIONX, this->NodeType(), 1.0f))
, mOrientationY(new AudioParam(this, PannerNode::ORIENTATIONY, this->NodeType(), 0.f))
, mOrientationZ(new AudioParam(this, PannerNode::ORIENTATIONZ, this->NodeType(), 0.f))
- , mVelocity()
, mRefDistance(1.)
, mMaxDistance(10000.)
, mRolloffFactor(1.)
, mConeInnerAngle(360.)
, mConeOuterAngle(360.)
, mConeOuterGain(0.)
{
mStream = AudioNodeStream::Create(aContext,
- new PannerNodeEngine(this, aContext->Destination()),
+ new PannerNodeEngine(this, aContext->Destination(), aContext->Listener()),
AudioNodeStream::NO_STREAM_FLAGS,
aContext->Graph());
- // We should register once we have set up our stream and engine.
- Context()->Listener()->RegisterPannerNode(this);
}
PannerNode::~PannerNode()
-{
- if (Context()) {
- Context()->UnregisterPannerNode(this);
- }
-}
+{ }
/* static */ already_AddRefed<PannerNode>
PannerNode::Create(AudioContext& aAudioContext,
const PannerOptions& aOptions,
ErrorResult& aRv)
{
if (aAudioContext.CheckClosed(aRv)) {
return nullptr;
@@ -372,38 +345,33 @@ void PannerNode::SetPanningModel(Panning
static_cast<PannerNodeEngine*>(mStream->Engine())->CreateHRTFPanner();
}
SendInt32ParameterToStream(PANNING_MODEL, int32_t(mPanningModel));
}
size_t
PannerNode::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
{
- size_t amount = AudioNode::SizeOfExcludingThis(aMallocSizeOf);
- amount += mSources.ShallowSizeOfExcludingThis(aMallocSizeOf);
- return amount;
+ return AudioNode::SizeOfExcludingThis(aMallocSizeOf);
}
size_t
PannerNode::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
{
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
}
JSObject*
PannerNode::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return PannerNode_Binding::Wrap(aCx, this, aGivenProto);
}
void PannerNode::DestroyMediaStream()
{
- if (Context()) {
- Context()->UnregisterPannerNode(this);
- }
AudioNode::DestroyMediaStream();
}
// Those three functions are described in the spec.
float
PannerNodeEngine::LinearGainFunction(double aDistance)
{
return 1 - mRolloffFactor * (std::max(std::min(aDistance, mMaxDistance), mRefDistance) - mRefDistance) / (mMaxDistance - mRefDistance);
@@ -472,20 +440,21 @@ PannerNodeEngine::EqualPowerPanningFunct
mOrientationZ.HasSimpleValue()) {
ThreeDPoint position = ConvertAudioParamTimelineTo3DP(mPositionX, mPositionY, mPositionZ, tick);
ThreeDPoint orientation = ConvertAudioParamTimelineTo3DP(mOrientationX, mOrientationY, mOrientationZ, tick);
if (!orientation.IsZero()) {
orientation.Normalize();
}
+
// For a stereo source, when both the listener and the panner are in
// the same spot, and no cone gain is specified, this node is noop.
if (inputChannels == 2 &&
- mListenerPosition == position &&
+ mListener->Position() == position &&
mConeInnerAngle == 360 &&
mConeOuterAngle == 360) {
*aOutput = aInput;
return;
}
// The output of this node is always stereo, no matter what the inputs are.
aOutput->AllocateChannels(2);
@@ -636,28 +605,28 @@ PannerNodeEngine::EqualPowerPanningFunct
AudioBlockInPlaceScale(outputR, alignedGain);
}
}
// This algorithm is specified in the webaudio spec.
void
PannerNodeEngine::ComputeAzimuthAndElevation(const ThreeDPoint& position, float& aAzimuth, float& aElevation)
{
- ThreeDPoint sourceListener = position - mListenerPosition;
+ ThreeDPoint sourceListener = position - mListener->Position();
if (sourceListener.IsZero()) {
aAzimuth = 0.0;
aElevation = 0.0;
return;
}
sourceListener.Normalize();
// Project the source-listener vector on the x-z plane.
- const ThreeDPoint& listenerFront = mListenerFrontVector;
- const ThreeDPoint& listenerRight = mListenerRightVector;
+ const ThreeDPoint& listenerFront = mListener->FrontVector();
+ const ThreeDPoint& listenerRight = mListener->RightVector();
ThreeDPoint up = listenerRight.CrossProduct(listenerFront);
double upProjection = sourceListener.DotProduct(up);
aElevation = 90 - 180 * acos(upProjection) / M_PI;
if (aElevation > 90) {
aElevation = 180 - aElevation;
} else if (aElevation < -90) {
@@ -696,17 +665,17 @@ PannerNodeEngine::ComputeConeGain(const
const ThreeDPoint& orientation)
{
// Omnidirectional source
if (orientation.IsZero() || ((mConeInnerAngle == 360) && (mConeOuterAngle == 360))) {
return 1;
}
// Normalized source-listener vector
- ThreeDPoint sourceToListener = mListenerPosition - position;
+ ThreeDPoint sourceToListener = mListener->Position() - position;
sourceToListener.Normalize();
// Angle between the source orientation vector and the source-listener vector
double dotProduct = sourceToListener.DotProduct(orientation);
double angle = 180 * acos(dotProduct) / M_PI;
double absAngle = fabs(angle);
// Divide by 2 here since API is entire angle (not half-angle)
@@ -728,103 +697,15 @@ PannerNodeEngine::ComputeConeGain(const
}
return gain;
}
double
PannerNodeEngine::ComputeDistanceGain(const ThreeDPoint& position)
{
- ThreeDPoint distanceVec = position - mListenerPosition;
+ ThreeDPoint distanceVec = position - mListener->Position();
float distance = sqrt(distanceVec.DotProduct(distanceVec));
return std::max(0.0f, (this->*mDistanceModelFunction)(distance));
}
-float
-PannerNode::ComputeDopplerShift()
-{
- double dopplerShift = 1.0; // Initialize to default value
-
- AudioListener* listener = Context()->Listener();
-
- if (listener->DopplerFactor() > 0) {
- // Don't bother if both source and listener have no velocity.
- if (!mVelocity.IsZero() || !listener->Velocity().IsZero()) {
- // Calculate the source to listener vector.
- ThreeDPoint sourceToListener = ConvertAudioParamTo3DP(mPositionX, mPositionY, mPositionZ) - listener->Velocity();
-
- double sourceListenerMagnitude = sourceToListener.Magnitude();
-
- double listenerProjection = sourceToListener.DotProduct(listener->Velocity()) / sourceListenerMagnitude;
- double sourceProjection = sourceToListener.DotProduct(mVelocity) / sourceListenerMagnitude;
-
- listenerProjection = -listenerProjection;
- sourceProjection = -sourceProjection;
-
- double scaledSpeedOfSound = listener->SpeedOfSound() / listener->DopplerFactor();
- listenerProjection = min(listenerProjection, scaledSpeedOfSound);
- sourceProjection = min(sourceProjection, scaledSpeedOfSound);
-
- dopplerShift = ((listener->SpeedOfSound() - listener->DopplerFactor() * listenerProjection) / (listener->SpeedOfSound() - listener->DopplerFactor() * sourceProjection));
-
- WebAudioUtils::FixNaN(dopplerShift); // Avoid illegal values
-
- // Limit the pitch shifting to 4 octaves up and 3 octaves down.
- dopplerShift = min(dopplerShift, 16.);
- dopplerShift = max(dopplerShift, 0.125);
- }
- }
-
- return dopplerShift;
-}
-
-void
-PannerNode::FindConnectedSources()
-{
- mSources.Clear();
- std::set<AudioNode*> cycleSet;
- FindConnectedSources(this, mSources, cycleSet);
-}
-
-void
-PannerNode::FindConnectedSources(AudioNode* aNode,
- nsTArray<AudioBufferSourceNode*>& aSources,
- std::set<AudioNode*>& aNodesSeen)
-{
- if (!aNode) {
- return;
- }
-
- const nsTArray<InputNode>& inputNodes = aNode->InputNodes();
-
- for(unsigned i = 0; i < inputNodes.Length(); i++) {
- // Return if we find a node that we have seen already.
- if (aNodesSeen.find(inputNodes[i].mInputNode) != aNodesSeen.end()) {
- return;
- }
- aNodesSeen.insert(inputNodes[i].mInputNode);
- // Recurse
- FindConnectedSources(inputNodes[i].mInputNode, aSources, aNodesSeen);
-
- // Check if this node is an AudioBufferSourceNode that still have a stream,
- // which means it has not finished playing.
- AudioBufferSourceNode* node = inputNodes[i].mInputNode->AsAudioBufferSourceNode();
- if (node && node->GetStream()) {
- aSources.AppendElement(node);
- }
- }
-}
-
-void
-PannerNode::SendDopplerToSourcesIfNeeded()
-{
- // Don't bother sending the doppler shift if both the source and the listener
- // are not moving, because the doppler shift is going to be 1.0.
- if (!(Context()->Listener()->Velocity().IsZero() && mVelocity.IsZero())) {
- for(uint32_t i = 0; i < mSources.Length(); i++) {
- mSources[i]->SendDopplerShiftToStream(ComputeDopplerShift());
- }
- }
-}
-
-
} // namespace dom
} // namespace mozilla
--- a/dom/media/webaudio/PannerNode.h
+++ b/dom/media/webaudio/PannerNode.h
@@ -100,30 +100,16 @@ public:
return;
}
mOrientationX->SetValue(aX);
mOrientationY->SetValue(aY);
mOrientationZ->SetValue(aZ);
SendThreeDPointParameterToStream(ORIENTATION, ConvertAudioParamTo3DP(mOrientationX, mOrientationY, mOrientationZ));
}
- void SetVelocity(double aX, double aY, double aZ)
- {
- if (WebAudioUtils::FuzzyEqual(mVelocity.x, aX) &&
- WebAudioUtils::FuzzyEqual(mVelocity.y, aY) &&
- WebAudioUtils::FuzzyEqual(mVelocity.z, aZ)) {
- return;
- }
- mVelocity.x = aX;
- mVelocity.y = aY;
- mVelocity.z = aZ;
- SendThreeDPointParameterToStream(VELOCITY, mVelocity);
- SendDopplerToSourcesIfNeeded();
- }
-
double RefDistance() const
{
return mRefDistance;
}
void SetRefDistance(double aRefDistance)
{
if (WebAudioUtils::FuzzyEqual(mRefDistance, aRefDistance)) {
return;
@@ -222,54 +208,41 @@ public:
return mOrientationY;
}
AudioParam* OrientationZ()
{
return mOrientationZ;
}
-
- float ComputeDopplerShift();
- void SendDopplerToSourcesIfNeeded();
- void FindConnectedSources();
- void FindConnectedSources(AudioNode* aNode, nsTArray<AudioBufferSourceNode*>& aSources, std::set<AudioNode*>& aSeenNodes);
-
const char* NodeType() const override
{
return "PannerNode";
}
size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override;
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override;
private:
explicit PannerNode(AudioContext* aContext);
~PannerNode();
friend class AudioListener;
friend class PannerNodeEngine;
enum EngineParameters {
- LISTENER_POSITION,
- LISTENER_FRONT_VECTOR, // unit length
- LISTENER_RIGHT_VECTOR, // unit length, orthogonal to LISTENER_FRONT_VECTOR
- LISTENER_VELOCITY,
- LISTENER_DOPPLER_FACTOR,
- LISTENER_SPEED_OF_SOUND,
PANNING_MODEL,
DISTANCE_MODEL,
POSITION,
POSITIONX,
POSITIONY,
POSITIONZ,
ORIENTATION, // unit length or zero
ORIENTATIONX,
ORIENTATIONY,
ORIENTATIONZ,
- VELOCITY,
REF_DISTANCE,
MAX_DISTANCE,
ROLLOFF_FACTOR,
CONE_INNER_ANGLE,
CONE_OUTER_ANGLE,
CONE_OUTER_GAIN
};
@@ -281,26 +254,21 @@ private:
PanningModelType mPanningModel;
DistanceModelType mDistanceModel;
RefPtr<AudioParam> mPositionX;
RefPtr<AudioParam> mPositionY;
RefPtr<AudioParam> mPositionZ;
RefPtr<AudioParam> mOrientationX;
RefPtr<AudioParam> mOrientationY;
RefPtr<AudioParam> mOrientationZ;
- ThreeDPoint mVelocity;
double mRefDistance;
double mMaxDistance;
double mRolloffFactor;
double mConeInnerAngle;
double mConeOuterAngle;
double mConeOuterGain;
-
- // An array of all the AudioBufferSourceNode connected directly or indirectly
- // to this AudioPannerNode.
- nsTArray<AudioBufferSourceNode*> mSources;
};
} // namespace dom
} // namespace mozilla
#endif
--- a/dom/webidl/AudioListener.webidl
+++ b/dom/webidl/AudioListener.webidl
@@ -7,25 +7,13 @@
* https://webaudio.github.io/web-audio-api/
*
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* liability, trademark and document use rules apply.
*/
[Pref="dom.webaudio.enabled"]
interface AudioListener {
-
- // same as OpenAL (default 1)
- [Deprecated="PannerNodeDoppler"]
- attribute double dopplerFactor;
-
- // in meters / second (default 343.3)
- [Deprecated="PannerNodeDoppler"]
- attribute double speedOfSound;
-
// Uses a 3D cartesian coordinate system
void setPosition(double x, double y, double z);
void setOrientation(double x, double y, double z, double xUp, double yUp, double zUp);
- [Deprecated="PannerNodeDoppler"]
- void setVelocity(double x, double y, double z);
-
};
--- a/dom/webidl/PannerNode.webidl
+++ b/dom/webidl/PannerNode.webidl
@@ -43,18 +43,16 @@ dictionary PannerOptions : AudioNodeOpti
interface PannerNode : AudioNode {
// Default for stereo is equalpower
attribute PanningModelType panningModel;
// Uses a 3D cartesian coordinate system
void setPosition(double x, double y, double z);
void setOrientation(double x, double y, double z);
- [Deprecated="PannerNodeDoppler"]
- void setVelocity(double x, double y, double z);
// Cartesian coordinate for position
readonly attribute AudioParam positionX;
readonly attribute AudioParam positionY;
readonly attribute AudioParam positionZ;
// Cartesian coordinate for orientation
readonly attribute AudioParam orientationX;