| Index: Source/modules/webaudio/PannerNode.cpp
|
| diff --git a/Source/modules/webaudio/PannerNode.cpp b/Source/modules/webaudio/PannerNode.cpp
|
| index 27e06244babb4cedc8f5a3bf61d400684df839df..3f2dde89def0dc6e3f5920d71ebb7663e6bd3d12 100644
|
| --- a/Source/modules/webaudio/PannerNode.cpp
|
| +++ b/Source/modules/webaudio/PannerNode.cpp
|
| @@ -49,7 +49,17 @@ static void fixNANs(double &x)
|
| PannerNode::PannerNode(AudioContext* context, float sampleRate)
|
| : AudioNode(context, sampleRate)
|
| , m_panningModel(Panner::PanningModelHRTF)
|
| + , 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_lastGain(-1.0)
|
| + , m_cachedAzimuth(0)
|
| + , m_cachedElevation(0)
|
| + , m_cachedDistanceConeGain(0)
|
| + , m_cachedDopplerRate(1)
|
| , m_connectionCount(0)
|
| {
|
| // Load the HRTF database asynchronously so we don't block the Javascript thread while creating the HRTF database.
|
| @@ -68,9 +78,7 @@ PannerNode::PannerNode(AudioContext* context, float sampleRate)
|
| m_distanceGain = AudioParam::create(context, "distanceGain", 1.0, 0.0, 1.0);
|
| m_coneGain = AudioParam::create(context, "coneGain", 1.0, 0.0, 1.0);
|
|
|
| - m_position = FloatPoint3D(0, 0, 0);
|
| - m_orientation = FloatPoint3D(1, 0, 0);
|
| - m_velocity = FloatPoint3D(0, 0, 0);
|
| + m_cachedListener = AudioListener::create();
|
|
|
| setNodeType(NodeTypePanner);
|
|
|
| @@ -131,11 +139,12 @@ void PannerNode::process(size_t framesToProcess)
|
| // Apply the panning effect.
|
| double azimuth;
|
| double elevation;
|
| - getAzimuthElevation(&azimuth, &elevation);
|
| + azimuthElevation(&azimuth, &elevation);
|
| +
|
| m_panner->pan(azimuth, elevation, source, destination, framesToProcess);
|
|
|
| // Get the distance and cone gain.
|
| - double totalGain = distanceConeGain();
|
| + float totalGain = distanceConeGain();
|
|
|
| // Snap to desired gain at the beginning.
|
| if (m_lastGain == -1.0)
|
| @@ -143,6 +152,11 @@ 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 panner.
|
| destination->zero();
|
| @@ -217,6 +231,42 @@ bool PannerNode::setPanningModel(unsigned model)
|
| return true;
|
| }
|
|
|
| +void PannerNode::setPosition(float x, float y, float z)
|
| +{
|
| + // FIXME : consider thread safety about m_position in audio thread.
|
| + // See http://crbugs.com/350583.
|
| + FloatPoint3D position = FloatPoint3D(x, y, z);
|
| +
|
| + if (m_position == position)
|
| + return;
|
| +
|
| + m_position = position;
|
| +}
|
| +
|
| +void PannerNode::setOrientation(float x, float y, float z)
|
| +{
|
| + // FIXME : consider thread safety about m_orientation in audio thread.
|
| + // See http://crbugs.com/350583.
|
| + FloatPoint3D orientation = FloatPoint3D(x, y, z);
|
| +
|
| + if (m_orientation == orientation)
|
| + return;
|
| +
|
| + m_orientation = orientation;
|
| +}
|
| +
|
| +void PannerNode::setVelocity(float x, float y, float z)
|
| +{
|
| + // FIXME : consider thread safety about m_velocity in audio thread.
|
| + // See http://crbugs.com/350583.
|
| + FloatPoint3D velocity = FloatPoint3D(x, y, z);
|
| +
|
| + if (m_velocity == velocity)
|
| + return;
|
| +
|
| + m_velocity = velocity;
|
| +}
|
| +
|
| String PannerNode::distanceModel() const
|
| {
|
| switch (const_cast<PannerNode*>(this)->m_distanceEffect.model()) {
|
| @@ -259,10 +309,8 @@ bool PannerNode::setDistanceModel(unsigned model)
|
| return true;
|
| }
|
|
|
| -void PannerNode::getAzimuthElevation(double* outAzimuth, double* outElevation)
|
| +void PannerNode::calculateAzimuthElevation(double* outAzimuth, double* outElevation)
|
| {
|
| - // FIXME: we should cache azimuth and elevation (if possible), so we only re-calculate if a change has been made.
|
| -
|
| double azimuth = 0.0;
|
|
|
| // Calculate the source-listener vector
|
| @@ -323,11 +371,10 @@ void PannerNode::getAzimuthElevation(double* outAzimuth, double* outElevation)
|
| *outElevation = elevation;
|
| }
|
|
|
| -float PannerNode::dopplerRate()
|
| +
|
| +double PannerNode::calculateDopplerRate()
|
| {
|
| double dopplerShift = 1.0;
|
| -
|
| - // FIXME: optimize for case when neither source nor listener has changed...
|
| double dopplerFactor = listener()->dopplerFactor();
|
|
|
| if (dopplerFactor > 0.0) {
|
| @@ -368,10 +415,10 @@ float PannerNode::dopplerRate()
|
| }
|
| }
|
|
|
| - return static_cast<float>(dopplerShift);
|
| + return dopplerShift;
|
| }
|
|
|
| -float PannerNode::distanceConeGain()
|
| +float PannerNode::calculateDistanceConeGain()
|
| {
|
| FloatPoint3D listenerPosition = listener()->position();
|
|
|
| @@ -380,7 +427,6 @@ float PannerNode::distanceConeGain()
|
|
|
| m_distanceGain->setValue(static_cast<float>(distanceGain));
|
|
|
| - // FIXME: could optimize by caching coneGain
|
| double coneGain = m_coneEffect.gain(m_position, m_orientation, listenerPosition);
|
|
|
| m_coneGain->setValue(static_cast<float>(coneGain));
|
| @@ -388,6 +434,72 @@ float PannerNode::distanceConeGain()
|
| return float(distanceGain * coneGain);
|
| }
|
|
|
| +void PannerNode::azimuthElevation(double* outAzimuth, double* outElevation)
|
| +{
|
| + if (isAzimuthElevationDirty())
|
| + calculateAzimuthElevation(&m_cachedAzimuth, &m_cachedElevation);
|
| +
|
| + *outAzimuth = m_cachedAzimuth;
|
| + *outElevation = m_cachedElevation;
|
| +}
|
| +
|
| +double PannerNode::dopplerRate()
|
| +{
|
| + if (isDopplerRateDirty())
|
| + m_cachedDopplerRate = calculateDopplerRate();
|
| +
|
| + return m_cachedDopplerRate;
|
| +}
|
| +
|
| +float PannerNode::distanceConeGain()
|
| +{
|
| + if (isDistanceConeGainDirty())
|
| + m_cachedDistanceConeGain = calculateDistanceConeGain();
|
| +
|
| + 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()
|
| +{
|
| + // Do a quick test and return if possible.
|
| + if (m_cachedPosition != m_position || m_cachedOrientation != m_orientation)
|
| + return true;
|
| +
|
| + if (m_cachedListener->position() != listener()->position())
|
| + return 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;
|
| +}
|
| +
|
| void PannerNode::notifyAudioSourcesConnectedToNode(AudioNode* node, HashMap<AudioNode*, bool>& visitedNodes)
|
| {
|
| ASSERT(node);
|
| @@ -420,6 +532,23 @@ void PannerNode::notifyAudioSourcesConnectedToNode(AudioNode* node, HashMap<Audi
|
| }
|
| }
|
|
|
| +void PannerNode::updateCachedListener()
|
| +{
|
| + 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()
|
| +{
|
| + m_cachedPosition = m_position;
|
| + m_cachedOrientation = m_orientation;
|
| + m_cachedVelocity = m_velocity;
|
| +}
|
| +
|
| } // namespace WebCore
|
|
|
| #endif // ENABLE(WEB_AUDIO)
|
|
|