Index: Source/modules/webaudio/PannerNode.cpp |
diff --git a/Source/modules/webaudio/PannerNode.cpp b/Source/modules/webaudio/PannerNode.cpp |
index b4279c9567eb9897f98d206d81e4b94745153993..fc3cdfc8ebcb3b92be8e382a2f8a79311a095628 100644 |
--- a/Source/modules/webaudio/PannerNode.cpp |
+++ b/Source/modules/webaudio/PannerNode.cpp |
@@ -53,9 +53,9 @@ PannerNode::PannerNode(AudioContext* context, float sampleRate) |
, m_position(0, 0, 0) |
, m_orientation(1, 0, 0) |
, m_velocity(0, 0, 0) |
- , m_cachedPosition(0, 0, 0) |
- , m_cachedOrientation(1, 0, 0) |
- , m_cachedVelocity(0, 0, 0) |
+ , m_isAzimuthElevationDirty(true) |
+ , m_isDistanceConeGainDirty(true) |
+ , m_isDopplerRateDirty(true) |
, m_lastGain(-1.0) |
, m_cachedAzimuth(0) |
, m_cachedElevation(0) |
@@ -76,8 +76,6 @@ PannerNode::PannerNode(AudioContext* context, float sampleRate) |
m_channelCountMode = ClampedMax; |
m_channelInterpretation = AudioBus::Speakers; |
- m_cachedListener = AudioListener::create(); |
- |
setNodeType(NodeTypePanner); |
initialize(); |
@@ -123,7 +121,9 @@ void PannerNode::process(size_t framesToProcess) |
// The audio thread can't block on this lock, so we call tryLock() instead. |
MutexTryLocker tryLocker(m_processLock); |
- if (tryLocker.locked()) { |
+ MutexTryLocker tryListenerLocker(listener()->listenerLock()); |
+ |
+ if (tryLocker.locked() && tryListenerLocker.locked()) { |
// HRTFDatabase should be loaded before proceeding for offline audio context when the panning model is HRTF. |
if (m_panningModel == HRTF && !m_hrtfDatabaseLoader->isLoaded()) { |
if (context()->isOfflineContext()) { |
@@ -150,14 +150,9 @@ void PannerNode::process(size_t framesToProcess) |
// Apply gain in-place with de-zippering. |
destination->copyWithGainFrom(*destination, &m_lastGain, totalGain); |
- |
- // Update the cached listener in case listener has moved. |
- updateCachedListener(); |
- // Now update the cached source location in case the source has changed. |
- updateCachedSourceLocationInfo(); |
} else { |
// Too bad - The tryLock() failed. |
- // We must be in the middle of changing the panning model, the distance model, or the source's location information. |
+ // We must be in the middle of changing the properties of the panner or the listener. |
destination->zero(); |
} |
} |
@@ -168,6 +163,7 @@ void PannerNode::initialize() |
return; |
m_panner = Panner::create(m_panningModel, sampleRate(), m_hrtfDatabaseLoader.get()); |
+ listener()->addPanner(this); |
AudioNode::initialize(); |
} |
@@ -178,6 +174,8 @@ void PannerNode::uninitialize() |
return; |
m_panner.clear(); |
+ listener()->removePanner(this); |
+ |
AudioNode::uninitialize(); |
} |
@@ -215,7 +213,6 @@ bool PannerNode::setPanningModel(unsigned model) |
if (!m_panner.get() || model != m_panningModel) { |
// This synchronizes with process(). |
MutexLocker processLocker(m_processLock); |
- |
OwnPtr<Panner> newPanner = Panner::create(model, sampleRate(), m_hrtfDatabaseLoader.get()); |
m_panner = newPanner.release(); |
m_panningModel = model; |
@@ -228,45 +225,6 @@ bool PannerNode::setPanningModel(unsigned model) |
return true; |
} |
-void PannerNode::setPosition(float x, float y, float z) |
-{ |
- FloatPoint3D position = FloatPoint3D(x, y, z); |
- |
- if (m_position == position) |
- return; |
- |
- // This synchronizes with process(). |
- MutexLocker processLocker(m_processLock); |
- |
- m_position = position; |
-} |
- |
-void PannerNode::setOrientation(float x, float y, float z) |
-{ |
- FloatPoint3D orientation = FloatPoint3D(x, y, z); |
- |
- if (m_orientation == orientation) |
- return; |
- |
- // This synchronizes with process(). |
- MutexLocker processLocker(m_processLock); |
- |
- m_orientation = orientation; |
-} |
- |
-void PannerNode::setVelocity(float x, float y, float z) |
-{ |
- FloatPoint3D velocity = FloatPoint3D(x, y, z); |
- |
- if (m_velocity == velocity) |
- return; |
- |
- // This synchronizes with process(). |
- MutexLocker processLocker(m_processLock); |
- |
- m_velocity = velocity; |
-} |
- |
String PannerNode::distanceModel() const |
{ |
switch (const_cast<PannerNode*>(this)->m_distanceEffect.model()) { |
@@ -312,6 +270,111 @@ bool PannerNode::setDistanceModel(unsigned model) |
return true; |
} |
+void PannerNode::setRefDistance(double distance) |
+{ |
+ if (refDistance() == distance) |
+ return; |
+ |
+ // This synchronizes with process(). |
+ MutexLocker processLocker(m_processLock); |
+ m_distanceEffect.setRefDistance(distance); |
+ markPannerAsDirty(PannerNode::DistanceConeGainDirty); |
+} |
+ |
+void PannerNode::setMaxDistance(double distance) |
+{ |
+ if (maxDistance() == distance) |
+ return; |
+ |
+ // This synchronizes with process(). |
+ MutexLocker processLocker(m_processLock); |
+ m_distanceEffect.setMaxDistance(distance); |
+ markPannerAsDirty(PannerNode::DistanceConeGainDirty); |
+} |
+ |
+void PannerNode::setRolloffFactor(double factor) |
+{ |
+ if (rolloffFactor() == factor) |
+ return; |
+ |
+ // This synchronizes with process(). |
+ MutexLocker processLocker(m_processLock); |
+ m_distanceEffect.setRolloffFactor(factor); |
+ markPannerAsDirty(PannerNode::DistanceConeGainDirty); |
+} |
+ |
+void PannerNode::setConeInnerAngle(double angle) |
+{ |
+ if (coneInnerAngle() == angle) |
+ return; |
+ |
+ // This synchronizes with process(). |
+ MutexLocker processLocker(m_processLock); |
+ m_coneEffect.setInnerAngle(angle); |
+ markPannerAsDirty(PannerNode::DistanceConeGainDirty); |
+} |
+ |
+void PannerNode::setConeOuterAngle(double angle) |
+{ |
+ if (coneOuterAngle() == angle) |
+ return; |
+ |
+ // This synchronizes with process(). |
+ MutexLocker processLocker(m_processLock); |
+ m_coneEffect.setOuterAngle(angle); |
+ markPannerAsDirty(PannerNode::DistanceConeGainDirty); |
+} |
+ |
+void PannerNode::setConeOuterGain(double angle) |
+{ |
+ if (coneOuterGain() == angle) |
+ return; |
+ |
+ // This synchronizes with process(). |
+ MutexLocker processLocker(m_processLock); |
+ m_coneEffect.setOuterGain(angle); |
+ markPannerAsDirty(PannerNode::DistanceConeGainDirty); |
+} |
+ |
+void PannerNode::setPosition(float x, float y, float z) |
+{ |
+ FloatPoint3D position = FloatPoint3D(x, y, z); |
+ |
+ if (m_position == position) |
+ return; |
+ |
+ // This synchronizes with process(). |
+ MutexLocker processLocker(m_processLock); |
+ m_position = position; |
+ markPannerAsDirty(PannerNode::AzimuthElevationDirty | PannerNode::DistanceConeGainDirty | PannerNode::DopplerRateDirty); |
+} |
+ |
+void PannerNode::setOrientation(float x, float y, float z) |
+{ |
+ FloatPoint3D orientation = FloatPoint3D(x, y, z); |
+ |
+ if (m_orientation == orientation) |
+ return; |
+ |
+ // This synchronizes with process(). |
+ MutexLocker processLocker(m_processLock); |
+ m_orientation = orientation; |
+ markPannerAsDirty(PannerNode::DistanceConeGainDirty); |
+} |
+ |
+void PannerNode::setVelocity(float x, float y, float z) |
+{ |
+ FloatPoint3D velocity = FloatPoint3D(x, y, z); |
+ |
+ if (m_velocity == velocity) |
+ return; |
+ |
+ // This synchronizes with process(). |
+ MutexLocker processLocker(m_processLock); |
+ m_velocity = velocity; |
+ markPannerAsDirty(PannerNode::DopplerRateDirty); |
+} |
+ |
void PannerNode::calculateAzimuthElevation(double* outAzimuth, double* outElevation) |
{ |
double azimuth = 0.0; |
@@ -435,8 +498,10 @@ void PannerNode::azimuthElevation(double* outAzimuth, double* outElevation) |
{ |
ASSERT(context()->isAudioThread()); |
- if (isAzimuthElevationDirty()) |
+ if (isAzimuthElevationDirty()) { |
calculateAzimuthElevation(&m_cachedAzimuth, &m_cachedElevation); |
+ m_isAzimuthElevationDirty = false; |
+ } |
*outAzimuth = m_cachedAzimuth; |
*outElevation = m_cachedElevation; |
@@ -446,8 +511,10 @@ double PannerNode::dopplerRate() |
{ |
ASSERT(context()->isAudioThread()); |
- if (isDopplerRateDirty()) |
+ if (isDopplerRateDirty()) { |
m_cachedDopplerRate = calculateDopplerRate(); |
+ m_isDopplerRateDirty = false; |
+ } |
return m_cachedDopplerRate; |
} |
@@ -456,51 +523,24 @@ float PannerNode::distanceConeGain() |
{ |
ASSERT(context()->isAudioThread()); |
- if (isDistanceConeGainDirty()) |
+ if (isDistanceConeGainDirty()) { |
m_cachedDistanceConeGain = calculateDistanceConeGain(); |
+ m_isDistanceConeGainDirty = false; |
+ } |
return m_cachedDistanceConeGain; |
} |
-bool PannerNode::isAzimuthElevationDirty() |
-{ |
- // Do a quick test and return if possible. |
- if (m_cachedPosition != m_position) |
- return true; |
- |
- if (m_cachedListener->position() != listener()->position() |
- || m_cachedListener->orientation() != listener()->orientation() |
- || m_cachedListener->upVector() != listener()->upVector()) |
- return true; |
- |
- return false; |
-} |
- |
-bool PannerNode::isDistanceConeGainDirty() |
+void PannerNode::markPannerAsDirty(unsigned dirty) |
{ |
- // Do a quick test and return if possible. |
- if (m_cachedPosition != m_position || m_cachedOrientation != m_orientation) |
- return true; |
+ if (dirty & PannerNode::AzimuthElevationDirty) |
+ m_isAzimuthElevationDirty = true; |
- if (m_cachedListener->position() != listener()->position()) |
- return true; |
+ if (dirty & PannerNode::DistanceConeGainDirty) |
+ m_isDistanceConeGainDirty = true; |
- return false; |
-} |
- |
-bool PannerNode::isDopplerRateDirty() |
-{ |
- // Do a quick test and return if possible. |
- if (m_cachedPosition != m_position || m_cachedVelocity != m_velocity) |
- return true; |
- |
- if (m_cachedListener->position() != listener()->position() |
- || m_cachedListener->velocity() != listener()->velocity() |
- || m_cachedListener->dopplerFactor() != listener()->dopplerFactor() |
- || m_cachedListener->speedOfSound() != listener()->speedOfSound()) |
- return true; |
- |
- return false; |
+ if (dirty & PannerNode::DopplerRateDirty) |
+ m_isDopplerRateDirty = true; |
} |
void PannerNode::notifyAudioSourcesConnectedToNode(AudioNode* node, HashMap<AudioNode*, bool>& visitedNodes) |
@@ -535,27 +575,6 @@ void PannerNode::notifyAudioSourcesConnectedToNode(AudioNode* node, HashMap<Audi |
} |
} |
-void PannerNode::updateCachedListener() |
-{ |
- ASSERT(context()->isAudioThread()); |
- |
- m_cachedListener->setPosition(listener()->position()); |
- m_cachedListener->setOrientation(listener()->orientation()); |
- m_cachedListener->setUpVector(listener()->upVector()); |
- m_cachedListener->setVelocity(listener()->velocity()); |
- m_cachedListener->setDopplerFactor(listener()->dopplerFactor()); |
- m_cachedListener->setSpeedOfSound(listener()->speedOfSound()); |
-} |
- |
-void PannerNode::updateCachedSourceLocationInfo() |
-{ |
- ASSERT(context()->isAudioThread()); |
- |
- m_cachedPosition = m_position; |
- m_cachedOrientation = m_orientation; |
- m_cachedVelocity = m_velocity; |
-} |
- |
} // namespace WebCore |
#endif // ENABLE(WEB_AUDIO) |