summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-scaling.html
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-scaling.html')
-rw-r--r--testing/web-platform/tests/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-scaling.html111
1 files changed, 111 insertions, 0 deletions
diff --git a/testing/web-platform/tests/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-scaling.html b/testing/web-platform/tests/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-scaling.html
new file mode 100644
index 0000000000..043bd5890a
--- /dev/null
+++ b/testing/web-platform/tests/webaudio/the-audio-api/the-analysernode-interface/realtimeanalyser-fft-scaling.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>
+ realtimeanalyser-fft-scaling.html
+ </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/webaudio/resources/audit-util.js"></script>
+ <script src="/webaudio/resources/audit.js"></script>
+ </head>
+ <body>
+ <div id="description"></div>
+ <div id="console"></div>
+ <script id="layout-test-code">
+ let audit = Audit.createTaskRunner();
+
+ // The number of analysers. We have analysers from size for each of the
+ // possible sizes of 2^5 to 2^15 for a total of 11.
+ let numberOfAnalysers = 11;
+ let sampleRate = 44100;
+ let 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.
+ let oscFrequency = nyquistFrequency / 16;
+
+ // The actual peak values from each analyser. Useful for examining the
+ // actual peak values.
+ let 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 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.
+ let peakThreshold = [
+ -14.43, -13.56, -13.56, -13.56, -13.56, -13.56, -13.56, -13.56, -13.56,
+ -13.56, -13.56
+ ];
+
+ function checkResult(order, analyser, should) {
+ return function() {
+ let index = order - 5;
+ let fftSize = 1 << order;
+ let fftData = new Float32Array(fftSize);
+ analyser.getFloatFrequencyData(fftData);
+
+ // Compute the frequency bin that should contain the peak.
+ let expectedBin =
+ analyser.frequencyBinCount * (oscFrequency / nyquistFrequency);
+
+ // Find the actual bin by finding the bin containing the peak.
+ let actualBin = 0;
+ peakValue[index] = -1000;
+ for (k = 0; k < analyser.frequencyBinCount; ++k) {
+ if (fftData[k] > peakValue[index]) {
+ actualBin = k;
+ peakValue[index] = fftData[k];
+ }
+ }
+
+ should(actualBin, (1 << order) + '-point FFT peak position')
+ .beEqualTo(expectedBin);
+
+ should(
+ peakValue[index], (1 << order) + '-point FFT peak value in dBFS')
+ .beGreaterThanOrEqualTo(peakThreshold[index]);
+ }
+ }
+
+ audit.define(
+ {
+ label: 'FFT scaling tests',
+ description: 'Test Scaling of FFT in AnalyserNode'
+ },
+ async function(task, should) {
+ let tests = [];
+ for (let k = 5; k <= 15; ++k)
+ await runTest(k, should);
+ task.done();
+ });
+
+ function runTest(order, should) {
+ let context = new OfflineAudioContext(1, 1 << order, sampleRate);
+ // Use a sine wave oscillator as the reference source signal.
+ let osc = context.createOscillator();
+ osc.type = 'sine';
+ osc.frequency.value = oscFrequency;
+ osc.connect(context.destination);
+
+ let analyser = context.createAnalyser();
+ // No smoothing to simplify the analysis of the result.
+ analyser.smoothingTimeConstant = 0;
+ analyser.fftSize = 1 << order;
+ osc.connect(analyser);
+
+ osc.start();
+ return context.startRendering().then(() => {
+ checkResult(order, analyser, should)();
+ });
+ }
+
+ audit.run();
+ </script>
+ </body>
+</html>