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

Unified Diff: third_party/WebKit/LayoutTests/webaudio/resources/biquad-filters.js

Issue 1361233004: Implement IIRFilter node for WebAudio. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix test issue by printing fewer digits. Created 4 years, 11 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/LayoutTests/webaudio/resources/biquad-filters.js
diff --git a/third_party/WebKit/LayoutTests/webaudio/resources/biquad-testing.js b/third_party/WebKit/LayoutTests/webaudio/resources/biquad-filters.js
similarity index 60%
copy from third_party/WebKit/LayoutTests/webaudio/resources/biquad-testing.js
copy to third_party/WebKit/LayoutTests/webaudio/resources/biquad-filters.js
index 8d8077ba12d7b037497f3a32918bb849bdfde97b..c2517694218bcc5408b09ed4107dc6d0d121cfce 100644
--- a/third_party/WebKit/LayoutTests/webaudio/resources/biquad-testing.js
+++ b/third_party/WebKit/LayoutTests/webaudio/resources/biquad-filters.js
@@ -1,33 +1,3 @@
-// Globals, to make testing and debugging easier.
-var context;
-var filter;
-var signal;
-var renderedBuffer;
-var renderedData;
-
-var sampleRate = 44100.0;
-var pulseLengthFrames = .1 * sampleRate;
-
-// Maximum allowed error for the test to succeed. Experimentally determined.
-var maxAllowedError = 5.9e-8;
-
-// This must be large enough so that the filtered result is
-// essentially zero. See comments for createTestAndRun.
-var timeStep = .1;
-
-// Maximum number of filters we can process (mostly for setting the
-// render length correctly.)
-var maxFilters = 5;
-
-// How long to render. Must be long enough for all of the filters we
-// want to test.
-var renderLengthSeconds = timeStep * (maxFilters + 1) ;
-
-var renderLengthSamples = Math.round(renderLengthSeconds * sampleRate);
-
-// Number of filters that will be processed.
-var nFilters;
-
// A biquad filter has a z-transform of
// H(z) = (b0 + b1 / z + b2 / z^2) / (1 + a1 / z + a2 / z^2)
//
@@ -156,7 +126,7 @@ function createBandpassFilter(freq, q, gain) {
// independent of q.
coef = {b0 : 0, b1 : 0, b2 : 0, a1 : 0, a2 : 0}
}
-
+
return coef;
}
@@ -169,16 +139,16 @@ function createLowShelfFilter(freq, q, gain) {
var a1;
var a2;
var coef;
-
+
var S = 1;
var A = Math.pow(10, gain / 40);
if (freq == 1) {
// The filter is just a constant gain
- coef = {b0 : A * A, b1 : 0, b2 : 0, a1 : 0, a2 : 0};
+ coef = {b0 : A * A, b1 : 0, b2 : 0, a1 : 0, a2 : 0};
} else if (freq == 0) {
// The filter is 1
- coef = {b0 : 1, b1 : 0, b2 : 0, a1 : 0, a2 : 0};
+ coef = {b0 : 1, b1 : 0, b2 : 0, a1 : 0, a2 : 0};
} else {
var w0 = Math.PI * freq;
var alpha = 1 / 2 * Math.sin(w0) * Math.sqrt((A + 1 / A) * (1 / S - 1) + 2);
@@ -262,7 +232,7 @@ function createPeakingFilter(freq, q, gain) {
a0 = 1 + alpha / A;
a1 = -2 * k;
a2 = 1 - alpha / A;
-
+
coef = normalizeFilterCoefficients(b0, b1, b2, a0, a1, a2);
} else {
// q = 0, we have a divide by zero problem in the formulas
@@ -347,30 +317,6 @@ function createAllpassFilter(freq, q, gain) {
return coef;
}
-// Map the filter type name to a function that computes the filter coefficents for the given filter
-// type.
-var filterCreatorFunction = {"lowpass": createLowpassFilter,
- "highpass": createHighpassFilter,
- "bandpass": createBandpassFilter,
- "lowshelf": createLowShelfFilter,
- "highshelf": createHighShelfFilter,
- "peaking": createPeakingFilter,
- "notch": createNotchFilter,
- "allpass": createAllpassFilter};
-
-var filterTypeName = {"lowpass": "Lowpass filter",
- "highpass": "Highpass filter",
- "bandpass": "Bandpass filter",
- "lowshelf": "Lowshelf filter",
- "highshelf": "Highshelf filter",
- "peaking": "Peaking filter",
- "notch": "Notch filter",
- "allpass": "Allpass filter"};
-
-function createFilter(filterType, freq, q, gain) {
- return filterCreatorFunction[filterType](freq, q, gain);
-}
-
function filterData(filterCoef, signal, len) {
var y = new Array(len);
var b0 = filterCoef.b0;
@@ -397,152 +343,26 @@ function filterData(filterCoef, signal, len) {
return y;
}
-function createImpulseBuffer(context, length) {
- var impulse = context.createBuffer(1, length, context.sampleRate);
- var data = impulse.getChannelData(0);
- for (var k = 1; k < data.length; ++k) {
- data[k] = 0;
- }
- data[0] = 1;
-
- return impulse;
-}
-
-
-function createTestAndRun(context, filterType, filterParameters) {
- // To test the filters, we apply a signal (an impulse) to each of
- // the specified filters, with each signal starting at a different
- // time. The output of the filters is summed together at the
- // output. Thus for filter k, the signal input to the filter
- // starts at time k * timeStep. For this to work well, timeStep
- // must be large enough for the output of each filter to have
- // decayed to zero with timeStep seconds. That way the filter
- // outputs don't interfere with each other.
-
- nFilters = Math.min(filterParameters.length, maxFilters);
-
- signal = new Array(nFilters);
- filter = new Array(nFilters);
-
- impulse = createImpulseBuffer(context, pulseLengthFrames);
-
- // Create all of the signal sources and filters that we need.
- for (var k = 0; k < nFilters; ++k) {
- signal[k] = context.createBufferSource();
- signal[k].buffer = impulse;
-
- filter[k] = context.createBiquadFilter();
- filter[k].type = filterType;
- filter[k].frequency.value = context.sampleRate / 2 * filterParameters[k].cutoff;
- filter[k].detune.value = (filterParameters[k].detune === undefined) ? 0 : filterParameters[k].detune;
- filter[k].Q.value = filterParameters[k].q;
- filter[k].gain.value = filterParameters[k].gain;
-
- signal[k].connect(filter[k]);
- filter[k].connect(context.destination);
-
- signal[k].start(timeStep * k);
- }
-
- context.oncomplete = checkFilterResponse(filterType, filterParameters);
- context.startRendering();
-}
-
-function addSignal(dest, src, destOffset) {
- // Add src to dest at the given dest offset.
- for (var k = destOffset, j = 0; k < dest.length, j < src.length; ++k, ++j) {
- dest[k] += src[j];
- }
-}
-
-function generateReference(filterType, filterParameters) {
- var result = new Array(renderLengthSamples);
- var data = new Array(renderLengthSamples);
- // Initialize the result array and data.
- for (var k = 0; k < result.length; ++k) {
- result[k] = 0;
- data[k] = 0;
- }
- // Make data an impulse.
- data[0] = 1;
-
- for (var k = 0; k < nFilters; ++k) {
- // Filter an impulse
- var detune = (filterParameters[k].detune === undefined) ? 0 : filterParameters[k].detune;
- var frequency = filterParameters[k].cutoff * Math.pow(2, detune / 1200); // Apply detune, converting from Cents.
-
- var filterCoef = createFilter(filterType,
- frequency,
- filterParameters[k].q,
- filterParameters[k].gain);
- var y = filterData(filterCoef, data, renderLengthSamples);
-
- // Accumulate this filtered data into the final output at the desired offset.
- addSignal(result, y, timeToSampleFrame(timeStep * k, sampleRate));
- }
-
- return result;
-}
-
-function checkFilterResponse(filterType, filterParameters) {
- return function(event) {
- renderedBuffer = event.renderedBuffer;
- renderedData = renderedBuffer.getChannelData(0);
-
- reference = generateReference(filterType, filterParameters);
-
- var len = Math.min(renderedData.length, reference.length);
-
- var success = true;
-
- // Maximum error between rendered data and expected data
- var maxError = 0;
-
- // Sample offset where the maximum error occurred.
- var maxPosition = 0;
-
- // Number of infinities or NaNs that occurred in the rendered data.
- var invalidNumberCount = 0;
-
- if (nFilters != filterParameters.length) {
- testFailed("Test wanted " + filterParameters.length + " filters but only " + maxFilters + " allowed.");
- success = false;
- }
+// Map the filter type name to a function that computes the filter coefficents for the given filter
+// type.
+var filterCreatorFunction = {"lowpass": createLowpassFilter,
+ "highpass": createHighpassFilter,
+ "bandpass": createBandpassFilter,
+ "lowshelf": createLowShelfFilter,
+ "highshelf": createHighShelfFilter,
+ "peaking": createPeakingFilter,
+ "notch": createNotchFilter,
+ "allpass": createAllpassFilter};
- // Compare the rendered signal with our reference, keeping
- // track of the maximum difference (and the offset of the max
- // difference.) Check for bad numbers in the rendered output
- // too. There shouldn't be any.
- for (var k = 0; k < len; ++k) {
- var err = Math.abs(renderedData[k] - reference[k]);
- if (err > maxError) {
- maxError = err;
- maxPosition = k;
- }
- if (!isValidNumber(renderedData[k])) {
- ++invalidNumberCount;
- }
- }
+var filterTypeName = {"lowpass": "Lowpass filter",
+ "highpass": "Highpass filter",
+ "bandpass": "Bandpass filter",
+ "lowshelf": "Lowshelf filter",
+ "highshelf": "Highshelf filter",
+ "peaking": "Peaking filter",
+ "notch": "Notch filter",
+ "allpass": "Allpass filter"};
- if (invalidNumberCount > 0) {
- testFailed("Rendered output has " + invalidNumberCount + " infinities or NaNs.");
- success = false;
- } else {
- testPassed("Rendered output did not have infinities or NaNs.");
- }
-
- if (maxError <= maxAllowedError) {
- testPassed(filterTypeName[filterType] + " response is correct.");
- } else {
- testFailed(filterTypeName[filterType] + " response is incorrect. Max err = " + maxError + " at " + maxPosition + ". Threshold = " + maxAllowedError);
- success = false;
- }
-
- if (success) {
- testPassed("Test signal was correctly filtered.");
- } else {
- testFailed("Test signal was not correctly filtered.");
- }
- finishJSTest();
- }
+function createFilter(filterType, freq, q, gain) {
+ return filterCreatorFunction[filterType](freq, q, gain);
}

Powered by Google App Engine
This is Rietveld 408576698