| OLD | NEW |
| 1 <!doctype html> | 1 <!doctype html> |
| 2 <html> | 2 <html> |
| 3 <head> | 3 <head> |
| 4 <title>Test setTargetAtTime Approach to Limit</title> | 4 <title>Test setTargetAtTime Approach to Limit</title> |
| 5 <script src="../../resources/testharness.js"></script> | 5 <script src="../../resources/testharness.js"></script> |
| 6 <script src="../../resources/testharnessreport.js"></script> | 6 <script src="../../resources/testharnessreport.js"></script> |
| 7 <script src="../resources/audit-util.js"></script> | 7 <script src="../resources/audit-util.js"></script> |
| 8 <script src="../resources/audio-testing.js"></script> | 8 <script src="../resources/audit.js"></script> |
| 9 <script src="../resources/audioparam-testing.js"></script> | 9 <script src="../resources/audioparam-testing.js"></script> |
| 10 </head> | 10 </head> |
| 11 | 11 |
| 12 <body> | 12 <body> |
| 13 <script> | 13 <script> |
| 14 | 14 |
| 15 var audit = Audit.createTaskRunner(); | 15 var audit = Audit.createTaskRunner(); |
| 16 | 16 |
| 17 audit.defineTask("approach 1", function(done) { | 17 audit.define("approach 1", (task, should) => { |
| 18 var sampleRate = 48000; | 18 var sampleRate = 48000; |
| 19 | 19 |
| 20 // A really short time constant so that setTargetAtTime approaches the l
imiting value well | 20 // A really short time constant so that setTargetAtTime approaches the l
imiting value well |
| 21 // before the end of the test. | 21 // before the end of the test. |
| 22 var timeConstant = 0.001; | 22 var timeConstant = 0.001; |
| 23 | 23 |
| 24 // Find the time where setTargetAtTime is close enough to the limit. Si
nce we're | 24 // Find the time where setTargetAtTime is close enough to the limit. Si
nce we're |
| 25 // approaching 1, use a value of eps smaller than kSetTargetThreshold (5
e-7) in | 25 // approaching 1, use a value of eps smaller than kSetTargetThreshold (5
e-7) in |
| 26 // AudioParamTimeline.cpp. This is to account for round-off in the actu
al implementation | 26 // AudioParamTimeline.cpp. This is to account for round-off in the actu
al implementation |
| 27 // (which uses a filter and not the formula.) | 27 // (which uses a filter and not the formula.) |
| 28 var limitThreshold = 1e-7; | 28 var limitThreshold = 1e-7; |
| 29 | 29 |
| 30 runTest({ | 30 runTest(should, { |
| 31 sampleRate: sampleRate, | 31 sampleRate: sampleRate, |
| 32 v0: 0, | 32 v0: 0, |
| 33 v1: 1, | 33 v1: 1, |
| 34 timeConstant: timeConstant, | 34 timeConstant: timeConstant, |
| 35 eps: limitThreshold, | 35 eps: limitThreshold, |
| 36 // Experimentally determined | 36 // Experimentally determined |
| 37 threshold: 2.4e-5 | 37 threshold: 2.4e-5 |
| 38 }).then(done); | 38 }).then(() => task.done()); |
| 39 }) | 39 }) |
| 40 | 40 |
| 41 audit.defineTask("approach 0", function(done) { | 41 audit.define("approach 0", (task, should) => { |
| 42 // Use the equation for setTargetAtTime to figure out when we are close
to 0: | 42 // Use the equation for setTargetAtTime to figure out when we are close
to 0: |
| 43 // | 43 // |
| 44 // v(t) = exp(-t/tau) | 44 // v(t) = exp(-t/tau) |
| 45 // | 45 // |
| 46 // So find t such that exp(-t/tau) <= eps. Thus t >= - tau * log(eps). | 46 // So find t such that exp(-t/tau) <= eps. Thus t >= - tau * log(eps). |
| 47 // | 47 // |
| 48 // For eps, use 1e-20 (kSetTargetZeroThreshold in AudioParamTimeline.cpp
). | 48 // For eps, use 1e-20 (kSetTargetZeroThreshold in AudioParamTimeline.cpp
). |
| 49 | 49 |
| 50 var sampleRate = 48000; | 50 var sampleRate = 48000; |
| 51 | 51 |
| 52 // A really short time constant so that setTargetAtTime approaches the l
imiting value well | 52 // A really short time constant so that setTargetAtTime approaches the l
imiting value well |
| 53 // before the end of the test. | 53 // before the end of the test. |
| 54 var timeConstant = 0.001; | 54 var timeConstant = 0.001; |
| 55 | 55 |
| 56 // Find the time where setTargetAtTime is close enough to the limit. Si
nce we're | 56 // Find the time where setTargetAtTime is close enough to the limit. Si
nce we're |
| 57 // approaching 0, use a value of eps smaller than kSetTargetZeroThreshol
d (1e-20) in | 57 // approaching 0, use a value of eps smaller than kSetTargetZeroThreshol
d (1e-20) in |
| 58 // AudioParamTimeline.cpp. This is to account for round-off in the actu
al implementation | 58 // AudioParamTimeline.cpp. This is to account for round-off in the actu
al implementation |
| 59 // (which uses a filter and not the formula.) | 59 // (which uses a filter and not the formula.) |
| 60 var limitThreshold = 1e-21; | 60 var limitThreshold = 1e-21; |
| 61 | 61 |
| 62 runTest({ | 62 runTest(should, { |
| 63 sampleRate: sampleRate, | 63 sampleRate: sampleRate, |
| 64 v0: 1, | 64 v0: 1, |
| 65 v1: 0, | 65 v1: 0, |
| 66 timeConstant: timeConstant, | 66 timeConstant: timeConstant, |
| 67 eps: limitThreshold, | 67 eps: limitThreshold, |
| 68 // Experimentally determined | 68 // Experimentally determined |
| 69 threshold: 1.3e-7 | 69 threshold: 1.3e-7 |
| 70 }).then(done); | 70 }).then(() => task.done()); |
| 71 }); | 71 }); |
| 72 | 72 |
| 73 function findLimitTime(v0, v1, timeConstant, eps) { | 73 function findLimitTime(v0, v1, timeConstant, eps) { |
| 74 // Find the time at which the setTargetAtTime is close enough to the tar
get value |v1| where | 74 // Find the time at which the setTargetAtTime is close enough to the tar
get value |v1| where |
| 75 // we can consider the curve to have reached its limiting value. | 75 // we can consider the curve to have reached its limiting value. |
| 76 // | 76 // |
| 77 // If v1 = 0, |eps| is the absolute error between the actual value and | 77 // If v1 = 0, |eps| is the absolute error between the actual value and |
| 78 // |v1|. Otherwise, |eps| is the relative error between the actual valu
e and |v1|. | 78 // |v1|. Otherwise, |eps| is the relative error between the actual valu
e and |v1|. |
| 79 // | 79 // |
| 80 // The curve is | 80 // The curve is |
| (...skipping 11 matching lines...) Expand all Loading... |
| 92 // For v1 not zero, we want |v(t) - v1|/|v1| <= eps: | 92 // For v1 not zero, we want |v(t) - v1|/|v1| <= eps: |
| 93 // | 93 // |
| 94 // t >= timeConstant * log(abs(v1-v0)/eps/v1) | 94 // t >= timeConstant * log(abs(v1-v0)/eps/v1) |
| 95 | 95 |
| 96 if (v1) | 96 if (v1) |
| 97 return timeConstant * Math.log(Math.abs(v1-v0)/eps/v1); | 97 return timeConstant * Math.log(Math.abs(v1-v0)/eps/v1); |
| 98 else | 98 else |
| 99 return timeConstant * Math.log(v0/eps); | 99 return timeConstant * Math.log(v0/eps); |
| 100 } | 100 } |
| 101 | 101 |
| 102 function runTest(options) { | 102 function runTest(should, options) { |
| 103 var renderLength = 1; | 103 var renderLength = 1; |
| 104 | 104 |
| 105 var context = new OfflineAudioContext(1, renderLength * sampleRate, opti
ons.sampleRate); | 105 var context = new OfflineAudioContext(1, renderLength * sampleRate, opti
ons.sampleRate); |
| 106 | 106 |
| 107 // A constant source | 107 // A constant source |
| 108 var source = context.createBufferSource(); | 108 var source = context.createBufferSource(); |
| 109 source.buffer = createConstantBuffer(context, 1, 1); | 109 source.buffer = createConstantBuffer(context, 1, 1); |
| 110 source.loop = true; | 110 source.loop = true; |
| 111 | 111 |
| 112 var gain = context.createGain(); | 112 var gain = context.createGain(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 124 options.v0, options.v1, | 124 options.v0, options.v1, |
| 125 options.sampleRate, options.timeConstant); | 125 options.sampleRate, options.timeConstant); |
| 126 | 126 |
| 127 var message = "setTargetAtTime(" + options.v1 + ", 0, " + options.time
Constant + ")"; | 127 var message = "setTargetAtTime(" + options.v1 + ", 0, " + options.time
Constant + ")"; |
| 128 | 128 |
| 129 // Determine where the tail of the curve begins. (Where the curve has
basically reached | 129 // Determine where the tail of the curve begins. (Where the curve has
basically reached |
| 130 // the limit value.) | 130 // the limit value.) |
| 131 var tailTime = findLimitTime(options.v0, options.v1, options.timeConst
ant, options.eps); | 131 var tailTime = findLimitTime(options.v0, options.v1, options.timeConst
ant, options.eps); |
| 132 var tailFrame = Math.ceil(tailTime * options.sampleRate); | 132 var tailFrame = Math.ceil(tailTime * options.sampleRate); |
| 133 | 133 |
| 134 var success = true; | 134 should(actual.slice(0, tailFrame), |
| 135 success = Should("Initial output of " + tailFrame + " samples for " +
message, | 135 "Initial output of " + tailFrame + " samples for " + message) |
| 136 actual.slice(0, tailFrame), { numberOfArrayLog: 8 }) | 136 .beCloseToArray(expected.slice(0, tailFrame), { |
| 137 .beCloseToArray(expected.slice(0, tailFrame), options.threshold) &&
success; | 137 absoluteThreshold: options.threshold |
| 138 }); |
| 138 | 139 |
| 139 success = Should("Tail output for " + message, | 140 should(actual.slice(tailFrame), "Tail output for " + message) |
| 140 actual.slice(tailFrame)) | 141 .containValues([options.v1]); |
| 141 .containValues([options.v1]) && success; | |
| 142 | |
| 143 Should(message, success) | |
| 144 .summarize("had the expected values", | |
| 145 "did not have the expected values"); | |
| 146 }); | 142 }); |
| 147 } | 143 } |
| 148 | 144 |
| 149 audit.defineTask("finish", function (done) { | 145 audit.run(); |
| 150 done(); | |
| 151 }); | |
| 152 | |
| 153 audit.runTasks(); | |
| 154 </script> | 146 </script> |
| 155 </body> | 147 </body> |
| 156 </html> | 148 </html> |
| OLD | NEW |