Chromium Code Reviews| Index: third_party/WebKit/Source/modules/webaudio/AudioListener.cpp |
| diff --git a/third_party/WebKit/Source/modules/webaudio/AudioListener.cpp b/third_party/WebKit/Source/modules/webaudio/AudioListener.cpp |
| index b41982d9d05ac5f59cbc674a08261ecb323b8b20..1a8fe70917d644a8b4d6bb9ca380649d189cf685 100644 |
| --- a/third_party/WebKit/Source/modules/webaudio/AudioListener.cpp |
| +++ b/third_party/WebKit/Source/modules/webaudio/AudioListener.cpp |
| @@ -29,17 +29,39 @@ |
| #include "modules/webaudio/AudioListener.h" |
| #include "modules/webaudio/PannerNode.h" |
| #include "platform/audio/AudioBus.h" |
| +#include "platform/audio/AudioUtilities.h" |
| #include "platform/audio/HRTFDatabaseLoader.h" |
| namespace blink { |
| -AudioListener::AudioListener() |
| - : m_position(0, 0, 0) |
| - , m_orientation(0, 0, -1) |
| - , m_upVector(0, 1, 0) |
| +AudioListener::AudioListener(AbstractAudioContext& context) |
| + : m_positionX(AudioParam::create(context, 0.0)) |
| + , m_positionY(AudioParam::create(context, 0.0)) |
| + , m_positionZ(AudioParam::create(context, 0.0)) |
| + , m_forwardX(AudioParam::create(context, 0.0)) |
| + , m_forwardY(AudioParam::create(context, 0.0)) |
| + , m_forwardZ(AudioParam::create(context, -1.0)) |
| + , m_upX(AudioParam::create(context, 0.0)) |
| + , m_upY(AudioParam::create(context, 1.0)) |
| + , m_upZ(AudioParam::create(context, 0.0)) |
| , m_dopplerFactor(1) |
| , m_speedOfSound(343.3) |
| + , m_lastUpdateTime(-1) |
| + , m_positionXValues(AudioUtilities::kRenderQuantumFrames) |
| + , m_positionYValues(AudioUtilities::kRenderQuantumFrames) |
| + , m_positionZValues(AudioUtilities::kRenderQuantumFrames) |
| + , m_forwardXValues(AudioUtilities::kRenderQuantumFrames) |
| + , m_forwardYValues(AudioUtilities::kRenderQuantumFrames) |
| + , m_forwardZValues(AudioUtilities::kRenderQuantumFrames) |
| + , m_upXValues(AudioUtilities::kRenderQuantumFrames) |
| + , m_upYValues(AudioUtilities::kRenderQuantumFrames) |
| + , m_upZValues(AudioUtilities::kRenderQuantumFrames) |
| { |
| + // Initialize the cached values with the current values. Thus, we don't need to notify any |
| + // panners because we haved moved. |
| + m_lastPosition = position(); |
| + m_lastForward = orientation(); |
| + m_lastUp = upVector(); |
| } |
| AudioListener::~AudioListener() |
| @@ -48,6 +70,17 @@ AudioListener::~AudioListener() |
| DEFINE_TRACE(AudioListener) |
| { |
| + visitor->trace(m_positionX); |
| + visitor->trace(m_positionY); |
| + visitor->trace(m_positionZ); |
| + |
| + visitor->trace(m_forwardX); |
| + visitor->trace(m_forwardY); |
| + visitor->trace(m_forwardZ); |
| + |
| + visitor->trace(m_upX); |
| + visitor->trace(m_upY); |
| + visitor->trace(m_upZ); |
| } |
| void AudioListener::addPanner(PannerHandler& panner) |
| @@ -63,6 +96,128 @@ void AudioListener::removePanner(PannerHandler& panner) |
| m_panners.remove(&panner); |
| } |
| +bool AudioListener::hasSampleAccurateValues() const |
| +{ |
| + return positionX()->handler().hasSampleAccurateValues() |
| + || positionY()->handler().hasSampleAccurateValues() |
| + || positionZ()->handler().hasSampleAccurateValues() |
| + || forwardX()->handler().hasSampleAccurateValues() |
| + || forwardY()->handler().hasSampleAccurateValues() |
| + || forwardZ()->handler().hasSampleAccurateValues() |
| + || upX()->handler().hasSampleAccurateValues() |
| + || upY()->handler().hasSampleAccurateValues() |
| + || upZ()->handler().hasSampleAccurateValues(); |
| +} |
| + |
| +void AudioListener::updateValuesIfNeeded(unsigned framesToProcess) |
| +{ |
| + double currentTime = positionX()->handler().context()->currentTime(); |
| + if (m_lastUpdateTime != currentTime) { |
| + // Time has changed. Update all of the automation values now. |
| + m_lastUpdateTime = currentTime; |
| + |
| + RELEASE_ASSERT(framesToProcess <= m_positionXValues.size()); |
|
hongchan
2016/05/03 18:15:01
Note: If this is true for any instance of AudioPar
Raymond Toy
2016/05/03 20:32:21
That would require refactoring calculateSampleAccu
|
| + RELEASE_ASSERT(framesToProcess <= m_positionYValues.size()); |
| + RELEASE_ASSERT(framesToProcess <= m_positionZValues.size()); |
| + RELEASE_ASSERT(framesToProcess <= m_forwardXValues.size()); |
| + RELEASE_ASSERT(framesToProcess <= m_forwardYValues.size()); |
| + RELEASE_ASSERT(framesToProcess <= m_forwardZValues.size()); |
| + RELEASE_ASSERT(framesToProcess <= m_upXValues.size()); |
| + RELEASE_ASSERT(framesToProcess <= m_upYValues.size()); |
| + RELEASE_ASSERT(framesToProcess <= m_upZValues.size()); |
| + |
| + positionX()->handler().calculateSampleAccurateValues(m_positionXValues.data(), framesToProcess); |
| + positionY()->handler().calculateSampleAccurateValues(m_positionYValues.data(), framesToProcess); |
| + positionZ()->handler().calculateSampleAccurateValues(m_positionZValues.data(), framesToProcess); |
| + |
| + forwardX()->handler().calculateSampleAccurateValues(m_forwardXValues.data(), framesToProcess); |
| + forwardY()->handler().calculateSampleAccurateValues(m_forwardYValues.data(), framesToProcess); |
| + forwardZ()->handler().calculateSampleAccurateValues(m_forwardZValues.data(), framesToProcess); |
| + |
| + upX()->handler().calculateSampleAccurateValues(m_upXValues.data(), framesToProcess); |
| + upY()->handler().calculateSampleAccurateValues(m_upYValues.data(), framesToProcess); |
| + upZ()->handler().calculateSampleAccurateValues(m_upZValues.data(), framesToProcess); |
| + } |
| +} |
| + |
| +const float* AudioListener::getPositionXValues(int framesToProcess) |
| +{ |
| + updateValuesIfNeeded(framesToProcess); |
| + return m_positionXValues.data(); |
| +} |
| + |
| +const float* AudioListener::getPositionYValues(int framesToProcess) |
| +{ |
| + updateValuesIfNeeded(framesToProcess); |
| + return m_positionYValues.data(); |
| +} |
| + |
| +const float* AudioListener::getPositionZValues(int framesToProcess) |
| +{ |
| + updateValuesIfNeeded(framesToProcess); |
| + return m_positionZValues.data(); |
| +} |
| + |
| +const float* AudioListener::getForwardXValues(int framesToProcess) |
| +{ |
| + updateValuesIfNeeded(framesToProcess); |
| + return m_forwardXValues.data(); |
| +} |
| + |
| +const float* AudioListener::getForwardYValues(int framesToProcess) |
| +{ |
| + updateValuesIfNeeded(framesToProcess); |
| + return m_forwardYValues.data(); |
| +} |
| + |
| +const float* AudioListener::getForwardZValues(int framesToProcess) |
| +{ |
| + updateValuesIfNeeded(framesToProcess); |
| + return m_forwardZValues.data(); |
| +} |
| + |
| +const float* AudioListener::getUpXValues(int framesToProcess) |
| +{ |
| + updateValuesIfNeeded(framesToProcess); |
| + return m_upXValues.data(); |
| +} |
| + |
| +const float* AudioListener::getUpYValues(int framesToProcess) |
| +{ |
| + updateValuesIfNeeded(framesToProcess); |
| + return m_upYValues.data(); |
| +} |
| + |
| +const float* AudioListener::getUpZValues(int framesToProcess) |
| +{ |
| + updateValuesIfNeeded(framesToProcess); |
| + return m_upZValues.data(); |
| +} |
| + |
| +void AudioListener::updateState() |
| +{ |
| + FloatPoint3D currentPosition = position(); |
| + FloatPoint3D currentForward = orientation(); |
| + FloatPoint3D currentUp = upVector(); |
| + |
| + bool hasMoved = currentPosition != m_lastPosition |
| + || currentForward != m_lastForward |
| + || currentUp != m_lastUp; |
| + |
| + if (hasMoved) { |
| + m_lastPosition = currentPosition; |
| + m_lastForward = currentForward; |
| + m_lastUp = currentUp; |
| + |
| + markPannersAsDirty(PannerHandler::AzimuthElevationDirty | PannerHandler::DistanceConeGainDirty); |
| + } else { |
| + // Tell each panner to check its dirty state in case the panner position/orientation |
| + // changed. |
| + for (PannerHandler* panner : m_panners) |
| + panner->updateDirtyState(); |
| + } |
| +} |
| + |
| void AudioListener::createAndLoadHRTFDatabaseLoader(float sampleRate) |
| { |
| if (!m_hrtfDatabaseLoader) |
| @@ -88,34 +243,31 @@ void AudioListener::markPannersAsDirty(unsigned type) |
| void AudioListener::setPosition(const FloatPoint3D& position) |
| { |
| - if (m_position == position) |
| - return; |
| - |
| // This synchronizes with panner's process(). |
| MutexLocker listenerLocker(m_listenerLock); |
| - m_position = position; |
| + m_positionX->setValue(position.x()); |
| + m_positionY->setValue(position.y()); |
| + m_positionZ->setValue(position.z()); |
| markPannersAsDirty(PannerHandler::AzimuthElevationDirty | PannerHandler::DistanceConeGainDirty); |
| } |
| void AudioListener::setOrientation(const FloatPoint3D& orientation) |
| { |
| - if (m_orientation == orientation) |
| - return; |
| - |
| // This synchronizes with panner's process(). |
| MutexLocker listenerLocker(m_listenerLock); |
| - m_orientation = orientation; |
| + m_forwardX->setValue(orientation.x()); |
| + m_forwardY->setValue(orientation.y()); |
| + m_forwardZ->setValue(orientation.z()); |
| markPannersAsDirty(PannerHandler::AzimuthElevationDirty); |
| } |
| void AudioListener::setUpVector(const FloatPoint3D& upVector) |
| { |
| - if (m_upVector == upVector) |
| - return; |
| - |
| // This synchronizes with panner's process(). |
| MutexLocker listenerLocker(m_listenerLock); |
| - m_upVector = upVector; |
| + m_upX->setValue(upVector.x()); |
| + m_upY->setValue(upVector.y()); |
| + m_upZ->setValue(upVector.z()); |
| markPannersAsDirty(PannerHandler::AzimuthElevationDirty); |
| } |