| <!DOCTYPE html> |
| <html> |
| <head> |
| <title> |
| Test Clamping of AudioParam Time |
| </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"> |
| // Fairly arbitrary sample rate and render frames. |
| let sampleRate = 24000; |
| let renderFrames = 1024; |
| |
| let audit = Audit.createTaskRunner(); |
| |
| audit.define('setValue', (task, should) => { |
| let suspendFrame = 128; |
| createGraph({ |
| suspendFrame: suspendFrame, |
| method: 'setValueAtTime', |
| initialGain: 0, |
| arg0: 1, |
| }) |
| .then(function(resultBuffer) { |
| // Just verify that the cosine wave actually started at |
| // suspendFrame. |
| let result = resultBuffer.getChannelData(0); |
| |
| should( |
| result.slice(0, suspendFrame), |
| 'setValue: Output[0-' + (suspendFrame - 1) + ']') |
| .beConstantValueOf(0); |
| should( |
| result.slice(suspendFrame), |
| 'setValue: Output[' + suspendFrame + '-' + |
| (renderFrames - 1) + ']') |
| .beConstantValueOf(1); |
| }) |
| .then(() => task.done()); |
| }); |
| |
| audit.define('linear', (task, should) => { |
| let suspendFrame = 128; |
| createGraph({ |
| suspendFrame: suspendFrame, |
| method: 'linearRampToValueAtTime', |
| initialGain: 1, |
| arg0: 0.5 |
| }) |
| .then(function(resultBuffer) { |
| // Just verify that the cosine wave actually started at |
| // suspendFrame. |
| let result = resultBuffer.getChannelData(0); |
| |
| should( |
| result.slice(0, suspendFrame), |
| 'linear: Output[0-' + (suspendFrame - 1) + ']') |
| .beConstantValueOf(1); |
| should( |
| result.slice(suspendFrame), |
| 'linear: Output[' + suspendFrame + '-' + (renderFrames - 1) + |
| ']') |
| .beConstantValueOf(0.5); |
| |
| }) |
| .then(() => task.done()); |
| }); |
| |
| audit.define('exponential', (task, should) => { |
| let suspendFrame = 128; |
| createGraph({ |
| suspendFrame: suspendFrame, |
| method: 'exponentialRampToValueAtTime', |
| initialGain: 1, |
| arg0: 0.5 |
| }) |
| .then(function(resultBuffer) { |
| // Just verify that the cosine wave actually started at |
| // suspendFrame. |
| let result = resultBuffer.getChannelData(0); |
| |
| should( |
| result.slice(0, suspendFrame), |
| 'exponential: Output[0-' + (suspendFrame - 1) + ']') |
| .beConstantValueOf(1); |
| should( |
| result.slice(suspendFrame), |
| 'exponential: Output[' + suspendFrame + '-' + |
| (renderFrames - 1) + ']') |
| .beConstantValueOf(0.5); |
| }) |
| .then(() => task.done()); |
| }); |
| |
| audit.define('setTarget', (task, should) => { |
| let suspendFrame = 128; |
| createGraph({ |
| suspendFrame: suspendFrame, |
| method: 'setTargetAtTime', |
| initialGain: 1, |
| arg0: 0.5, |
| moreArgs: 0.1 |
| }) |
| .then(function(resultBuffer) { |
| // Just verify that the cosine wave actually started at |
| // suspendFrame. |
| let result = resultBuffer.getChannelData(0); |
| |
| should( |
| result.slice(0, suspendFrame), |
| 'setTarget: Output[0-' + (suspendFrame - 1) + ']') |
| .beConstantValueOf(1); |
| // For the samples past the suspend time, we only care that first |
| // value is 1 and that the rest are not zero. |
| should( |
| result[suspendFrame], |
| 'setTarget: Output[' + suspendFrame + ']') |
| .beEqualTo(1); |
| |
| let positive = result.slice(suspendFrame + 1).every(x => x > 0); |
| should( |
| positive, |
| 'Output[' + (suspendFrame + 1) + '-' + (renderFrames - 1) + |
| '] contains only positive values') |
| .beEqualTo(true); |
| }) |
| .then(() => task.done()); |
| }); |
| |
| audit.define('setValueCurve', (task, should) => { |
| let suspendFrame = 128; |
| createGraph({ |
| suspendFrame: suspendFrame, |
| method: 'setValueCurveAtTime', |
| initialGain: 1, |
| arg0: Float32Array.from([2, 3]), |
| moreArgs: 0.1 |
| }) |
| .then(function(resultBuffer) { |
| // Just verify that the cosine wave actually started at |
| // suspendFrame. |
| let result = resultBuffer.getChannelData(0); |
| |
| should( |
| result.slice(0, suspendFrame), |
| 'setValueCurve: Output[0-' + (suspendFrame - 1) + ']') |
| .beConstantValueOf(1); |
| |
| // The selected curve contains values greater than or equal to 2. |
| // Just verify that all values are greater than or equal to 2. |
| let biggerThan2 = result.slice(suspendFrame).every(x => x >= 2); |
| should( |
| biggerThan2, |
| 'setValueCurve: Output[' + suspendFrame + '-' + |
| (renderFrames - 1) + ']') |
| .beEqualTo(true); |
| }) |
| .then(() => task.done()); |
| }); |
| |
| |
| // Create the test graph consisting of a constant source followed by a |
| // gain node. The gain node automations will be tested. |options| |
| // specifies the parameters for the test including |
| // |
| // suspendFrame: time at which we schedule the automation call |
| // method: the name of automation method to be tested |
| // initialGain: the initial gain at time 0 for the gain node |
| // arg0: the first argument to be supplied to the automation method. |
| // moreArgs: An array of any additional arguments for the automation |
| // method. |
| function createGraph(options) { |
| let context = new OfflineAudioContext(1, renderFrames, sampleRate); |
| |
| let cosineWave = new PeriodicWave(context, {real: [0, 1]}); |
| |
| let src = new OscillatorNode( |
| context, {periodicWave: cosineWave, frequency: 0}); |
| |
| // The gain node whose automations we're testing. |
| let gain = new GainNode(context, {gain: 0}); |
| |
| src.connect(gain).connect(context.destination); |
| |
| gain.gain.setValueAtTime(options.initialGain, 0); |
| |
| // Suspend rendering so that we can call the automation method at the |
| // right time. |startTime| is the time for the automation method. It |
| // must be some time before the suspend time. |
| let suspendFrame = options.suspendFrame; |
| let startTime = (suspendFrame / 2) / context.sampleRate; |
| context.suspend(suspendFrame / context.sampleRate) |
| .then(function() { |
| // Call the appropriate automation method with the desired |
| // automation value, time, and any other arguments needed. |
| gain.gain[options.method]( |
| ...[options.arg0, startTime, options.moreArgs]); |
| }) |
| .then(context.resume.bind(context)); |
| |
| // Start the source and begin rendering, returning the promise from |
| // rendering. |
| src.start(); |
| |
| return context.startRendering(); |
| } |
| |
| audit.run(); |
| </script> |
| </body> |
| </html> |