blob: da99c85c89f01bfb5b4e2887968a387d59757d8a [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<title>
Test PeriodicWave Normalization
</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">
let sampleRate = 48000;
let renderFrames = 6000;
let context;
let audit = Audit.createTaskRunner();
let testSet = [
// Test the default case where the two-arg createPeriodicWave is called.
// The waveform should be normalized.
{
name: 'option-default/normalized',
// This option is treated specially; it means that the two-arg
// function is called.
option: 'NONE',
// Somewhat arbitrary except that resulting waveform should have
// amplitude greater than 1. And we don't want a simple sine wave
// because that always has max amplitude of 1.
realCoef: [0, -1, 1],
threshold: 1e-5,
expectedMax: 1
},
{
name: 'option-null/normalized',
option: null,
// Somewhat arbitrary except that resulting waveform should have
// amplitude greater than 1. And we don't want a simple sine wave
// because that always has max amplitude of 1.
realCoef: [0, -1, 1],
threshold: 1e-5,
expectedMax: 1
},
// Explicitly set to false. Waveform should be normalized.
{
name: 'false/normalized',
option: {disableNormalization: false},
realCoef: [0, -1, 1],
threshold: 1e-5,
expectedMax: 1
},
// Explicitly disable normalization. Waveform is not normalized.
{
name: 'true/unnormalized',
option: {disableNormalization: true},
// Somewhat arbitrary except that resulting waveform should have
// amplitude very clearly greater than 1.
realCoef: [0, 10],
threshold: 1e-5,
expectedMax: 10
},
// Explicitly set to some value that is not false. Waveform should NOT
// be normalized.
{
name: 'foo/unnormalized',
option: {disableNormalization: 'foo'},
realCoef: [0, 10],
threshold: 1e-5,
expectedMax: 10
},
// Explicitly set to null, which is the same as false. Waveform is
// normalized.
{
name: 'null/unnormalized',
option: {disableNormalization: null},
realCoef: [0, 1, -1],
threshold: 1e-5,
expectedMax: 1
},
// Pass in a random dictionary not using our key. Waveform should be
// normalized.
{
name: 'random-key-value/normalized',
option: {randomKey: true},
realCoef: [0, -1, 1],
threshold: 1e-5,
expectedMax: 1
},
// Set options to several random keys. Waveform must be normalized.
{
name: 'more-random-keys/normalized',
option: {key1: 'value1', key2: 42},
realCoef: [0, 1, -1],
threshold: 1e-5,
expectedMax: 1
},
// Set option to include our key (set to true) amongst a bunch of
// others. Waveform is NOT normalized.
{
name: 'true-with-random-keys/unnormalized',
option: {key1: 'value1', disableNormalization: true},
realCoef: [0, 10],
threshold: 1e-5,
expectedMax: 10
},
// Set option to include our key (set to false) amongst a bunch of
// others. Waveform is normalized.
{
name: 'false-with-random-keys/normalized',
option: {key1: 'value1', disableNormalization: false},
realCoef: [0, 10],
threshold: 1e-5,
expectedMax: 1
},
// Set option to a non-dictionary. Waveform is normalized.
{
name: 'non-dict/normalized',
option: [1, 2, 3],
realCoef: [0, 1, -1],
threshold: 1e-5,
expectedMax: 1
},
];
function arrayMax(array) {
return array.reduce(function(reducedValue, currentValue) {
return Math.max(reducedValue, Math.abs(currentValue));
}, -1);
}
function createAndRunAudioGraph(options, realCoef, imagCoef, verify) {
context = new OfflineAudioContext(1, renderFrames, sampleRate);
let osc = context.createOscillator();
let r = new Float32Array(realCoef);
let i = new Float32Array(imagCoef);
let wave;
// If options is "NONE", we want to be sure to call the two-arg
// createPeriodicWave to make sure the default method works as expected.
if (options === 'NONE') {
// console.log("2-arg: " + options);
wave = context.createPeriodicWave(r, i);
} else {
// console.log("3-arg: " + options);
wave = context.createPeriodicWave(r, i, options);
}
osc.setPeriodicWave(wave);
osc.connect(context.destination);
osc.start();
return context.startRendering().then(verify);
}
// Define a test function from the given test parameter. This is used as
// the Audit.defineTask task function.
function defineTest(testInfo) {
return (task, should) => {
let imagCoef = new Float32Array(testInfo.realCoef.length);
createAndRunAudioGraph(
testInfo.option, testInfo.realCoef, imagCoef,
function(result) {
let prefix;
// Try to print out the test.option in a reasonably nice but
// explicit way.
if (testInfo.option === 'NONE') {
prefix = '';
} else if (Array.isArray(testInfo.option)) {
prefix = '[' + testInfo.option + ']: ';
} else {
prefix = JSON.stringify(testInfo.option) + ': ';
}
should(arrayMax(result.getChannelData(0)), prefix + 'amplitude')
.beCloseTo(
testInfo.expectedMax, {threshold: testInfo.threshold});
})
.then(() => task.done());
};
}
// Ensure the actual Audit test name is unique by prepending an index to
// the provided test name.
function actualTestName(name, index) {
return index + ':' + name;
}
function defineTasks() {
for (let k = 0; k < testSet.length; ++k) {
let testInfo = testSet[k];
audit.define(actualTestName(test.name, k), defineTest(testInfo));
}
}
defineTasks();
audit.run();
successfullyParsed = true;
</script>
</body>
</html>