| <!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> |