| <!doctype html> |
| <html> |
| <head> |
| <script src="resources/compatibility.js"></script> |
| <script src="resources/audio-testing.js"></script> |
| <script src="resources/audioparam-testing.js"></script> |
| <script src="../resources/js-test.js"></script> |
| <title>Test Sampling of LinearRampToValueAtTime</title> |
| </head> |
| |
| <body> |
| <script> |
| description("Test Sampling of LinearRampToValueAtTime"); |
| |
| window.jsTestIsAsync = true; |
| var sampleRate = 12800; |
| var context; |
| |
| var audit = Audit.createTaskRunner(); |
| |
| function runTest(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. |
| var source = context.createBufferSource(); |
| var b = createConstantBuffer(context, 1, 1); |
| source.buffer = b; |
| source.loop = true; |
| |
| // Gain node that is to be automated. |
| var 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. |
| var resultData = resultBuffer.getChannelData(0); |
| |
| // The automation has starts at config.startTime, so the frame just after this should have |
| // the automation applied. |
| var startFrame = Math.ceil(config.startTime * sampleRate); |
| |
| // The automation ends at config.endTime so the frame just before this should have the |
| // automation applied. |
| var endFrame = Math.floor(config.endTime * sampleRate); |
| |
| // Use the true automation to find the expected values. |
| var expectedStart = config.expectedFunction(startFrame / sampleRate); |
| var expectedEnd = config.expectedFunction(endFrame / sampleRate); |
| |
| var success = Should(config.desc + ": Sample " + startFrame, |
| resultData[startFrame], { |
| precision: 7 |
| }).beCloseTo(expectedStart, config.startValueThreshold); |
| success = Should(config.desc + ": Sample " + endFrame, |
| resultData[endFrame], { |
| precision: 7 |
| }).beCloseTo(expectedEnd, config.endValueThreshold) && success; |
| |
| if (success) |
| testPassed(config.desc + " passed.\n"); |
| else |
| testFailed(config.desc + " failed.\n"); |
| }); |
| } |
| |
| function expectedLinear(t) { |
| var slope = (this.endValue - this.startValue) / (this.endTime - this.startTime); |
| return this.startValue + slope * (t - this.startTime); |
| }; |
| |
| function expectedExponential(t) { |
| var ratio = this.endValue / this.startValue; |
| var 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. |
| var 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 function (done) { |
| runTest(config).then(done); |
| }; |
| } |
| |
| // Create all of the tasks from the test configs |
| for (var k = 0; k < testConfigs.length; ++k) { |
| var config = testConfigs[k]; |
| var taskName = config.desc + ":task" + k; |
| audit.defineTask(taskName, createTaskFunction(config)); |
| } |
| |
| audit.defineTask("finish", function (done) { |
| finishJSTest(); |
| done(); |
| }); |
| |
| audit.runTasks(); |
| successfullyParsed = true; |
| </script> |
| </body> |
| </html> |