blob: de25c3b270b4eb890d7741ff4ae254f0eb237728 [file] [log] [blame]
<!doctype html>
<html>
<head>
<title>Test Custom Oscillator at Very Low Frequency</title>
<script src="../resources/js-test.js"></script>
<script src="resources/compatibility.js"></script>
<script src="resources/audio-testing.js"></script>
</head>
<body>
<script>
description("Test Custom Oscillator at Very Low Frequency");
window.jsTestIsAsync = true;
// Create a custom oscillator and verify that the parts of a periodic wave that should be
// ignored really are ignored.
var sampleRate = 48000;
// The desired frequency of the oscillator. The value to be used depends on the
// implementation of the PeriodicWave and should be less than then lowest fundamental
// frequency. The lowest frequency is the Nyquist frequency divided by the max number of
// coefficients used for the FFT. In the current implementation, the max number of
// coefficients is 2048 (for a sample rate of 48 kHz) so the lowest frequency is 24000/2048 =
// 11.78 Hz.
var desiredFrequencyHz = 1;
// Minimum allowed SNR between the actual oscillator and the expected result. Experimentally
// determined.
var snrThreshold = 130;
var context;
var osc;
var actual;
var audit = Audit.createTaskRunner();
// Compute the SNR between the actual result and expected cosine wave
function checkCosineResult(result, freq, sampleRate) {
var signal = 0;
var noise = 0;
var omega = 2 * Math.PI * freq / sampleRate;
actual = result.getChannelData(0);
for (var k = 0; k < actual.length; ++k) {
var x = Math.cos(omega * k);
var diff = x - actual[k];
signal += x * x;
noise += diff * diff;
}
var snr = 10 * Math.log10(signal / noise);
Should("SNR of " + desiredFrequencyHz + " Hz sine wave", snr).beGreaterThanOrEqualTo(snrThreshold);
testPassed("PeriodicWave coefficients that must be ignored were correctly ignored.");
}
function runTest() {
context = new OfflineAudioContext(1, sampleRate, sampleRate);
osc = context.createOscillator();
// Create the custom oscillator. For simplicity of testing, we use just a cosine wave, but
// the initial elements of the real and imaginary parts are explicitly set to non-zero to
// test that they are ignored.
var r = new Float32Array(2);
var i = new Float32Array(2);
r[0] = 1; // DC component to be ignored
r[1] = 1; // Fundamental
i[0] = 1; // Sine term that doesn't actually exist in a Fourier series
i[1] = 0;
var wave = context.createPeriodicWave(r, i);
osc.setPeriodicWave(wave);
osc.frequency.value = desiredFrequencyHz;
osc.connect(context.destination);
osc.start();
context.startRendering().then(function (buffer) {
checkCosineResult(buffer, desiredFrequencyHz, sampleRate);
}).then(finishJSTest);
};
runTest();
successfullyParsed = true;
</script>
</body>
</html>