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

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

Issue 2857833003: Print warning if IIR filter is unstable (Closed)
Patch Set: Use stable IIR filter for test. Created 3 years, 7 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
« no previous file with comments | « third_party/WebKit/LayoutTests/webaudio/IIRFilter/iir-unstable-expected.txt ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Source/modules/webaudio/IIRFilterNode.cpp
diff --git a/third_party/WebKit/Source/modules/webaudio/IIRFilterNode.cpp b/third_party/WebKit/Source/modules/webaudio/IIRFilterNode.cpp
index 42adea144361130b807f4928fe9be9d1f3897cd5..f8a525df2d2872afa8cde349a93040326ca91315 100644
--- a/third_party/WebKit/Source/modules/webaudio/IIRFilterNode.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/IIRFilterNode.cpp
@@ -7,6 +7,7 @@
#include "bindings/core/v8/ExceptionMessages.h"
#include "bindings/core/v8/ExceptionState.h"
#include "core/dom/ExceptionCode.h"
+#include "core/inspector/ConsoleMessage.h"
#include "modules/webaudio/AudioBasicProcessorHandler.h"
#include "modules/webaudio/BaseAudioContext.h"
#include "modules/webaudio/IIRFilterOptions.h"
@@ -15,6 +16,51 @@
namespace blink {
+// Determine if filter is stable based on the feedback coefficients.
+// We compute the reflection coefficients for the filter. If, at any
+// point, the magnitude of the reflection coefficient is greater than
+// or equal to 1, the filter is declared unstable.
+//
+// Let A(z) be the feedback polynomial given by
+// A[n](z) = 1 + a[1]/z + a[2]/z^2 + ... + a[n]/z^n
+//
+// The first reflection coefficient k[n] = a[n]. Then, recursively compute
+//
+// A[n-1](z) = (A[n](z) - k[n]*A[n](1/z)/z^n)/(1-k[n]^2);
+//
+// stopping at A[1](z). If at any point |k[n]| >= 1, the filter is
+// unstable.
+static bool IsFilterStable(const Vector<double>& feedback_coef) {
+ // Make a copy of the feedback coefficients
+ Vector<double> coef(feedback_coef);
+ int order = coef.size() - 1;
+
+ // If necessary, normalize filter coefficients so that constant term is 1.
+ if (coef[0] != 1) {
+ for (int m = 1; m <= order; ++m)
+ coef[m] /= coef[0];
+ coef[0] = 1;
+ }
+
+ // Begin recursion, using a work array to hold intermediate results.
+ Vector<double> work(order + 1);
+ for (int n = order; n >= 1; --n) {
+ double k = coef[n];
+
+ if (std::fabs(k) >= 1)
+ return false;
+
+ // Note that A[n](1/z)/z^n is basically the coefficients of A[n]
+ // in reverse order.
+ double factor = 1 - k * k;
+ for (int m = 0; m <= n; ++m)
+ work[m] = (coef[m] - k * coef[n - m]) / factor;
+ coef.swap(work);
+ }
+
+ return true;
+}
+
IIRFilterNode::IIRFilterNode(BaseAudioContext& context,
const Vector<double>& feedforward_coef,
const Vector<double>& feedback_coef)
@@ -88,6 +134,20 @@ IIRFilterNode* IIRFilterNode::Create(BaseAudioContext& context,
return nullptr;
}
+ if (!IsFilterStable(feedback_coef)) {
+ StringBuilder message;
+ message.Append("Unstable IIRFilter with feedback coefficients: [");
+ message.AppendNumber(feedback_coef[0]);
+ for (size_t k = 1; k < feedback_coef.size(); ++k) {
+ message.Append(", ");
+ message.AppendNumber(feedback_coef[k]);
+ }
+ message.Append(']');
+
+ context.GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create(
+ kJSMessageSource, kWarningMessageLevel, message.ToString()));
+ }
+
return new IIRFilterNode(context, feedforward_coef, feedback_coef);
}
« no previous file with comments | « third_party/WebKit/LayoutTests/webaudio/IIRFilter/iir-unstable-expected.txt ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698