Commit 26776eab authored by rtoy@chromium.org's avatar rtoy@chromium.org

Make realtimeanalyser-fft-scaling test more robust

The failures on Windows Debug is probably due to a timing issue where
the FFT samples were grabbed at an unexpected time.  If the grabbed
time sample isn't a multiple of a full cycle and doesn't start at 0,
the FFT result is affected which can change the peak position and value.
This is aggravated by the Blackman window that is applied which smears the peak out anyway.

This is partly due to the use of one context for all of the
different-sized analyzers.  This CL replaces that with a separate
offline context for each analyzer test that should guarantee that
right time samples are used.

BUG=349523

Review URL: https://codereview.chromium.org/316293002

git-svn-id: svn://svn.chromium.org/blink/trunk@175806 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent fa99d848
......@@ -831,7 +831,6 @@ crbug.com/309197 [ Win Debug ] webaudio/oscillator-custom.html [ Skip ]
crbug.com/309197 [ Win Debug ] webaudio/oscillator-sine.html [ Skip ]
crbug.com/309197 [ Win Debug ] webaudio/oscillator-square.html [ Skip ]
crbug.com/349523 [ Win ] webaudio/realtimeanalyser-fft-scaling.html [ Failure ]
crbug.com/352464 http/tests/security/dataURL/xss-DENIED-to-data-url-in-foreign-domain-subframe-location-change.html [ Pass Failure Missing ]
crbug.com/372425 http/tests/security/dataURL/xss-DENIED-to-data-url-in-foreign-domain-subframe.html [ Pass Failure Timeout ]
crbug.com/372428 http/tests/security/dataURL/xss-DENIED-to-data-url-in-foreign-domain-window-open.html [ Pass Failure ]
......
......@@ -2,26 +2,26 @@ Test scaling of FFT data for AnalyserNode
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS Actual FFT peak in the expected position (1)
PASS Peak value is near 0 dBFS as expected
PASS Actual FFT peak in the expected position (1).
PASS Peak value is near -14.43 dBFS as expected.
PASS Analyser correctly scaled FFT data of size 32
PASS Actual FFT peak in the expected position (2)
PASS Peak value is near 0 dBFS as expected
PASS Actual FFT peak in the expected position (2).
PASS Peak value is near -13.56 dBFS as expected.
PASS Analyser correctly scaled FFT data of size 64
PASS Actual FFT peak in the expected position (4)
PASS Peak value is near 0 dBFS as expected
PASS Actual FFT peak in the expected position (4).
PASS Peak value is near -13.56 dBFS as expected.
PASS Analyser correctly scaled FFT data of size 128
PASS Actual FFT peak in the expected position (8)
PASS Peak value is near 0 dBFS as expected
PASS Actual FFT peak in the expected position (8).
PASS Peak value is near -13.56 dBFS as expected.
PASS Analyser correctly scaled FFT data of size 256
PASS Actual FFT peak in the expected position (16)
PASS Peak value is near 0 dBFS as expected
PASS Actual FFT peak in the expected position (16).
PASS Peak value is near -13.56 dBFS as expected.
PASS Analyser correctly scaled FFT data of size 512
PASS Actual FFT peak in the expected position (32)
PASS Peak value is near 0 dBFS as expected
PASS Actual FFT peak in the expected position (32).
PASS Peak value is near -13.56 dBFS as expected.
PASS Analyser correctly scaled FFT data of size 1024
PASS Actual FFT peak in the expected position (64)
PASS Peak value is near 0 dBFS as expected
PASS Actual FFT peak in the expected position (64).
PASS Peak value is near -13.56 dBFS as expected.
PASS Analyser correctly scaled FFT data of size 2048
PASS All Analyser tests passed.
PASS successfullyParsed is true
......
......@@ -14,14 +14,18 @@
description("Test scaling of FFT data for AnalyserNode");
// The number of analysers. We have analysers from size for each of the possible sizes of 32,
// 64, 128, 256, 512, 1024 and 2048.
// 64, 128, 256, 512, 1024 and 2048 for a total of 7.
var numberOfAnalysers = 7;
var sampleRate = 44100;
var context;
var osc;
var oscFrequency = sampleRate/32;
var analysers = new Array(7);
var peakValue = new Array(7);
var nyquistFrequency = sampleRate / 2;
// Frequency of the sine wave test signal. Should be high enough so that we get at least one
// full cycle for the 32-point FFT. This should also be such that the frequency should be
// exactly in one of the FFT bins for each of the possible FFT sizes.
var oscFrequency = nyquistFrequency/16;
// The actual peak values from each analyser. Useful for examining the results in Chrome.
var peakValue = new Array(numberOfAnalysers);
// For a 0dBFS sine wave, we would expect the FFT magnitude to be 0dB as well, but the
// analyzer node applies a Blackman window (to smooth the estimate). This reduces the energy
......@@ -31,63 +35,65 @@
// See https://code.google.com/p/chromium/issues/detail?id=341596.
var peakThreshold = [-14.43, -13.56, -13.56, -13.56, -13.56, -13.56, -13.56];
function checkResult() {
var allTestsPassed = true;
for (n = 0; n < analysers.length; ++n) {
// Grab the FFT data from each analyser.
var fftSize = analysers[n].fftSize;
var fftData = new Float32Array(fftSize);
analysers[n].getFloatFrequencyData(fftData);
// Compute the frequency bin that should contain the peak.
var expectedBin = fftSize * (oscFrequency / sampleRate);
// Find the actual bin by finding the bin containing the peak.
var actualBin = 0;
peakValue[n] = -1000;
for (k = 0; k < analysers[n].frequencyBinCount; ++k) {
if (fftData[k] > peakValue[n]) {
actualBin = k;
peakValue[n] = fftData[k];
}
}
var success = true;
if (actualBin == expectedBin) {
testPassed("Actual FFT peak in the expected position (" + expectedBin + ")");
} else {
success = false;
testFailed("Actual FFT peak (" + actualBin + ") differs from expected (" + expectedBin + ")");
}
if (peakValue[n] >= peakThreshold[n]) {
testPassed("Peak value is near 0 dBFS as expected");
} else {
success = false;
testFailed("Peak value of " + peakValue[n]
var allTestsPassed = true;
function checkResult(order, analyser) {
return function () {
var index = order - 5;
var fftSize = 1 << order;
var fftData = new Float32Array(fftSize);
analyser.getFloatFrequencyData(fftData);
// Compute the frequency bin that should contain the peak.
var expectedBin = analyser.frequencyBinCount * (oscFrequency / nyquistFrequency);
// Find the actual bin by finding the bin containing the peak.
var actualBin = 0;
peakValue[index] = -1000;
for (k = 0; k < analyser.frequencyBinCount; ++k) {
if (fftData[k] > peakValue[index]) {
actualBin = k;
peakValue[index] = fftData[k];
}
}
var success = true;
if (actualBin == expectedBin) {
testPassed("Actual FFT peak in the expected position (" + expectedBin + ").");
} else {
success = false;
testFailed("Actual FFT peak (" + actualBin + ") differs from expected (" + expectedBin + ").");
}
if (peakValue[index] >= peakThreshold[index]) {
testPassed("Peak value is near " + peakThreshold[index] + " dBFS as expected.");
} else {
success = false;
testFailed("Peak value of " + peakValue[index]
+ " is incorrect. (Expected approximately "
+ peakThreshold[n] + ")");
}
if (success) {
testPassed("Analyser correctly scaled FFT data of size " + fftSize);
} else {
testFailed("Analyser incorrectly scaled FFT data of size " + fftSize);
}
allTestsPassed = allTestsPassed && success;
}
if (allTestsPassed) {
testPassed("All Analyser tests passed.");
} else {
testFailed("At least one Analyser test failed.");
}
finishJSTest();
+ peakThreshold[index] + ").");
}
if (success) {
testPassed("Analyser correctly scaled FFT data of size " + fftSize);
} else {
testFailed("Analyser incorrectly scaled FFT data of size " + fftSize);
}
allTestsPassed = allTestsPassed && success;
if (fftSize == 2048) {
if (allTestsPassed) {
testPassed("All Analyser tests passed.");
} else {
testFailed("At least one Analyser test failed.");
}
finishJSTest();
}
}
}
function runTests() {
if (window.testRunner) {
testRunner.dumpAsText();
......@@ -96,26 +102,28 @@
window.jsTestIsAsync = true;
context = new OfflineAudioContext(1, 2048, sampleRate);
// Use a sine wave oscillator as the reference source signal.
osc = context.createOscillator();
osc.type = "sine";
osc.frequency.value = oscFrequency;
osc.connect(context.destination);
// Create an analyser node for each of the possible valid sizes.
// Test each analyser size from order 5 (size 32) to 11 (size 2048).
for (order = 5; order < 12; ++order) {
analysers[order - 5] = context.createAnalyser();
// No smoothing so between frames to simplify testing.
analysers[order - 5].smoothingTimeConstant = 0;
analysers[order - 5].fftSize = 1 << order;
osc.connect(analysers[order - 5]);
// Create a new offline context for each analyser test with the number of samples
// exactly equal to the fft size. This ensures that the analyser node gets the
// expected data from the oscillator.
var context = new OfflineAudioContext(1, 1 << order, sampleRate);
// Use a sine wave oscillator as the reference source signal.
var osc = context.createOscillator();
osc.type = "sine";
osc.frequency.value = oscFrequency;
osc.connect(context.destination);
var analyser = context.createAnalyser();
// No smoothing to simplify the analysis of the result.
analyser.smoothingTimeConstant = 0;
analyser.fftSize = 1 << order;
osc.connect(analyser);
osc.start();
context.oncomplete = checkResult(order, analyser);
context.startRendering();
}
osc.start();
context.oncomplete = checkResult;
context.startRendering();
}
runTests();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment