| <!DOCTYPE html> |
| <html> |
| <head> |
| <title> |
| Test Automation Following setValueCurveAtTime Automations |
| </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/audio-param.js"></script> |
| </head> |
| <body> |
| <script id="layout-test-code"> |
| let sampleRate = 12800; |
| // Some short duration because we don't need to run the test for very |
| // long. |
| let testDurationFrames = 256; |
| let testDurationSec = testDurationFrames / sampleRate; |
| let curveDuration = testDurationSec / 2; |
| |
| let audit = Audit.createTaskRunner(); |
| |
| // Configuration for each test. |
| // |
| // Required options: |
| // automation - Name of automation method to test |
| // time - Time for the automation method. |
| // Optional options: |
| // extraDuration - extra time for the duration of the setValueCurve |
| // duration. Default is 0. This should not be on a |
| // sample frame boundary. This is for testing that |
| // curves that don't end on a frame boundary are handled |
| // correctly. |
| // threshold - Error threshold for the test; default is 0. |
| let testConfigs = [ |
| { |
| automation: 'linearRampToValueAtTime', |
| time: testDurationSec, |
| threshold: 3.9737e-8 |
| }, |
| { |
| automation: 'linearRampToValueAtTime', |
| time: testDurationSec, |
| extraDuration: 0.5 / sampleRate, |
| threshold: 1.8141e-8 |
| }, |
| { |
| automation: 'exponentialRampToValueAtTime', |
| time: testDurationSec, |
| threshold: 3.9737e-8 |
| }, |
| { |
| automation: 'exponentialRampToValueAtTime', |
| time: testDurationSec, |
| extraDuration: 0.5 / sampleRate, |
| threshold: 7.8294e-8 |
| }, |
| { |
| automation: 'setTargetAtTime', |
| time: curveDuration, |
| threshold: 1.5895e-7 |
| }, |
| { |
| automation: 'setTargetAtTime', |
| time: curveDuration + 0.5 / sampleRate, |
| extraDuration: 0.5 / sampleRate, |
| threshold: 1.3278e-7 |
| } |
| ]; |
| |
| // Define tests from the configs |
| for (k in testConfigs) { |
| audit.define(k + ': ' + testConfigs[k].automation, (function(config) { |
| return (task, should) => { |
| runTest(should, config).then(() => task.done()); |
| }; |
| })(testConfigs[k])); |
| } |
| |
| audit.run(); |
| |
| function runTest(should, options) { |
| // For the test, use a gain node with a constant input to test the |
| // automations. |
| let context = |
| new OfflineAudioContext(1, testDurationFrames, sampleRate); |
| let source = context.createBufferSource(); |
| source.buffer = createConstantBuffer(context, 1, 1); |
| source.loop = true; |
| |
| let gain = context.createGain(); |
| |
| // Any valid curve is ok. We only use the last value for testing. |
| let curve = [0, 2, 0.3]; |
| let actualDuration = curveDuration + (options.extraDuration || 0); |
| gain.gain.setValueCurveAtTime( |
| Float32Array.from(curve), 0, actualDuration); |
| |
| // Run the desired test automation. The extra parameter (0.01) is only |
| // used for setTargetAtTime tests; it's ignored for other tests. |
| let automationValue = 2; |
| gain.gain[options.automation](automationValue, options.time, 0.01); |
| |
| source.connect(gain); |
| gain.connect(context.destination); |
| |
| source.start(); |
| |
| return context.startRendering().then(function(resultBuffer) { |
| let result = resultBuffer.getChannelData(0); |
| |
| // Only need to verify that the ramp started at the right |
| // value. Figure the nearest sample frame to the end curve. |
| let curveEndFrame = Math.ceil(actualDuration * sampleRate); |
| |
| let expectedResult = curve[curve.length - 1]; |
| |
| // Determine the expected value after the end of the setValueCurve |
| // event. |
| if (options.automation == 'linearRampToValueAtTime') { |
| expectedResult = audioParamLinearRamp( |
| curveEndFrame / sampleRate, curve[curve.length - 1], |
| actualDuration, automationValue, testDurationSec); |
| } else if (options.automation == 'exponentialRampToValueAtTime') { |
| expectedResult = audioParamExponentialRamp( |
| curveEndFrame / sampleRate, curve[curve.length - 1], |
| actualDuration, automationValue, testDurationSec); |
| } else if (options.automation == 'setTargetAtTime') { |
| expectedResult = audioParamSetTarget( |
| curveEndFrame / sampleRate, curve[curve.length - 1], |
| actualDuration, automationValue, 0.01); |
| } |
| |
| let message = 'setValueCurve(..., ' + 0 + ', ' + actualDuration + |
| ').' + options.automation + '(2, ' + testDurationSec; |
| |
| if (options.automation == 'setTargetAtTime') |
| message += ', 0.01'; |
| message += ')'; |
| |
| should( |
| result[curveEndFrame], |
| message + ': value at time ' + curveEndFrame / sampleRate) |
| .beCloseTo(expectedResult, {threshold: options.threshold || 0}); |
| }); |
| } |
| |
| function linearRampValue(t, t0, v0, t1, v1) { |
| return v0 + (v1 - v0) * (t - t0) / (t1 - t0); |
| } |
| |
| function exponentialRampValue(t, t0, v0, t1, v1) { |
| return v0 * Math.pow(v1 / v0, (t - t0) / (t1 - t0)); |
| } |
| |
| function setTargetValue(t, t0, v0, v1, timeConstant) { |
| return v1 + (v0 - v1) * Math.exp(-(t - t0) / timeConstant) |
| } |
| </script> |
| </body> |
| </html> |