blob: 956443338931bd3851de591d195344248e9f7711 [file] [log] [blame]
<!doctype html>
<html>
<head>
<script src="../resources/js-test.js"></script>
<script src="resources/compatibility.js"></script>
<script src="resources/audio-testing.js"></script>
<script src="resources/realtimeanalyser-testing.js"></script>
<script src="resources/fft.js"></script>
<title>Test Analyser getFloatFrequencyData and getByteFrequencyData, Smoothing</title>
</head>
<body>
<script>
description("Test AnalyserNode getFloatFrequencyData and getByteFrequencyData, Smoothing");
window.jsTestIsAsync = true;
// Use a power of two to eliminate any round-off in the computation of the times for
// context.suspend().
var sampleRate = 32768;
// The largest FFT size for the analyser node is 32768. We want to render longer than this so
// that we have at least one complete buffer of data of 32768 samples.
var renderFrames = 2 * 32768;
var renderDuration = renderFrames / sampleRate;
var audit = Audit.createTaskRunner();
// Do one basic test of smoothing of the FFT data.
audit.defineTask("smoothing test", function (done) {
// Test only 512-point FFT. The size isn't too important as long as it's greater than 128
// (a rendering quantum).
var options = {
order: 9,
smoothing: 0.5,
floatRelError: 5.7607e-6
};
var success = true;
var graph = createGraph(options);
context = graph.context;
analyser = graph.analyser;
var smoothedFloatResult = new Float32Array(analyser.frequencyBinCount);
smoothedFloatResult.fill(0);
// Stop after one analyser frame to get the initial FFT
var suspendFrame = analyser.fftSize;
context.suspend(suspendFrame / sampleRate).then(function () {
var timeData = new Float32Array(analyser.fftSize);
var freqData = new Float32Array(analyser.frequencyBinCount);
analyser.getFloatTimeDomainData(timeData);
analyser.getFloatFrequencyData(freqData);
var expectedFreq = computeFFTMagnitude(timeData, options.order);
smoothFFT(smoothedFloatResult, expectedFreq, options.smoothing);
var message = "First " + analyser.fftSize + "-point FFT at frame " + (context.currentTime *
sampleRate);
var comparison = compareFloatFreq(message, freqData, smoothedFloatResult.map(
linearToDb), options);
success = success && comparison.success;
// Test the byte frequency data.
var byteFreqData = new Uint8Array(analyser.frequencyBinCount);
var expectedByteData = new Float32Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(byteFreqData);
// Convert the expected float frequency data to byte data.
var expectedByteData = convertFloatToByte(smoothedFloatResult.map(linearToDb),
analyser.minDecibels, analyser.maxDecibels);
success = Should(analyser.fftSize + "-point byte FFT", byteFreqData, {
verbose: true
}).beCloseToArray(expectedByteData, 0) && success;
}).then(context.resume.bind(context));
// Skip an analyser frame and grab another to verify that the smoothing is done correctly.
suspendFrame += 2 * analyser.fftSize;
context.suspend(suspendFrame / sampleRate).then(function () {
var timeData = new Float32Array(analyser.fftSize);
var freqDataInDb = new Float32Array(analyser.frequencyBinCount);
// Grab the time domain and frequency domain data
analyser.getFloatTimeDomainData(timeData);
analyser.getFloatFrequencyData(freqDataInDb);
var newFreqData = computeFFTMagnitude(timeData, options.order);
// Smooth the data together
smoothFFT(smoothedFloatResult, newFreqData, options.smoothing);
var message = "Smoothed " + analyser.fftSize + "-point FFT at frame " +
(context.currentTime * sampleRate);
var comparison = compareFloatFreq(message,
freqDataInDb, smoothedFloatResult.map(linearToDb), {
order: options.order,
smoothing: options.smoothing,
floatRelError: 1.5979e-5
});
success = success && comparison.success;
// Test the byte frequency data.
var byteFreqData = new Uint8Array(analyser.frequencyBinCount);
var expectedByteData = new Float32Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(byteFreqData);
// Convert the expected float frequency data to byte data.
var expectedByteData = convertFloatToByte(smoothedFloatResult.map(linearToDb),
analyser.minDecibels, analyser.maxDecibels);
success = Should(analyser.fftSize + "-point byte FFT", byteFreqData, {
verbose: true
}).beCloseToArray(expectedByteData, 0) && success;
}).then(context.resume.bind(context));
context.startRendering().then(function (buffer) {
var prefix = "FFT smoothing performed ";
var suffix = " with smoothing constant " + analyser.smoothingTimeConstant + ".\n"
if (success)
testPassed(prefix + "correctly" + suffix);
else
testFailed(prefix + "incorrectly" + suffix);
}).then(done);
});
audit.defineTask("finish", function (done) {
finishJSTest();
done();
});
audit.runTasks();
</script>
</body>
</html>