| OLD | NEW |
| 1 <!DOCTYPE html> | 1 <!DOCTYPE html> |
| 2 | 2 |
| 3 <html> | 3 <html> |
| 4 <head> | 4 <head> |
| 5 <script src="../../resources/js-test.js"></script> | 5 <script src="../../resources/testharness.js"></script> |
| 6 <script src="../../resources/testharnessreport.js"></script> |
| 6 <script src="../resources/audit-util.js"></script> | 7 <script src="../resources/audit-util.js"></script> |
| 7 <script src="../resources/audio-testing.js"></script> | 8 <script src="../resources/audit.js"></script> |
| 8 <script src="../resources/mixing-rules.js"></script> | 9 <script src="../resources/mixing-rules.js"></script> |
| 9 </head> | 10 </head> |
| 10 | 11 |
| 11 <body> | 12 <body> |
| 12 | 13 |
| 13 <script> | 14 <script> |
| 14 description("Channel mixing rules for AudioNodes."); | 15 let audit = Audit.createTaskRunner(); |
| 16 let context = 0; |
| 17 let sampleRate = 44100; |
| 18 let renderNumberOfChannels = 8; |
| 19 let singleTestFrameLength = 8; |
| 20 let testBuffers; |
| 15 | 21 |
| 16 var context = 0; | 22 // A list of connections to an AudioNode input, each of which is to be used in |
| 17 var sampleRate = 44100; | 23 // one or more specific test cases. Each element in the list is a string, with |
| 18 var renderNumberOfChannels = 8; | 24 // the number of connections corresponding to the length of the string, and each |
| 19 var singleTestFrameLength = 8; | 25 // character in the string is from '1' to '8' representing a 1 to 8 channel |
| 20 var testBuffers; | 26 // connection (from an AudioNode output). |
| 21 | 27 |
| 22 // A list of connections to an AudioNode input, each of which is to be used in o
ne or more specific test cases. | 28 // For example, the string "128" means 3 connections, having 1, 2, and 8 |
| 23 // Each element in the list is a string, with the number of connections correspo
nding to the length of the string, | 29 // channels respectively. |
| 24 // and each character in the string is from '1' to '8' representing a 1 to 8 cha
nnel connection (from an AudioNode output). | |
| 25 // For example, the string "128" means 3 connections, having 1, 2, and 8 channel
s respectively. | |
| 26 var connectionsList = ["1", "2", "3", "4", "5", "6", "7", "8", "11", "12", "14",
"18", "111", "122", "123", "124", "128"]; | |
| 27 | 30 |
| 28 // A list of mixing rules, each of which will be tested against all of the conne
ctions in connectionsList. | 31 let connectionsList = ["1", "2", "3", "4", "5", "6", "7", "8", "11", "12", |
| 29 var mixingRulesList = [ | 32 "14", "18", "111", "122", "123", "124", "128" |
| 33 ]; |
| 34 |
| 35 // A list of mixing rules, each of which will be tested against all of the |
| 36 // connections in connectionsList. |
| 37 let mixingRulesList = [ |
| 30 {channelCount: 2, channelCountMode: "max", channelInterpretation: "speakers"
}, | 38 {channelCount: 2, channelCountMode: "max", channelInterpretation: "speakers"
}, |
| 31 {channelCount: 4, channelCountMode: "clamped-max", channelInterpretation: "s
peakers"}, | 39 {channelCount: 4, channelCountMode: "clamped-max", channelInterpretation: "s
peakers"}, |
| 32 | 40 |
| 33 // Test up-down-mix to some explicit speaker layouts. | 41 // Test up-down-mix to some explicit speaker layouts. |
| 34 {channelCount: 1, channelCountMode: "explicit", channelInterpretation: "spea
kers"}, | 42 {channelCount: 1, channelCountMode: "explicit", channelInterpretation: "spea
kers"}, |
| 35 {channelCount: 2, channelCountMode: "explicit", channelInterpretation: "spea
kers"}, | 43 {channelCount: 2, channelCountMode: "explicit", channelInterpretation: "spea
kers"}, |
| 36 {channelCount: 4, channelCountMode: "explicit", channelInterpretation: "spea
kers"}, | 44 {channelCount: 4, channelCountMode: "explicit", channelInterpretation: "spea
kers"}, |
| 37 {channelCount: 6, channelCountMode: "explicit", channelInterpretation: "spea
kers"}, | 45 {channelCount: 6, channelCountMode: "explicit", channelInterpretation: "spea
kers"}, |
| 38 | 46 |
| 39 {channelCount: 2, channelCountMode: "max", channelInterpretation: "discrete"
}, | 47 {channelCount: 2, channelCountMode: "max", channelInterpretation: "discrete"
}, |
| 40 {channelCount: 4, channelCountMode: "clamped-max", channelInterpretation: "d
iscrete"}, | 48 {channelCount: 4, channelCountMode: "clamped-max", channelInterpretation: "d
iscrete"}, |
| 41 {channelCount: 4, channelCountMode: "explicit", channelInterpretation: "disc
rete"}, | 49 {channelCount: 4, channelCountMode: "explicit", channelInterpretation: "disc
rete"}, |
| 42 {channelCount: 8, channelCountMode: "explicit", channelInterpretation: "disc
rete"}, | 50 {channelCount: 8, channelCountMode: "explicit", channelInterpretation: "disc
rete"}, |
| 43 ]; | 51 ]; |
| 44 | 52 |
| 45 var numberOfTests = mixingRulesList.length * connectionsList.length; | 53 let numberOfTests = mixingRulesList.length * connectionsList.length; |
| 46 | 54 |
| 47 // Print out the information for an individual test case. | 55 // Print out the information for an individual test case. |
| 48 function printTestInformation(testNumber, actualBuffer, expectedBuffer, frameLen
gth, frameOffset) { | 56 function printTestInformation(testNumber, actualBuffer, expectedBuffer, |
| 49 var actual = stringifyBuffer(actualBuffer, frameLength); | 57 frameLength, frameOffset) { |
| 50 var expected = stringifyBuffer(expectedBuffer, frameLength, frameOffset); | 58 let actual = stringifyBuffer(actualBuffer, frameLength); |
| 51 debug('TEST CASE #' + testNumber + '\n'); | 59 let expected = stringifyBuffer(expectedBuffer, frameLength, frameOffset); |
| 52 debug('actual channels:\n' + actual); | 60 debug('TEST CASE #' + testNumber + '\n'); |
| 53 debug('expected channels:\n' + expected); | 61 debug('actual channels:\n' + actual); |
| 62 debug('expected channels:\n' + expected); |
| 54 } | 63 } |
| 55 | 64 |
| 56 function scheduleTest(testNumber, connections, channelCount, channelCountMode, c
hannelInterpretation) { | 65 function scheduleTest(testNumber, connections, channelCount, channelCountMode, |
| 57 var mixNode = context.createGain(); | 66 channelInterpretation) { |
| 67 let mixNode = context.createGain(); |
| 58 mixNode.channelCount = channelCount; | 68 mixNode.channelCount = channelCount; |
| 59 mixNode.channelCountMode = channelCountMode; | 69 mixNode.channelCountMode = channelCountMode; |
| 60 mixNode.channelInterpretation = channelInterpretation; | 70 mixNode.channelInterpretation = channelInterpretation; |
| 61 mixNode.connect(context.destination); | 71 mixNode.connect(context.destination); |
| 62 | 72 |
| 63 for (var i = 0; i < connections.length; ++i) { | 73 for (let i = 0; i < connections.length; ++i) { |
| 64 var connectionNumberOfChannels = connections.charCodeAt(i) - "0".charCod
eAt(0); | 74 let connectionNumberOfChannels = connections.charCodeAt(i) - "0".charCod
eAt( |
| 75 0); |
| 65 | 76 |
| 66 var source = context.createBufferSource(); | 77 let source = context.createBufferSource(); |
| 67 // Get a buffer with the right number of channels, converting from 1-bas
ed to 0-based index. | 78 // Get a buffer with the right number of channels, converting from 1-bas
ed to 0-based index. |
| 68 var buffer = testBuffers[connectionNumberOfChannels - 1]; | 79 let buffer = testBuffers[connectionNumberOfChannels - 1]; |
| 69 source.buffer = buffer; | 80 source.buffer = buffer; |
| 70 source.connect(mixNode); | 81 source.connect(mixNode); |
| 71 | 82 |
| 72 // Start at the right offset. | 83 // Start at the right offset. |
| 73 var sampleFrameOffset = testNumber * singleTestFrameLength; | 84 let sampleFrameOffset = testNumber * singleTestFrameLength; |
| 74 var time = sampleFrameOffset / sampleRate; | 85 let time = sampleFrameOffset / sampleRate; |
| 75 source.start(time); | 86 source.start(time); |
| 76 } | 87 } |
| 77 } | 88 } |
| 78 | 89 |
| 79 function checkTestResult(renderedBuffer, testNumber, connections, channelCount,
channelCountMode, channelInterpretation) { | 90 function checkTestResult(renderedBuffer, testNumber, connections, channelCount, |
| 80 var s = "connections: " + connections + ", " + channelCountMode; | 91 channelCountMode, channelInterpretation, should) { |
| 92 let s = "connections: " + connections + ", " + channelCountMode; |
| 81 | 93 |
| 82 // channelCount is ignored in "max" mode. | 94 // channelCount is ignored in "max" mode. |
| 83 if (channelCountMode == "clamped-max" || channelCountMode == "explicit") { | 95 if (channelCountMode == "clamped-max" || channelCountMode == "explicit") { |
| 84 s += "(" + channelCount + ")"; | 96 s += "(" + channelCount + ")"; |
| 85 } | 97 } |
| 86 | 98 |
| 87 s += ", " + channelInterpretation; | 99 s += ", " + channelInterpretation; |
| 88 | 100 |
| 89 var computedNumberOfChannels = computeNumberOfChannels(connections, channelC
ount, channelCountMode); | 101 let computedNumberOfChannels = computeNumberOfChannels(connections, |
| 102 channelCount, channelCountMode); |
| 90 | 103 |
| 91 // Create a zero-initialized silent AudioBuffer with computedNumberOfChannel
s. | 104 // Create a zero-initialized silent AudioBuffer with computedNumberOfChannel
s. |
| 92 var destBuffer = context.createBuffer(computedNumberOfChannels, singleTestFr
ameLength, context.sampleRate); | 105 let destBuffer = context.createBuffer(computedNumberOfChannels, |
| 106 singleTestFrameLength, context.sampleRate); |
| 93 | 107 |
| 94 // Mix all of the connections into the destination buffer. | 108 // Mix all of the connections into the destination buffer. |
| 95 for (var i = 0; i < connections.length; ++i) { | 109 for (let i = 0; i < connections.length; ++i) { |
| 96 var connectionNumberOfChannels = connections.charCodeAt(i) - "0".charCod
eAt(0); | 110 let connectionNumberOfChannels = connections.charCodeAt(i) - "0".charCod
eAt( |
| 97 var sourceBuffer = testBuffers[connectionNumberOfChannels - 1]; // conve
rt from 1-based to 0-based index | 111 0); |
| 112 let sourceBuffer = testBuffers[connectionNumberOfChannels - 1]; // conve
rt from 1-based to 0-based index |
| 98 | 113 |
| 99 if (channelInterpretation == "speakers") { | 114 if (channelInterpretation == "speakers") { |
| 100 speakersSum(sourceBuffer, destBuffer); | 115 speakersSum(sourceBuffer, destBuffer); |
| 101 } else if (channelInterpretation == "discrete") { | 116 } else if (channelInterpretation == "discrete") { |
| 102 discreteSum(sourceBuffer, destBuffer); | 117 discreteSum(sourceBuffer, destBuffer); |
| 103 } else { | 118 } else { |
| 104 alert("Invalid channel interpretation!"); | 119 alert("Invalid channel interpretation!"); |
| 105 } | 120 } |
| 106 } | 121 } |
| 107 | 122 |
| 108 // Use this when debugging mixing rules. | 123 // Use this when debugging mixing rules. |
| 109 // printTestInformation(testNumber, renderedBuffer, destBuffer, singleTestFr
ameLength, sampleFrameOffset); | 124 // printTestInformation(testNumber, renderedBuffer, destBuffer, |
| 125 // singleTestFrameLength, sampleFrameOffset); |
| 110 | 126 |
| 111 // Validate that destBuffer matches the rendered output. | 127 // Validate that destBuffer matches the rendered output. We need to check |
| 112 // We need to check the rendered output at a specific sample-frame-offset co
rresponding | 128 // the rendered output at a specific sample-frame-offset corresponding to |
| 113 // to the specific test case we're checking for based on testNumber. | 129 // the specific test case we're checking for based on testNumber. |
| 114 | 130 |
| 115 var sampleFrameOffset = testNumber * singleTestFrameLength; | 131 let sampleFrameOffset = testNumber * singleTestFrameLength; |
| 116 for (var c = 0; c < renderNumberOfChannels; ++c) { | 132 for (let c = 0; c < renderNumberOfChannels; ++c) { |
| 117 var renderedData = renderedBuffer.getChannelData(c); | 133 let renderedData = renderedBuffer.getChannelData(c); |
| 118 for (var frame = 0; frame < singleTestFrameLength; ++frame) { | 134 for (let frame = 0; frame < singleTestFrameLength; ++frame) { |
| 119 var renderedValue = renderedData[frame + sampleFrameOffset]; | 135 let renderedValue = renderedData[frame + sampleFrameOffset]; |
| 120 | 136 |
| 121 var expectedValue = 0; | 137 let expectedValue = 0; |
| 122 if (c < destBuffer.numberOfChannels) { | 138 if (c < destBuffer.numberOfChannels) { |
| 123 var expectedData = destBuffer.getChannelData(c); | 139 let expectedData = destBuffer.getChannelData(c); |
| 124 expectedValue = expectedData[frame]; | 140 expectedValue = expectedData[frame]; |
| 125 } | 141 } |
| 126 | 142 |
| 127 // We may need to add an epsilon in the comparison if we add more te
st vectors. | 143 // We may need to add an epsilon in the comparison if we add more |
| 144 // test vectors. |
| 128 if (renderedValue != expectedValue) { | 145 if (renderedValue != expectedValue) { |
| 129 var message = s + "rendered: " + renderedValue + " expected: " +
expectedValue + " channel: " + c + " frame: " + frame; | 146 let message = s + "rendered: " + renderedValue + " expected: " + |
| 130 testFailed(s); | 147 expectedValue + " channel: " + c + " frame: " + frame; |
| 148 //testFailed(s); |
| 149 should(renderedValue, s) |
| 150 .beEqualTo(expectedValue); |
| 131 return; | 151 return; |
| 132 } | 152 } |
| 133 } | 153 } |
| 134 } | 154 } |
| 135 | 155 |
| 136 testPassed(s); | 156 should(true, s) |
| 157 .beTrue(); |
| 137 } | 158 } |
| 138 | 159 |
| 139 function checkResult(event) { | 160 function checkResult(buffer, should) { |
| 140 var buffer = event.renderedBuffer; | |
| 141 | |
| 142 // Sanity check result. | 161 // Sanity check result. |
| 143 if (buffer.length != numberOfTests * singleTestFrameLength || buffer.numberO
fChannels != renderNumberOfChannels) { | 162 should(buffer.length, "Rendered number of frames") |
| 144 testFailed("OfflineAudioContext result not of expected size!"); | 163 .beEqualTo(numberOfTests * singleTestFrameLength); |
| 145 finishJSTest(); | 164 should(buffer.numberOfChannels, "Rendered number of channels") |
| 146 return; | 165 .beEqualTo(renderNumberOfChannels); |
| 147 } | |
| 148 | 166 |
| 149 // Check all the tests. | 167 // Check all the tests. |
| 150 var testNumber = 0; | 168 let testNumber = 0; |
| 151 for (var m = 0; m < mixingRulesList.length; ++m) { | 169 for (let m = 0; m < mixingRulesList.length; ++m) { |
| 152 var mixingRules = mixingRulesList[m]; | 170 let mixingRules = mixingRulesList[m]; |
| 153 for (var i = 0; i < connectionsList.length; ++i, ++testNumber) { | 171 for (let i = 0; i < connectionsList.length; ++i, ++testNumber) { |
| 154 checkTestResult(buffer, testNumber, connectionsList[i], mixingRules.
channelCount, mixingRules.channelCountMode, mixingRules.channelInterpretation); | 172 checkTestResult(buffer, testNumber, connectionsList[i], |
| 173 mixingRules.channelCount, mixingRules.channelCountMode, |
| 174 mixingRules.channelInterpretation, should); |
| 155 } | 175 } |
| 156 } | 176 } |
| 157 | |
| 158 finishJSTest(); | |
| 159 } | 177 } |
| 160 | 178 |
| 161 function runTest() { | 179 audit.define("test", function (task, should) { |
| 162 if (window.testRunner) { | 180 task.describe("Channel mixing rules for AudioNodes"); |
| 163 testRunner.dumpAsText(); | |
| 164 testRunner.waitUntilDone(); | |
| 165 } | |
| 166 | 181 |
| 167 window.jsTestIsAsync = true; | 182 // Create 8-channel offline audio context. Each test will render 8 |
| 168 | 183 // sample-frames starting at sample-frame position testNumber * 8. |
| 169 // Create 8-channel offline audio context. | 184 let totalFrameLength = numberOfTests * singleTestFrameLength; |
| 170 // Each test will render 8 sample-frames starting at sample-frame position t
estNumber * 8. | 185 context = new OfflineAudioContext(renderNumberOfChannels, |
| 171 var totalFrameLength = numberOfTests * singleTestFrameLength; | 186 totalFrameLength, sampleRate); |
| 172 context = new OfflineAudioContext(renderNumberOfChannels, totalFrameLength,
sampleRate); | |
| 173 | 187 |
| 174 // Set destination to discrete mixing. | 188 // Set destination to discrete mixing. |
| 175 context.destination.channelCount = renderNumberOfChannels; | 189 context.destination.channelCount = renderNumberOfChannels; |
| 176 context.destination.channelCountMode = "explicit"; | 190 context.destination.channelCountMode = "explicit"; |
| 177 context.destination.channelInterpretation = "discrete"; | 191 context.destination.channelInterpretation = "discrete"; |
| 178 | 192 |
| 179 // Create test buffers from 1 to 8 channels. | 193 // Create test buffers from 1 to 8 channels. |
| 180 testBuffers = new Array(); | 194 testBuffers = new Array(); |
| 181 for (var i = 0; i < renderNumberOfChannels; ++i) { | 195 for (let i = 0; i < renderNumberOfChannels; ++i) { |
| 182 testBuffers[i] = createShiftedImpulseBuffer(context, i + 1, singleTestFr
ameLength); | 196 testBuffers[i] = createShiftedImpulseBuffer(context, i + 1, |
| 197 singleTestFrameLength); |
| 183 } | 198 } |
| 184 | 199 |
| 185 // Schedule all the tests. | 200 // Schedule all the tests. |
| 186 var testNumber = 0; | 201 let testNumber = 0; |
| 187 for (var m = 0; m < mixingRulesList.length; ++m) { | 202 for (let m = 0; m < mixingRulesList.length; ++m) { |
| 188 var mixingRules = mixingRulesList[m]; | 203 let mixingRules = mixingRulesList[m]; |
| 189 for (var i = 0; i < connectionsList.length; ++i, ++testNumber) { | 204 for (let i = 0; i < connectionsList.length; ++i, ++testNumber) { |
| 190 scheduleTest(testNumber, connectionsList[i], mixingRules.channelCoun
t, mixingRules.channelCountMode, mixingRules.channelInterpretation); | 205 scheduleTest(testNumber, connectionsList[i], mixingRules.channelCoun
t, |
| 206 mixingRules.channelCountMode, mixingRules.channelInterpretation |
| 207 ); |
| 191 } | 208 } |
| 192 } | 209 } |
| 193 | 210 |
| 194 // Render then check results. | 211 // Render then check results. |
| 195 context.oncomplete = checkResult; | 212 //context.oncomplete = checkResult; |
| 196 context.startRendering(); | 213 context.startRendering() |
| 197 } | 214 .then(buffer => { |
| 215 checkResult(buffer, should); |
| 216 task.done(); |
| 217 });; |
| 218 }); |
| 198 | 219 |
| 199 runTest(); | 220 audit.run(); |
| 200 | 221 |
| 201 </script> | 222 </script> |
| 202 | 223 |
| 203 </body> | 224 </body> |
| 204 </html> | 225 </html> |
| OLD | NEW |