summaryrefslogtreecommitdiff
path: root/Source/WebCore/Modules/webaudio/PannerNode.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/Modules/webaudio/PannerNode.cpp
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebCore/Modules/webaudio/PannerNode.cpp')
-rw-r--r--Source/WebCore/Modules/webaudio/PannerNode.cpp135
1 files changed, 39 insertions, 96 deletions
diff --git a/Source/WebCore/Modules/webaudio/PannerNode.cpp b/Source/WebCore/Modules/webaudio/PannerNode.cpp
index 17bf13042..d7f92cabc 100644
--- a/Source/WebCore/Modules/webaudio/PannerNode.cpp
+++ b/Source/WebCore/Modules/webaudio/PannerNode.cpp
@@ -23,17 +23,15 @@
*/
#include "config.h"
+#include "PannerNode.h"
#if ENABLE(WEB_AUDIO)
-#include "PannerNode.h"
-
#include "AudioBufferSourceNode.h"
#include "AudioBus.h"
#include "AudioContext.h"
#include "AudioNodeInput.h"
#include "AudioNodeOutput.h"
-#include "ExceptionCode.h"
#include "HRTFPanner.h"
#include "ScriptExecutionContext.h"
#include <wtf/MathExtras.h>
@@ -46,12 +44,15 @@ static void fixNANs(double &x)
x = 0.0;
}
-PannerNode::PannerNode(AudioContext* context, float sampleRate)
+PannerNode::PannerNode(AudioContext& context, float sampleRate)
: AudioNode(context, sampleRate)
- , m_panningModel(Panner::PanningModelHRTF)
+ , m_panningModel(PanningModelType::HRTF)
, m_lastGain(-1.0)
, m_connectionCount(0)
{
+ // Load the HRTF database asynchronously so we don't block the Javascript thread while creating the HRTF database.
+ m_hrtfDatabaseLoader = HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(context.sampleRate());
+
addInput(std::make_unique<AudioNodeInput>(this));
addOutput(std::make_unique<AudioNodeOutput>(this, 2));
@@ -81,11 +82,12 @@ void PannerNode::pullInputs(size_t framesToProcess)
{
// We override pullInputs(), so we can detect new AudioSourceNodes which have connected to us when new connections are made.
// These AudioSourceNodes need to be made aware of our existence in order to handle doppler shift pitch changes.
- if (m_connectionCount != context()->connectionCount()) {
- m_connectionCount = context()->connectionCount();
+ if (m_connectionCount != context().connectionCount()) {
+ m_connectionCount = context().connectionCount();
// Recursively go through all nodes connected to us.
- notifyAudioSourcesConnectedToNode(this);
+ HashSet<AudioNode*> visitedNodes;
+ notifyAudioSourcesConnectedToNode(this, visitedNodes);
}
AudioNode::pullInputs(framesToProcess);
@@ -101,14 +103,23 @@ void PannerNode::process(size_t framesToProcess)
}
AudioBus* source = input(0)->bus();
-
if (!source) {
destination->zero();
return;
}
+ // HRTFDatabase should be loaded before proceeding for offline audio context when panningModel() is "HRTF".
+ if (panningModel() == PanningModelType::HRTF && !m_hrtfDatabaseLoader->isLoaded()) {
+ if (context().isOfflineContext())
+ m_hrtfDatabaseLoader->waitForLoaderThreadCompletion();
+ else {
+ destination->zero();
+ return;
+ }
+ }
+
// The audio thread can't block on this lock, so we use std::try_to_lock instead.
- std::unique_lock<std::mutex> lock(m_pannerMutex, std::try_to_lock);
+ std::unique_lock<Lock> lock(m_pannerMutex, std::try_to_lock);
if (!lock.owns_lock()) {
// Too bad - The try_lock() failed. We must be in the middle of changing the panner.
destination->zero();
@@ -144,7 +155,7 @@ void PannerNode::initialize()
if (isInitialized())
return;
- m_panner = Panner::create(m_panningModel, sampleRate(), context()->hrtfDatabaseLoader());
+ m_panner = Panner::create(m_panningModel, sampleRate(), m_hrtfDatabaseLoader.get());
AudioNode::initialize();
}
@@ -160,100 +171,28 @@ void PannerNode::uninitialize()
AudioListener* PannerNode::listener()
{
- return context()->listener();
+ return context().listener();
}
-String PannerNode::panningModel() const
+void PannerNode::setPanningModel(PanningModelType model)
{
- switch (m_panningModel) {
- case EQUALPOWER:
- return "equalpower";
- case HRTF:
- return "HRTF";
- case SOUNDFIELD:
- return "soundfield";
- default:
- ASSERT_NOT_REACHED();
- return "HRTF";
- }
-}
+ if (!m_panner.get() || model != m_panningModel) {
+ // This synchronizes with process().
+ std::lock_guard<Lock> lock(m_pannerMutex);
-void PannerNode::setPanningModel(const String& model)
-{
- if (model == "equalpower")
- setPanningModel(EQUALPOWER);
- else if (model == "HRTF")
- setPanningModel(HRTF);
- else if (model == "soundfield")
- setPanningModel(SOUNDFIELD);
- else
- ASSERT_NOT_REACHED();
-}
-
-bool PannerNode::setPanningModel(unsigned model)
-{
- switch (model) {
- case EQUALPOWER:
- case HRTF:
- if (!m_panner.get() || model != m_panningModel) {
- // This synchronizes with process().
- std::lock_guard<std::mutex> lock(m_pannerMutex);
-
- m_panner = Panner::create(model, sampleRate(), context()->hrtfDatabaseLoader());
- m_panningModel = model;
- }
- break;
- case SOUNDFIELD:
- // FIXME: Implement sound field model. See // https://bugs.webkit.org/show_bug.cgi?id=77367.
- context()->scriptExecutionContext()->addConsoleMessage(JSMessageSource, WarningMessageLevel, "'soundfield' panning model not implemented.");
- break;
- default:
- return false;
- }
-
- return true;
-}
-
-String PannerNode::distanceModel() const
-{
- switch (const_cast<PannerNode*>(this)->m_distanceEffect.model()) {
- case DistanceEffect::ModelLinear:
- return "linear";
- case DistanceEffect::ModelInverse:
- return "inverse";
- case DistanceEffect::ModelExponential:
- return "exponential";
- default:
- ASSERT_NOT_REACHED();
- return "inverse";
+ m_panner = Panner::create(model, sampleRate(), m_hrtfDatabaseLoader.get());
+ m_panningModel = model;
}
}
-void PannerNode::setDistanceModel(const String& model)
+DistanceModelType PannerNode::distanceModel() const
{
- if (model == "linear")
- setDistanceModel(DistanceEffect::ModelLinear);
- else if (model == "inverse")
- setDistanceModel(DistanceEffect::ModelInverse);
- else if (model == "exponential")
- setDistanceModel(DistanceEffect::ModelExponential);
- else
- ASSERT_NOT_REACHED();
+ return const_cast<PannerNode*>(this)->m_distanceEffect.model();
}
-bool PannerNode::setDistanceModel(unsigned model)
+void PannerNode::setDistanceModel(DistanceModelType model)
{
- switch (model) {
- case DistanceEffect::ModelLinear:
- case DistanceEffect::ModelInverse:
- case DistanceEffect::ModelExponential:
- m_distanceEffect.setModel(static_cast<DistanceEffect::ModelType>(model), true);
- break;
- default:
- return false;
- }
-
- return true;
+ m_distanceEffect.setModel(model, true);
}
void PannerNode::getAzimuthElevation(double* outAzimuth, double* outElevation)
@@ -385,7 +324,7 @@ float PannerNode::distanceConeGain()
return float(distanceGain * coneGain);
}
-void PannerNode::notifyAudioSourcesConnectedToNode(AudioNode* node)
+void PannerNode::notifyAudioSourcesConnectedToNode(AudioNode* node, HashSet<AudioNode*>& visitedNodes)
{
ASSERT(node);
if (!node)
@@ -404,7 +343,11 @@ void PannerNode::notifyAudioSourcesConnectedToNode(AudioNode* node)
for (unsigned j = 0; j < input->numberOfRenderingConnections(); ++j) {
AudioNodeOutput* connectedOutput = input->renderingOutput(j);
AudioNode* connectedNode = connectedOutput->node();
- notifyAudioSourcesConnectedToNode(connectedNode); // recurse
+ if (visitedNodes.contains(connectedNode))
+ continue;
+
+ visitedNodes.add(connectedNode);
+ notifyAudioSourcesConnectedToNode(connectedNode, visitedNodes);
}
}
}