121 lines
4.5 KiB
HTML
121 lines
4.5 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>
|
|
Test fftSize Changes Resetting AnalyserNode State
|
|
</title>
|
|
<script src="../../imported/w3c/web-platform-tests/resources/testharness.js"></script>
|
|
<script src="../../resources/testharnessreport.js"></script>
|
|
<script src="../resources/audit-util.js"></script>
|
|
<script src="../resources/audit.js"></script>
|
|
</head>
|
|
<body>
|
|
<script id="layout-test-code">
|
|
// Fairly arbitrary sample rate.
|
|
let sampleRate = 24000;
|
|
|
|
let audit = Audit.createTaskRunner();
|
|
|
|
// Verify that setting the fftSize resets the memory for the FFT smoothing
|
|
// operation. Only a few of the possible variations are tested.
|
|
|
|
audit.define('128->1024', (task, should) => {
|
|
testFFTSize(should, {
|
|
initialFFTSize: 128,
|
|
finalFFTSize: 1024,
|
|
errorThreshold: {relativeThreshold: 3.6296e-6}
|
|
}).then(() => task.done());
|
|
});
|
|
|
|
audit.define('512->256', (task, should) => {
|
|
testFFTSize(should, {
|
|
initialFFTSize: 512,
|
|
finalFFTSize: 256,
|
|
errorThreshold: {relativeThreshold: 1.8614e-6}
|
|
}).then(() => task.done());
|
|
});
|
|
|
|
function testFFTSize(should, options) {
|
|
let {initialFFTSize, finalFFTSize, errorThreshold} = options;
|
|
|
|
// The duration is fairly arbitrary as long as it's long enough for the
|
|
// FFT test.
|
|
let context = new OfflineAudioContext(1, sampleRate, sampleRate);
|
|
|
|
// Actual source doesn't matter but a sawtooth is a nice waveform with
|
|
// lots of harmonic content.
|
|
let osc = context.createOscillator();
|
|
osc.type = 'sawtooth';
|
|
|
|
// The analyser under test.
|
|
let testAnalyser = context.createAnalyser();
|
|
testAnalyser.fftSize = initialFFTSize;
|
|
|
|
// The reference analyser. The fftSize is fixed to the desired value,
|
|
// and we turn off smoothing so that we get the FFT of the current time
|
|
// data.
|
|
let refAnalyser = context.createAnalyser();
|
|
refAnalyser.fftSize = finalFFTSize;
|
|
refAnalyser.smoothingTimeConstant = 0;
|
|
|
|
// Setup the graph and start the oscillator.
|
|
osc.connect(testAnalyser).connect(context.destination);
|
|
osc.connect(refAnalyser).connect(context.destination);
|
|
|
|
osc.start();
|
|
|
|
// Let the analyser smooth a few FFTs (rather arbitrary, but should be
|
|
// more than one), then switch the size.
|
|
|
|
let suspendFrame = 4 * initialFFTSize;
|
|
context.suspend(suspendFrame / context.sampleRate)
|
|
.then(function() {
|
|
testAnalyser.fftSize = finalFFTSize;
|
|
})
|
|
.then(context.resume.bind(context));
|
|
|
|
// Wait some frames and grab the FFT data. This is fairly arbitrary
|
|
// too, and can be independent of the FFT sizes.
|
|
suspendFrame += 1024;
|
|
context.suspend(suspendFrame / context.sampleRate)
|
|
.then(function() {
|
|
let testFFT = new Float32Array(testAnalyser.frequencyBinCount);
|
|
let refFFT = new Float32Array(refAnalyser.frequencyBinCount)
|
|
let testSignal = new Float32Array(testAnalyser.fftSize);
|
|
let refSignal = new Float32Array(refAnalyser.fftSize);
|
|
|
|
testAnalyser.getFloatTimeDomainData(testSignal);
|
|
refAnalyser.getFloatTimeDomainData(refSignal);
|
|
|
|
testAnalyser.getFloatFrequencyData(testFFT);
|
|
refAnalyser.getFloatFrequencyData(refFFT);
|
|
|
|
// Convert the FFT data from dB to linear
|
|
testFFT = testFFT.map(x => Math.pow(10, x / 20));
|
|
refFFT = refFFT.map(x => Math.pow(10, x / 20));
|
|
|
|
// The test data has smoothing applied, but the reference doesn't.
|
|
// Apply the smoothing factor to the reference data.
|
|
let smoothing = 1 - testAnalyser.smoothingTimeConstant;
|
|
refFFT = refFFT.map(x => x * smoothing);
|
|
|
|
// First a basic sanity check that the time domain signals are
|
|
// exactly the same for both analysers.
|
|
should(testSignal, 'Time data').beCloseToArray(refSignal, 0);
|
|
|
|
should(
|
|
testFFT,
|
|
'Linear FFT data after setting fftSize = ' +
|
|
testAnalyser.fftSize)
|
|
.beCloseToArray(refFFT, errorThreshold);
|
|
})
|
|
.then(context.resume.bind(context));
|
|
|
|
return context.startRendering();
|
|
}
|
|
|
|
audit.run();
|
|
</script>
|
|
</body>
|
|
</html>
|