OLD | NEW |
1 <!doctype html> | 1 <!DOCTYPE html> |
2 <html> | 2 <html> |
3 <head> | 3 <head> |
| 4 <title> |
| 5 Test Clamping of Automations |
| 6 </title> |
4 <script src="../../resources/testharness.js"></script> | 7 <script src="../../resources/testharness.js"></script> |
5 <script src="../../resources/testharnessreport.js"></script> | 8 <script src="../../resources/testharnessreport.js"></script> |
6 <script src="../resources/audit-util.js"></script> | 9 <script src="../resources/audit-util.js"></script> |
7 <script src="../resources/audit.js"></script> | 10 <script src="../resources/audit.js"></script> |
8 <title>Test Clamping of Automations</title> | |
9 </head> | 11 </head> |
10 | |
11 <body> | 12 <body> |
12 <script> | 13 <script id="layout-test-code"> |
13 | 14 // Some arbitrary sample rate for the offline context. |
14 // Some arbitrary sample rate for the offline context. | 15 let sampleRate = 48000; |
15 var sampleRate = 48000; | |
16 | 16 |
17 // Duration of test (fairly arbitrary). | 17 // Duration of test (fairly arbitrary). |
18 var renderDuration = 1; | 18 let renderDuration = 1; |
19 var renderFrames = renderDuration * sampleRate; | 19 let renderFrames = renderDuration * sampleRate; |
20 | 20 |
21 var audit = Audit.createTaskRunner(); | 21 let audit = Audit.createTaskRunner(); |
22 | 22 |
23 audit.define("clamp", (task, should) => { | 23 audit.define('clamp', (task, should) => { |
24 // Test clamping of automations. Most AudioParam limits are essentially | 24 // Test clamping of automations. Most AudioParam limits are essentially |
25 // unbounded, so clamping doesn't happen. For most other AudioParams, | 25 // unbounded, so clamping doesn't happen. For most other AudioParams, |
26 // the behavior is sufficiently complicated with complicated outputs | 26 // the behavior is sufficiently complicated with complicated outputs |
27 // that testing them is hard. However the output behavior of the | 27 // that testing them is hard. However the output behavior of the |
28 // frequency parameter for a BiquadFilter is relatively simple. Use | 28 // frequency parameter for a BiquadFilter is relatively simple. Use |
29 // that as the test. | 29 // that as the test. |
30 var context = new OfflineAudioContext(1, renderFrames, sampleRate); | 30 let context = new OfflineAudioContext(1, renderFrames, sampleRate); |
31 | 31 |
32 var source = context.createBufferSource(); | 32 let source = context.createBufferSource(); |
33 source.buffer = createConstantBuffer(context, 1, 1); | 33 source.buffer = createConstantBuffer(context, 1, 1); |
34 source.loop = true; | 34 source.loop = true; |
35 | 35 |
36 var filter = context.createBiquadFilter(); | 36 let filter = context.createBiquadFilter(); |
37 filter.type = "lowpass"; | 37 filter.type = 'lowpass'; |
38 | 38 |
39 source.connect(filter); | 39 source.connect(filter); |
40 filter.connect(context.destination); | 40 filter.connect(context.destination); |
41 | 41 |
42 var V0 = 880; | 42 let V0 = 880; |
43 var T0 = 0; | 43 let T0 = 0; |
44 filter.frequency.setValueAtTime(V0, T0); | 44 filter.frequency.setValueAtTime(V0, T0); |
45 | 45 |
46 var V1 = -1000; | 46 let V1 = -1000; |
47 var T1 = renderDuration / 4; | 47 let T1 = renderDuration / 4; |
48 filter.frequency.linearRampToValueAtTime(V1, T1); | 48 filter.frequency.linearRampToValueAtTime(V1, T1); |
49 | 49 |
50 var V2 = 880; | 50 let V2 = 880; |
51 var T2 = renderDuration / 2; | 51 let T2 = renderDuration / 2; |
52 filter.frequency.linearRampToValueAtTime(V2, T2); | 52 filter.frequency.linearRampToValueAtTime(V2, T2); |
53 | 53 |
54 source.start(); | 54 source.start(); |
55 | 55 |
56 context.startRendering().then(function (buffer) { | 56 context.startRendering() |
57 var result = buffer.getChannelData(0); | 57 .then(function(buffer) { |
| 58 let result = buffer.getChannelData(0); |
58 | 59 |
59 // When the cutoff frequency of a lowpass filter is 0, nothing gets | 60 // When the cutoff frequency of a lowpass filter is 0, nothing |
60 // through. Hence the output of the filter between the clamping | 61 // gets through. Hence the output of the filter between the |
61 // period should be exactly zero. This tests passes if the output is 0 | 62 // clamping period should be exactly zero. This tests passes if |
62 // during the expected range. | 63 // the output is 0 during the expected range. |
63 // | 64 // |
64 // Compute when the frequency value of the biquad goes to 0. In | 65 // Compute when the frequency value of the biquad goes to 0. In |
65 // general, t = (T0*V1 -T1*V0)/(V1-V0) (using the notation from the | 66 // general, t = (T0*V1 -T1*V0)/(V1-V0) (using the notation from |
66 // spec.) | 67 // the spec.) |
67 var clampStartTime = solveLinearRamp(0, V0, T0, V1, T1); | 68 let clampStartTime = solveLinearRamp(0, V0, T0, V1, T1); |
68 var clampEndTime = solveLinearRamp(0, V1, T1, V2, T2); | 69 let clampEndTime = solveLinearRamp(0, V1, T1, V2, T2); |
69 | 70 |
70 var clampStartFrame = Math.ceil(clampStartTime * sampleRate); | 71 let clampStartFrame = Math.ceil(clampStartTime * sampleRate); |
71 var clampEndFrame = Math.floor(clampEndTime * sampleRate); | 72 let clampEndFrame = Math.floor(clampEndTime * sampleRate); |
72 | 73 |
73 var clampedSignal = result.slice(clampStartFrame, clampEndFrame + 1); | 74 let clampedSignal = |
74 var expectedSignal = new Float32Array(clampedSignal.length); | 75 result.slice(clampStartFrame, clampEndFrame + 1); |
75 expectedSignal.fill(0); | 76 let expectedSignal = new Float32Array(clampedSignal.length); |
| 77 expectedSignal.fill(0); |
76 | 78 |
77 // Output should be zero. | 79 // Output should be zero. |
78 should(clampedSignal, | 80 should( |
79 "Clamped signal in frame range [" + clampStartFrame + ", " + | 81 clampedSignal, |
80 clampEndFrame + "]") | 82 'Clamped signal in frame range [' + clampStartFrame + ', ' + |
81 .beCloseToArray(expectedSignal, 0); | 83 clampEndFrame + ']') |
| 84 .beCloseToArray(expectedSignal, 0); |
82 | 85 |
83 // Find the actual clamp range based on the output values. | 86 // Find the actual clamp range based on the output values. |
84 var actualClampStart = result.findIndex(x => x === 0); | 87 let actualClampStart = result.findIndex(x => x === 0); |
85 var actualClampEnd = actualClampStart + result.slice(actualClampStart)
.findIndex( | 88 let actualClampEnd = actualClampStart + |
86 x => x != 0); | 89 result.slice(actualClampStart).findIndex(x => x != 0); |
87 | 90 |
88 // Verify that the expected clamping range is a subset of the actual r
ange. | 91 // Verify that the expected clamping range is a subset of the |
89 should(actualClampStart, "Actual Clamp start") | 92 // actual range. |
90 .beLessThanOrEqualTo(clampStartFrame); | 93 should(actualClampStart, 'Actual Clamp start') |
91 should(actualClampEnd, "Actual Clamp end") | 94 .beLessThanOrEqualTo(clampStartFrame); |
92 .beGreaterThanOrEqualTo(clampEndFrame); | 95 should(actualClampEnd, 'Actual Clamp end') |
| 96 .beGreaterThanOrEqualTo(clampEndFrame); |
93 | 97 |
94 }).then(() => task.done()); | 98 }) |
| 99 .then(() => task.done()); |
95 }); | 100 }); |
96 | 101 |
97 audit.run(); | 102 audit.run(); |
98 | 103 |
99 function solveLinearRamp(v, v0, t0, v1, t1) { | 104 function solveLinearRamp(v, v0, t0, v1, t1) { |
100 // Solve the linear ramp equation for the time t at which the ramp | 105 // Solve the linear ramp equation for the time t at which the ramp |
101 // reaches the value v. The linear ramp equation (from the spec) is | 106 // reaches the value v. The linear ramp equation (from the spec) is |
102 // | 107 // |
103 // v(t) = v0 + (v1 - v0) * (t - t0)/(t1 - t0) | 108 // v(t) = v0 + (v1 - v0) * (t - t0)/(t1 - t0) |
104 // | 109 // |
105 // Find t such that | 110 // Find t such that |
106 // | 111 // |
107 // v = v0 + (v1 - v0) * (t - t0)/(t1 - t0) | 112 // v = v0 + (v1 - v0) * (t - t0)/(t1 - t0) |
108 // | 113 // |
109 // Then | 114 // Then |
110 // | 115 // |
111 // t = (t0 * v1 - t1 * v0 + (t1 - t0) * v) / (v1 - v0) | 116 // t = (t0 * v1 - t1 * v0 + (t1 - t0) * v) / (v1 - v0) |
112 // | 117 // |
113 return (t0 * v1 - t1 * v0 + (t1 - t0) * v) / (v1 - v0); | 118 return (t0 * v1 - t1 * v0 + (t1 - t0) * v) / (v1 - v0); |
114 } | 119 } |
115 </script> | 120 </script> |
116 </body> | 121 </body> |
117 </html> | 122 </html> |
OLD | NEW |