| <!DOCTYPE html> |
| <html> |
| <head> |
| <title> |
| Test Sampling of LinearRampToValueAtTime |
| </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> |
| <script src="../resources/audioparam-testing.js"></script> |
| </head> |
| <body> |
| <script id="layout-test-code"> |
| let sampleRate = 12800; |
| let context; |
| |
| let audit = Audit.createTaskRunner(); |
| |
| function runTest(should, config) { |
| // Create a short context with a constant signal source connected to a |
| // gain node that will be automated. |
| context = new OfflineAudioContext(1, 256, sampleRate); |
| |
| // Create a constant unit amplitude source. |
| let source = context.createBufferSource(); |
| let b = createConstantBuffer(context, 1, 1); |
| source.buffer = b; |
| source.loop = true; |
| |
| // Gain node that is to be automated. |
| let gain = context.createGain(); |
| gain.gain.value = 0; |
| gain.gain.setValueAtTime(config.startValue, config.startTime); |
| config.automationFunction(gain); |
| |
| source.connect(gain); |
| gain.connect(context.destination); |
| |
| source.start(); |
| |
| return context.startRendering().then(function(resultBuffer) { |
| // Check that the automation has the correct sampling. |
| let resultData = resultBuffer.getChannelData(0); |
| |
| // The automation has starts at config.startTime, so the frame just |
| // after this should have the automation applied. |
| let startFrame = Math.ceil(config.startTime * sampleRate); |
| |
| // The automation ends at config.endTime so the frame just before this |
| // should have the automation applied. |
| let endFrame = Math.floor(config.endTime * sampleRate); |
| |
| // Use the true automation to find the expected values. |
| let expectedStart = config.expectedFunction(startFrame / sampleRate); |
| let expectedEnd = config.expectedFunction(endFrame / sampleRate); |
| |
| should(resultData[startFrame], config.desc + ': Sample ' + startFrame) |
| .beCloseTo( |
| expectedStart, {threshold: config.startValueThreshold}); |
| should(resultData[endFrame], config.desc + ': Sample ' + endFrame) |
| .beCloseTo(expectedEnd, {threshold: config.endValueThreshold}); |
| }); |
| } |
| |
| function expectedLinear(t) { |
| let slope = |
| (this.endValue - this.startValue) / (this.endTime - this.startTime); |
| return this.startValue + slope * (t - this.startTime); |
| }; |
| |
| function expectedExponential(t) { |
| let ratio = this.endValue / this.startValue; |
| let exponent = (t - this.startTime) / (this.endTime - this.startTime); |
| return this.startValue * Math.pow(ratio, exponent); |
| }; |
| |
| function linearAutomation(g) { |
| g.gain.linearRampToValueAtTime(this.endValue, this.endTime); |
| } |
| |
| function exponentialAutomation(g) { |
| g.gain.exponentialRampToValueAtTime(this.endValue, this.endTime); |
| } |
| |
| // Basically want to test that if neither the start time nor end time is |
| // on a frame boundary that we sample the automation curve correctly. The |
| // start times and end times are mostly arbitrary, except that they cannot |
| // be on a frame boundary. |
| let testConfigs = [ |
| { |
| desc: 'linearRamp', |
| startTime: .1 / sampleRate, |
| endTime: 128.1 / sampleRate, |
| startValue: 1, |
| endValue: 0, |
| startValueThreshold: 1.201e-8, |
| endValueThreshold: 1.526e-5, |
| automationFunction: linearAutomation, |
| expectedFunction: expectedLinear |
| }, |
| { |
| desc: 'linearRamp:short', |
| startTime: .1 / sampleRate, |
| endTime: 5.1 / sampleRate, |
| startValue: 1, |
| endValue: 0, |
| startValueThreshold: 8.723e-9, |
| endValueThreshold: 9.537e-7, |
| automationFunction: linearAutomation, |
| expectedFunction: expectedLinear |
| }, |
| { |
| desc: 'linearRamp:long', |
| startTime: .1 / sampleRate, |
| endTime: 200.1 / sampleRate, |
| startValue: 1, |
| endValue: 0, |
| startValueThreshold: 2.827e-8, |
| endValueThreshold: 4.674e-5, |
| automationFunction: linearAutomation, |
| expectedFunction: expectedLinear |
| }, |
| { |
| desc: 'exponentialRamp', |
| startTime: .1 / sampleRate, |
| endTime: 128.1 / sampleRate, |
| startValue: 1, |
| endValue: 1e-5, |
| startValueThreshold: 2.505e-8, |
| endValueThreshold: 1.484e-7, |
| automationFunction: exponentialAutomation, |
| expectedFunction: expectedExponential |
| }, |
| { |
| desc: 'exponentialRamp:short', |
| startTime: .1 / sampleRate, |
| endTime: 5.1 / sampleRate, |
| startValue: 1, |
| endValue: 1e-5, |
| startValueThreshold: 5.027e-8, |
| endValueThreshold: 3.821e-7, |
| automationFunction: exponentialAutomation, |
| expectedFunction: expectedExponential |
| }, |
| { |
| desc: 'exponentialRamp:long', |
| startTime: .1 / sampleRate, |
| endTime: 200.1 / sampleRate, |
| startValue: 1, |
| endValue: 1e-5, |
| startValueThreshold: 8.035e-9, |
| endValueThreshold: 1.337e-6, |
| automationFunction: exponentialAutomation, |
| expectedFunction: expectedExponential |
| }, |
| ]; |
| |
| function createTaskFunction(config) { |
| return (task, should) => { |
| runTest(should, config).then(() => task.done()); |
| }; |
| } |
| |
| // Create all of the tasks from the test configs |
| for (let k = 0; k < testConfigs.length; ++k) { |
| let config = testConfigs[k]; |
| let taskName = config.desc + ':task' + k; |
| audit.define(taskName, createTaskFunction(config)); |
| } |
| |
| audit.run(); |
| </script> |
| </body> |
| </html> |