<!DOCTYPE html>
<html>
<head>
<title>
Test Custom 440 Hz Oscillator
</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>
</head>
<body>
<script id = 'layout-test-code'>let sampleRate = 48000;
// Minimum allowed SNR between the actual oscillator and the expected
// result. Experimentally determined.
let snrThreshold = 59.280;
// Max absolute difference between actual and expected oscillator
// outputs. Experimentally determined.
let maxDiffThreshold = 1.5640e-3;
let audit = Audit.createTaskRunner();
// Test that two ways of creating a 440-Hz sine wave produce the same
// results, within some tolerance.
audit.define('440 Hz Osc', (task, should) => {
// 3-channel context: channel 0 = actual output; channel 1 = expected
// output, channel 2 = difference between channels 0 and 1.
let context = new OfflineAudioContext(3, sampleRate, sampleRate);
let merger = new ChannelMergerNode(
context, {numberOfInputs: context.destination.channelCount});
merger.connect(context.destination);
// Create a 440 Hz oscillator in following way. Use a PeriodicWave with
// a single harmonic value of 440 and use that in an oscillator with
// fundamental frequeqncy of 1 Hz. This should produce a 440 Hz sine
// wave. This is the test signal.
let imag = new Float32Array(512);
imag[440] = 1;
let wave440 =
new PeriodicWave(context, {imag: imag, disableNormaliztion: true});
let oscTest =
new OscillatorNode(context, {frequency: 1, periodicWave: wave440});
// Create a 440 Hz oscillator by specifying a frequency of 440 Hz. We
// use a periodicWave for this so we can disable normalization.
let oscRef = new OscillatorNode(context, {
frequency: 440,
periodocWave: new PeriodicWave(
context, {imag: [0, 1], disableNormaliztion: true})
});
oscTest.connect(merger, 0, 0);
oscRef.connect(merger, 0, 1);
// Compute the difference of the two signals
let neg = new GainNode(context, {gain: -1});
neg.connect(merger, 0, 2);
oscTest.connect(merger, 0, 2);
oscRef.connect(neg);
oscTest.start();
oscRef.start();
context.startRendering()
.then(result => {
// Extract the actual output, the reference output and the
// difference signal from the rendered data.
actual = result.getChannelData(0);
ref = result.getChannelData(1);
diff = result.getChannelData(2);
// The actual and reference signals should be close, and the SNR
// should be high.
should(actual, 'Test oscillator output').beCloseToArray(
ref, {absoluteThreshold: maxDiffThreshold});
let snr = 10 * Math.log10(computeSNR(actual, ref));
should(snr, 'SNR').beGreaterThanOrEqualTo(snrThreshold);
})
.then(() => task.done());
});
audit.run();
</script>
</body>
</html>