Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(817)

Unified Diff: third_party/WebKit/Source/modules/webaudio/AudioNode.cpp

Issue 2839063003: Implement tail processing for AudioNodes (Closed)
Patch Set: Make declaration order consistent Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/modules/webaudio/AudioNode.cpp
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioNode.cpp b/third_party/WebKit/Source/modules/webaudio/AudioNode.cpp
index 64cc1d575fa39161d2f8b3260d2c130396d932dd..1debbd08aab14746a0eab08410784ad308644af3 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioNode.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioNode.cpp
@@ -90,8 +90,6 @@ void AudioHandler::Uninitialize() {
is_initialized_ = false;
}
-void AudioHandler::ClearInternalStateWhenDisabled() {}
-
void AudioHandler::Dispose() {
DCHECK(IsMainThread());
DCHECK(Context()->IsGraphOwner());
@@ -325,12 +323,6 @@ void AudioHandler::ProcessIfNecessary(size_t frames_to_process) {
PullInputs(frames_to_process);
bool silent_inputs = InputsAreSilent();
- if (!silent_inputs) {
- last_non_silent_time_ =
- (Context()->CurrentSampleFrame() + frames_to_process) /
- static_cast<double>(Context()->sampleRate());
- }
-
if (silent_inputs && PropagatesSilence()) {
SilenceOutputs();
// AudioParams still need to be processed so that the value can be updated
@@ -345,6 +337,15 @@ void AudioHandler::ProcessIfNecessary(size_t frames_to_process) {
UnsilenceOutputs();
Process(frames_to_process);
}
+
+ if (!silent_inputs) {
+ // Update last_non_silent_time AFTER processing this block.
+ // Doing it before causes PropagateSilence to be one render
+ // quantum longer than necessary.
+ last_non_silent_time_ =
+ (Context()->CurrentSampleFrame() + frames_to_process) /
+ static_cast<double>(Context()->sampleRate());
+ }
}
}
@@ -402,6 +403,10 @@ void AudioHandler::EnableOutputsIfNecessary() {
}
void AudioHandler::DisableOutputsIfNecessary() {
+ // This function calls other functions that require graph ownership,
+ // so assert that this needs graph ownership too.
+ DCHECK(Context()->IsGraphOwner());
+
// Disable outputs if appropriate. We do this if the number of connections is
// 0 or 1. The case of 0 is from deref() where there are no connections left.
// The case of 1 is from AudioNodeInput::disable() where we want to disable
@@ -418,36 +423,35 @@ void AudioHandler::DisableOutputsIfNecessary() {
// they're connected to. disable() can recursively deref connections (and
// call disable()) down a whole chain of connected nodes.
- // TODO(rtoy,hongchan): we need special cases the convolver, delay, biquad,
- // and IIR since they have a significant tail-time and shouldn't be
- // disconnected simply because they no longer have any input connections.
- // This needs to be handled more generally where AudioNodes have a tailTime
- // attribute. Then the AudioNode only needs to remain "active" for tailTime
- // seconds after there are no longer any active connections.
- //
- // The analyser node also requires special handling because we
- // need the internal state to be updated for the time and FFT data
- // even if it has no connections.
- if (GetNodeType() != kNodeTypeConvolver &&
- GetNodeType() != kNodeTypeDelay &&
- GetNodeType() != kNodeTypeBiquadFilter &&
- GetNodeType() != kNodeTypeIIRFilter &&
- GetNodeType() != kNodeTypeAnalyser) {
- is_disabled_ = true;
- ClearInternalStateWhenDisabled();
- for (auto& output : outputs_)
- output->Disable();
+ // If a node requires tail processing, we defer the disabling of
+ // the outputs so that the tail for the node can be output.
+ // Otherwise, we can disable the outputs right away.
+ if (RequiresTailProcessing()) {
+ if (Context()->ContextState() !=
+ BaseAudioContext::AudioContextState::kClosed) {
+ Context()->GetDeferredTaskHandler().AddTailProcessingNode(this);
+ }
+ } else {
+ ReallyDisableOutputs();
}
}
}
+void AudioHandler::ReallyDisableOutputs() {
+ is_disabled_ = true;
+ for (auto& output : outputs_)
+ output->Disable();
+}
+
void AudioHandler::MakeConnection() {
AtomicIncrement(&connection_ref_count_);
+ Context()->GetDeferredTaskHandler().RemoveTailProcessingNode(this);
+
#if DEBUG_AUDIONODE_REFERENCES
- fprintf(stderr, "[%16p]: %16p: %2d: AudioHandler::ref %3d [%3d]\n",
+ fprintf(stderr, "[%16p]: %16p: %2d: AudioHandler::ref %3d [%3d] @%.15g\n",
Context(), this, GetNodeType(), connection_ref_count_,
- node_count_[GetNodeType()]);
+ node_count_[GetNodeType()], Context()->currentTime());
#endif
// See the disabling code in disableOutputsIfNecessary(). This handles
// the case where a node is being re-connected after being used at least
@@ -483,9 +487,9 @@ void AudioHandler::BreakConnectionWithLock() {
AtomicDecrement(&connection_ref_count_);
#if DEBUG_AUDIONODE_REFERENCES
- fprintf(stderr, "[%16p]: %16p: %2d: AudioHandler::deref %3d [%3d]\n",
+ fprintf(stderr, "[%16p]: %16p: %2d: AudioHandler::deref %3d [%3d] @%.15g\n",
Context(), this, GetNodeType(), connection_ref_count_,
- node_count_[GetNodeType()]);
+ node_count_[GetNodeType()], Context()->currentTime());
#endif
if (!connection_ref_count_)
@@ -511,6 +515,31 @@ void AudioHandler::PrintNodeCounts() {
#endif // DEBUG_AUDIONODE_REFERENCES
+#if DEBUG_AUDIONODE_REFERENCES > 1
+void AudioHandler::TailProcessingDebug(const char* note) {
+ fprintf(stderr, "[%16p]: %16p: %2d: %s %d @%.15g", Context(), this,
+ GetNodeType(), note, connection_ref_count_, Context()->currentTime());
+
+ // If we're on the audio thread, we can print out the tail and
+ // latency times (because these methods can only be called from the
+ // audio thread.)
+ if (Context()->IsAudioThread()) {
+ fprintf(stderr, ", tail=%.15g + %.15g, last=%.15g\n", TailTime(),
+ LatencyTime(), last_non_silent_time_);
+ }
+
+ fprintf(stderr, "\n");
+}
+
+void AudioHandler::AddTailProcessingDebug() {
+ TailProcessingDebug("addTail");
+}
+
+void AudioHandler::RemoveTailProcessingDebug() {
+ TailProcessingDebug("remTail");
+}
+#endif // DEBUG_AUDIONODE_REFERENCES > 1
+
void AudioHandler::UpdateChannelCountMode() {
channel_count_mode_ = new_channel_count_mode_;
UpdateChannelsForInputs();

Powered by Google App Engine
This is Rietveld 408576698