Index: LayoutTests/webaudio/realtimeanalyser-fft-scaling.html |
diff --git a/LayoutTests/webaudio/realtimeanalyser-fft-scaling.html b/LayoutTests/webaudio/realtimeanalyser-fft-scaling.html |
new file mode 100644 |
index 0000000000000000000000000000000000000000..711633d548f9632bebe73cb2f42f4f5d370ff1b3 |
--- /dev/null |
+++ b/LayoutTests/webaudio/realtimeanalyser-fft-scaling.html |
@@ -0,0 +1,124 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
+<html> |
+ <head> |
+ <script src="../resources/js-test.js"></script> |
+ <script src="resources/audio-testing.js"></script> |
+ </head> |
+ |
+ <body> |
+ <div id="description"></div> |
+ <div id="console"></div> |
+ |
+ <script> |
+ 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. |
+ var numberOfAnalysers = 7; |
+ var sampleRate = 44100; |
+ var context; |
+ var osc; |
+ var oscFrequency = sampleRate/32; |
+ var analysers = new Array(7); |
+ var peakValue = new Array(7); |
+ |
+ // 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 |
+ // of the signal so the FFT peak is less than 0dB. The threshold value given here was |
+ // determined experimentally. |
+ // |
+ // See https://code.google.com/p/chromium/issues/detail?id=341596. |
+ var peakThreshold = [-8.41, -7.54, -7.54, -7.54, -7.54, -7.54, -7.54]; |
+ |
+ 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] |
+ + " 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(); |
+ } |
+ |
+ function runTests() { |
+ if (window.testRunner) { |
+ testRunner.dumpAsText(); |
+ testRunner.waitUntilDone(); |
+ } |
+ |
+ window.jsTestIsAsync = true; |
+ |
+ context = new webkitOfflineAudioContext(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. |
+ 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]); |
+ } |
+ |
+ osc.start(); |
+ context.oncomplete = checkResult; |
+ context.startRendering(); |
+ } |
+ |
+ runTests(); |
+ successfullyParsed = true; |
+ </script> |
+ </body> |
+</html> |