diff options
Diffstat (limited to 'Source/WebCore/Modules/webaudio/AudioNode.cpp')
-rw-r--r-- | Source/WebCore/Modules/webaudio/AudioNode.cpp | 205 |
1 files changed, 98 insertions, 107 deletions
diff --git a/Source/WebCore/Modules/webaudio/AudioNode.cpp b/Source/WebCore/Modules/webaudio/AudioNode.cpp index 514ec7a3e..d0d42335f 100644 --- a/Source/WebCore/Modules/webaudio/AudioNode.cpp +++ b/Source/WebCore/Modules/webaudio/AudioNode.cpp @@ -42,7 +42,7 @@ namespace WebCore { -AudioNode::AudioNode(AudioContext* context, float sampleRate) +AudioNode::AudioNode(AudioContext& context, float sampleRate) : m_isInitialized(false) , m_nodeType(NodeTypeUnknown) , m_context(context) @@ -67,6 +67,7 @@ AudioNode::AudioNode(AudioContext* context, float sampleRate) AudioNode::~AudioNode() { + ASSERT(isMainThread()); #if DEBUG_AUDIONODE_REFERENCES --s_nodeCount[nodeType()]; fprintf(stderr, "%p: %d: AudioNode::~AudioNode() %d %d\n", this, nodeType(), m_normalRefCount.load(), m_connectionRefCount); @@ -100,12 +101,12 @@ void AudioNode::lazyInitialize() void AudioNode::addInput(std::unique_ptr<AudioNodeInput> input) { - m_inputs.append(std::move(input)); + m_inputs.append(WTFMove(input)); } void AudioNode::addOutput(std::unique_ptr<AudioNodeOutput> output) { - m_outputs.append(std::move(output)); + m_outputs.append(WTFMove(output)); } AudioNodeInput* AudioNode::input(unsigned i) @@ -122,117 +123,103 @@ AudioNodeOutput* AudioNode::output(unsigned i) return nullptr; } -void AudioNode::connect(AudioNode* destination, unsigned outputIndex, unsigned inputIndex, ExceptionCode& ec) +ExceptionOr<void> AudioNode::connect(AudioNode& destination, unsigned outputIndex, unsigned inputIndex) { ASSERT(isMainThread()); - AudioContext::AutoLocker locker(*context()); - - if (!destination) { - ec = SYNTAX_ERR; - return; - } + AudioContext::AutoLocker locker(context()); // Sanity check input and output indices. - if (outputIndex >= numberOfOutputs()) { - ec = INDEX_SIZE_ERR; - return; - } + if (outputIndex >= numberOfOutputs()) + return Exception { INDEX_SIZE_ERR }; - if (destination && inputIndex >= destination->numberOfInputs()) { - ec = INDEX_SIZE_ERR; - return; - } + if (inputIndex >= destination.numberOfInputs()) + return Exception { INDEX_SIZE_ERR }; - if (context() != destination->context()) { - ec = SYNTAX_ERR; - return; - } + if (context() != destination.context()) + return Exception { SYNTAX_ERR }; - AudioNodeInput* input = destination->input(inputIndex); - AudioNodeOutput* output = this->output(outputIndex); + auto* input = destination.input(inputIndex); + auto* output = this->output(outputIndex); input->connect(output); // Let context know that a connection has been made. - context()->incrementConnectionCount(); + context().incrementConnectionCount(); + + return { }; } -void AudioNode::connect(AudioParam* param, unsigned outputIndex, ExceptionCode& ec) +ExceptionOr<void> AudioNode::connect(AudioParam& param, unsigned outputIndex) { ASSERT(isMainThread()); - AudioContext::AutoLocker locker(*context()); + AudioContext::AutoLocker locker(context()); - if (!param) { - ec = SYNTAX_ERR; - return; - } + if (outputIndex >= numberOfOutputs()) + return Exception { INDEX_SIZE_ERR }; - if (outputIndex >= numberOfOutputs()) { - ec = INDEX_SIZE_ERR; - return; - } + if (context() != param.context()) + return Exception { SYNTAX_ERR }; - if (context() != param->context()) { - ec = SYNTAX_ERR; - return; - } + auto* output = this->output(outputIndex); + param.connect(output); - AudioNodeOutput* output = this->output(outputIndex); - param->connect(output); + return { }; } -void AudioNode::disconnect(unsigned outputIndex, ExceptionCode& ec) +ExceptionOr<void> AudioNode::disconnect(unsigned outputIndex) { ASSERT(isMainThread()); - AudioContext::AutoLocker locker(*context()); + AudioContext::AutoLocker locker(context()); // Sanity check input and output indices. - if (outputIndex >= numberOfOutputs()) { - ec = INDEX_SIZE_ERR; - return; - } + if (outputIndex >= numberOfOutputs()) + return Exception { INDEX_SIZE_ERR }; - AudioNodeOutput* output = this->output(outputIndex); + auto* output = this->output(outputIndex); output->disconnectAll(); + + return { }; } -unsigned long AudioNode::channelCount() +unsigned AudioNode::channelCount() { return m_channelCount; } -void AudioNode::setChannelCount(unsigned long channelCount, ExceptionCode& ec) +ExceptionOr<void> AudioNode::setChannelCount(unsigned channelCount) { ASSERT(isMainThread()); - AudioContext::AutoLocker locker(*context()); + AudioContext::AutoLocker locker(context()); - if (channelCount > 0 && channelCount <= AudioContext::maxNumberOfChannels()) { - if (m_channelCount != channelCount) { - m_channelCount = channelCount; - if (m_channelCountMode != Max) - updateChannelsForInputs(); - } - } else - ec = INVALID_STATE_ERR; + if (!(channelCount > 0 && channelCount <= AudioContext::maxNumberOfChannels())) + return Exception { INVALID_STATE_ERR }; + + if (m_channelCount == channelCount) + return { }; + + m_channelCount = channelCount; + if (m_channelCountMode != Max) + updateChannelsForInputs(); + return { }; } String AudioNode::channelCountMode() { switch (m_channelCountMode) { case Max: - return "max"; + return ASCIILiteral("max"); case ClampedMax: - return "clamped-max"; + return ASCIILiteral("clamped-max"); case Explicit: - return "explicit"; + return ASCIILiteral("explicit"); } ASSERT_NOT_REACHED(); - return ""; + return emptyString(); } -void AudioNode::setChannelCountMode(const String& mode, ExceptionCode& ec) +ExceptionOr<void> AudioNode::setChannelCountMode(const String& mode) { ASSERT(isMainThread()); - AudioContext::AutoLocker locker(*context()); + AudioContext::AutoLocker locker(context()); ChannelCountMode oldMode = m_channelCountMode; @@ -243,41 +230,45 @@ void AudioNode::setChannelCountMode(const String& mode, ExceptionCode& ec) else if (mode == "explicit") m_channelCountMode = Explicit; else - ec = INVALID_STATE_ERR; + return Exception { INVALID_STATE_ERR }; if (m_channelCountMode != oldMode) updateChannelsForInputs(); + + return { }; } String AudioNode::channelInterpretation() { switch (m_channelInterpretation) { case AudioBus::Speakers: - return "speakers"; + return ASCIILiteral("speakers"); case AudioBus::Discrete: - return "discrete"; + return ASCIILiteral("discrete"); } ASSERT_NOT_REACHED(); - return ""; + return emptyString(); } -void AudioNode::setChannelInterpretation(const String& interpretation, ExceptionCode& ec) +ExceptionOr<void> AudioNode::setChannelInterpretation(const String& interpretation) { ASSERT(isMainThread()); - AudioContext::AutoLocker locker(*context()); + AudioContext::AutoLocker locker(context()); if (interpretation == "speakers") m_channelInterpretation = AudioBus::Speakers; else if (interpretation == "discrete") m_channelInterpretation = AudioBus::Discrete; else - ec = INVALID_STATE_ERR; + return Exception { INVALID_STATE_ERR }; + + return { }; } void AudioNode::updateChannelsForInputs() { - for (unsigned i = 0; i < m_inputs.size(); ++i) - input(i)->changedOutputs(); + for (auto& input : m_inputs) + input->changedOutputs(); } EventTargetInterface AudioNode::eventTargetInterface() const @@ -287,12 +278,12 @@ EventTargetInterface AudioNode::eventTargetInterface() const ScriptExecutionContext* AudioNode::scriptExecutionContext() const { - return const_cast<AudioNode*>(this)->context()->scriptExecutionContext(); + return const_cast<AudioNode*>(this)->context().scriptExecutionContext(); } void AudioNode::processIfNecessary(size_t framesToProcess) { - ASSERT(context()->isAudioThread()); + ASSERT(context().isAudioThread()); if (!isInitialized()) return; @@ -301,7 +292,7 @@ void AudioNode::processIfNecessary(size_t framesToProcess) // This handles the "fanout" problem where an output is connected to multiple inputs. // The first time we're called during this time slice we process, but after that we don't want to re-process, // instead our output(s) will already have the results cached in their bus; - double currentTime = context()->currentTime(); + double currentTime = context().currentTime(); if (m_lastProcessingTime != currentTime) { m_lastProcessingTime = currentTime; // important to first update this time because of feedback loops in the rendering graph @@ -309,7 +300,7 @@ void AudioNode::processIfNecessary(size_t framesToProcess) bool silentInputs = inputsAreSilent(); if (!silentInputs) - m_lastNonSilentTime = (context()->currentSampleFrame() + framesToProcess) / static_cast<double>(m_sampleRate); + m_lastNonSilentTime = (context().currentSampleFrame() + framesToProcess) / static_cast<double>(m_sampleRate); if (silentInputs && propagatesSilence()) silenceOutputs(); @@ -322,9 +313,9 @@ void AudioNode::processIfNecessary(size_t framesToProcess) void AudioNode::checkNumberOfChannelsForInput(AudioNodeInput* input) { - ASSERT(context()->isAudioThread() && context()->isGraphOwner()); + ASSERT(context().isAudioThread() && context().isGraphOwner()); - for (const std::unique_ptr<AudioNodeInput>& savedInput : m_inputs) { + for (auto& savedInput : m_inputs) { if (input == savedInput.get()) { input->updateInternalBus(); return; @@ -336,22 +327,22 @@ void AudioNode::checkNumberOfChannelsForInput(AudioNodeInput* input) bool AudioNode::propagatesSilence() const { - return m_lastNonSilentTime + latencyTime() + tailTime() < context()->currentTime(); + return m_lastNonSilentTime + latencyTime() + tailTime() < context().currentTime(); } void AudioNode::pullInputs(size_t framesToProcess) { - ASSERT(context()->isAudioThread()); + ASSERT(context().isAudioThread()); // Process all of the AudioNodes connected to our inputs. - for (unsigned i = 0; i < m_inputs.size(); ++i) - input(i)->pull(0, framesToProcess); + for (auto& input : m_inputs) + input->pull(0, framesToProcess); } bool AudioNode::inputsAreSilent() { - for (unsigned i = 0; i < m_inputs.size(); ++i) { - if (!input(i)->bus()->isSilent()) + for (auto& input : m_inputs) { + if (!input->bus()->isSilent()) return false; } return true; @@ -359,25 +350,25 @@ bool AudioNode::inputsAreSilent() void AudioNode::silenceOutputs() { - for (unsigned i = 0; i < m_outputs.size(); ++i) - output(i)->bus()->zero(); + for (auto& output : m_outputs) + output->bus()->zero(); } void AudioNode::unsilenceOutputs() { - for (unsigned i = 0; i < m_outputs.size(); ++i) - output(i)->bus()->clearSilentFlag(); + for (auto& output : m_outputs) + output->bus()->clearSilentFlag(); } void AudioNode::enableOutputsIfNecessary() { if (m_isDisabled && m_connectionRefCount > 0) { ASSERT(isMainThread()); - AudioContext::AutoLocker locker(*context()); + AudioContext::AutoLocker locker(context()); m_isDisabled = false; - for (unsigned i = 0; i < m_outputs.size(); ++i) - output(i)->enable(); + for (auto& output : m_outputs) + output->enable(); } } @@ -401,8 +392,8 @@ void AudioNode::disableOutputsIfNecessary() // longer any active connections. if (nodeType() != NodeTypeConvolver && nodeType() != NodeTypeDelay) { m_isDisabled = true; - for (unsigned i = 0; i < m_outputs.size(); ++i) - output(i)->disable(); + for (auto& output : m_outputs) + output->disable(); } } } @@ -438,11 +429,11 @@ void AudioNode::deref(RefType refType) bool hasLock = false; bool mustReleaseLock = false; - if (context()->isAudioThread()) { + if (context().isAudioThread()) { // Real-time audio thread must not contend lock (to avoid glitches). - hasLock = context()->tryLock(mustReleaseLock); + hasLock = context().tryLock(mustReleaseLock); } else { - context()->lock(mustReleaseLock); + context().lock(mustReleaseLock); hasLock = true; } @@ -451,24 +442,24 @@ void AudioNode::deref(RefType refType) finishDeref(refType); if (mustReleaseLock) - context()->unlock(); + context().unlock(); } else { // We were unable to get the lock, so put this in a list to finish up later. - ASSERT(context()->isAudioThread()); + ASSERT(context().isAudioThread()); ASSERT(refType == RefTypeConnection); - context()->addDeferredFinishDeref(this); + context().addDeferredFinishDeref(this); } // Once AudioContext::uninitialize() is called there's no more chances for deleteMarkedNodes() to get called, so we call here. // We can't call in AudioContext::~AudioContext() since it will never be called as long as any AudioNode is alive // because AudioNodes keep a reference to the context. - if (context()->isAudioThreadFinished()) - context()->deleteMarkedNodes(); + if (context().isAudioThreadFinished()) + context().deleteMarkedNodes(); } void AudioNode::finishDeref(RefType refType) { - ASSERT(context()->isGraphOwner()); + ASSERT(context().isGraphOwner()); switch (refType) { case RefTypeNormal: @@ -491,11 +482,11 @@ void AudioNode::finishDeref(RefType refType) if (!m_normalRefCount) { if (!m_isMarkedForDeletion) { // All references are gone - we need to go away. - for (unsigned i = 0; i < m_outputs.size(); ++i) - output(i)->disconnectAll(); // This will deref() nodes we're connected to. + for (auto& output : m_outputs) + output->disconnectAll(); // This will deref() nodes we're connected to. // Mark for deletion at end of each render quantum or when context shuts down. - context()->markForDeletion(this); + context().markForDeletion(this); m_isMarkedForDeletion = true; } } else if (refType == RefTypeConnection) |