<!DOCTYPE html>
<html>
<head>
<title>
Test Analyser getFloatFrequencyData and getByteFrequencyData, Smoothing
</title>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script src="../resources/audit-util.js"></script>
<script src="../resources/audit.js"></script>
<script src="../resources/realtimeanalyser-testing.js"></script>
<script src="../resources/fft.js"></script>
</head>
<body>
<script id="layout-test-code">
// Use a power of two to eliminate any round-off in the computation of the
// times for context.suspend().
let 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.
let renderFrames = 2 * 32768;
let renderDuration = renderFrames / sampleRate;
let audit = Audit.createTaskRunner();
// Do one basic test of smoothing of the FFT data.
audit.define('smoothing test', (task, should) => {
// Test only 512-point FFT. The size isn't too important as long as
// it's greater than 128 (a rendering quantum).
let options = {order: 9, smoothing: 0.5, floatRelError: 5.9207e-6};
let success = true;
let graph = createGraph(options);
context = graph.context;
analyser = graph.analyser;
let smoothedFloatResult = new Float32Array(analyser.frequencyBinCount);
smoothedFloatResult.fill(0);
// Stop after one analyser frame to get the initial FFT
let suspendFrame = analyser.fftSize;
context.suspend(suspendFrame / sampleRate)
.then(function() {
let timeData = new Float32Array(analyser.fftSize);
let freqData = new Float32Array(analyser.frequencyBinCount);
analyser.getFloatTimeDomainData(timeData);
analyser.getFloatFrequencyData(freqData);
let expectedFreq = computeFFTMagnitude(timeData, options.order);
smoothFFT(smoothedFloatResult, expectedFreq, options.smoothing);
let message = 'First ' + analyser.fftSize +
'-point FFT at frame ' + (context.currentTime * sampleRate);
let comparison = compareFloatFreq(
message, freqData, smoothedFloatResult.map(linearToDb),
should, options);
success = success && comparison.success;
// Test the byte frequency data.
let byteFreqData = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(byteFreqData);
// Convert the expected float frequency data to byte data.
let expectedByteData = convertFloatToByte(
smoothedFloatResult.map(linearToDb), analyser.minDecibels,
analyser.maxDecibels);
should(byteFreqData, analyser.fftSize + '-point byte FFT')
.beCloseToArray(expectedByteData, 0);
})
.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() {
let timeData = new Float32Array(analyser.fftSize);
let freqDataInDb = new Float32Array(analyser.frequencyBinCount);
// Grab the time domain and frequency domain data
analyser.getFloatTimeDomainData(timeData);
analyser.getFloatFrequencyData(freqDataInDb);
let newFreqData = computeFFTMagnitude(timeData, options.order);
// Smooth the data together
smoothFFT(smoothedFloatResult, newFreqData, options.smoothing);
let message = 'Smoothed ' + analyser.fftSize +
'-point FFT at frame ' + (context.currentTime * sampleRate);
let comparison = compareFloatFreq(
message, freqDataInDb, smoothedFloatResult.map(linearToDb),
should, {
order: options.order,
smoothing: options.smoothing,
floatRelError: 2.5332e-5
});
success = success && comparison.success;
// Test the byte frequency data.
let byteFreqData = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(byteFreqData);
// Convert the expected float frequency data to byte data.
let expectedByteData = convertFloatToByte(
smoothedFloatResult.map(linearToDb), analyser.minDecibels,
analyser.maxDecibels);
should(byteFreqData, analyser.fftSize + '-point byte FFT')
.beCloseToArray(expectedByteData, 0);
})
.then(context.resume.bind(context));
context.startRendering().then(() => task.done());
});
audit.run();
</script>
</body>
</html>