Chromium Code Reviews| Index: Source/modules/webaudio/PannerNode.cpp |
| diff --git a/Source/modules/webaudio/PannerNode.cpp b/Source/modules/webaudio/PannerNode.cpp |
| index b4279c9567eb9897f98d206d81e4b94745153993..2a5dfed87e8ecd12deb2b91a24225612cef93486 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 panning model, source's location information, listener, distance parameters and sound cones. |
|
Raymond Toy
2014/04/16 17:36:15
Maybe simplify comment to just:
// We must be in
KhNo
2014/04/17 13:41:03
Done.
|
| destination->zero(); |
| } |
| } |
| @@ -168,6 +163,7 @@ void PannerNode::initialize() |
| return; |
| m_panner = Panner::create(m_panningModel, sampleRate(), m_hrtfDatabaseLoader.get()); |
| + listener()->addPanner(this); |
|
Raymond Toy
2014/04/16 17:36:15
This happens in the main thread, but the processin
KhNo
2014/04/17 13:41:03
No, It doesn't happen. panners list in AudioListen
|
| AudioNode::initialize(); |
| } |
| @@ -178,6 +174,8 @@ void PannerNode::uninitialize() |
| return; |
| m_panner.clear(); |
| + listener()->removePanner(this); |
|
Raymond Toy
2014/04/16 17:36:15
Is there a race condition here? You've cleared the
KhNo
2014/04/17 13:41:03
No, It doesn't happen. panners list in AudioListen
|
| + |
| AudioNode::uninitialize(); |
| } |
| @@ -189,7 +187,7 @@ AudioListener* PannerNode::listener() |
| String PannerNode::panningModel() const |
| { |
| switch (m_panningModel) { |
| - case EQUALPOWER: |
| + case EqualPower: |
| return "equalpower"; |
| case HRTF: |
| return "HRTF"; |
| @@ -202,7 +200,7 @@ String PannerNode::panningModel() const |
| void PannerNode::setPanningModel(const String& model) |
| { |
| if (model == "equalpower") |
| - setPanningModel(EQUALPOWER); |
| + setPanningModel(EqualPower); |
| else if (model == "HRTF") |
| setPanningModel(HRTF); |
| } |
| @@ -210,12 +208,11 @@ void PannerNode::setPanningModel(const String& model) |
| bool PannerNode::setPanningModel(unsigned model) |
| { |
| switch (model) { |
| - case EQUALPOWER: |
| + case EqualPower: |
| case HRTF: |
| 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); |
| + updatePannerDirty(PannerNode::DistanceConeGainDirty); |
| +} |
| + |
| +void PannerNode::setMaxDistance(double distance) |
| +{ |
| + if (maxDistance() == distance) |
| + return; |
| + |
| + // This synchronizes with process(). |
| + MutexLocker processLocker(m_processLock); |
| + m_distanceEffect.setMaxDistance(distance); |
| + updatePannerDirty(PannerNode::DistanceConeGainDirty); |
| +} |
| + |
| +void PannerNode::setRolloffFactor(double factor) |
| +{ |
| + if (rolloffFactor() == factor) |
| + return; |
| + |
| + // This synchronizes with process(). |
| + MutexLocker processLocker(m_processLock); |
| + m_distanceEffect.setRolloffFactor(factor); |
| + updatePannerDirty(PannerNode::DistanceConeGainDirty); |
| +} |
| + |
| +void PannerNode::setConeInnerAngle(double angle) |
| +{ |
| + if (coneInnerAngle() == angle) |
| + return; |
| + |
| + // This synchronizes with process(). |
| + MutexLocker processLocker(m_processLock); |
| + m_coneEffect.setInnerAngle(angle); |
| + updatePannerDirty(PannerNode::DistanceConeGainDirty); |
| +} |
| + |
| +void PannerNode::setConeOuterAngle(double angle) |
| +{ |
| + if (coneOuterAngle() == angle) |
| + return; |
| + |
| + // This synchronizes with process(). |
| + MutexLocker processLocker(m_processLock); |
| + m_coneEffect.setOuterAngle(angle); |
| + updatePannerDirty(PannerNode::DistanceConeGainDirty); |
| +} |
| + |
| +void PannerNode::setConeOuterGain(double angle) |
| +{ |
| + if (coneOuterGain() == angle) |
| + return; |
| + |
| + // This synchronizes with process(). |
| + MutexLocker processLocker(m_processLock); |
| + m_coneEffect.setOuterGain(angle); |
| + updatePannerDirty(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; |
| + updatePannerDirty(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; |
| + updatePannerDirty(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; |
| + updatePannerDirty(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::updatePannerDirty(unsigned dirty) |
|
Raymond Toy
2014/04/16 17:36:15
I think the name markPannerAsDirty is more explici
KhNo
2014/04/17 13:41:03
Done.
|
| { |
| - // 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) |