| OLD | NEW |
| 1 <!DOCTYPE html> | 1 <!DOCTYPE html> |
| 2 | |
| 3 <!-- | 2 <!-- |
| 4 Tests that we are able to schedule a series of notes to playback with sample-acc
uracy. | 3 Tests that we are able to schedule a series of notes to playback with sample-acc
uracy. |
| 5 We use an impulse so we can tell exactly where the rendering is happening. | 4 We use an impulse so we can tell exactly where the rendering is happening. |
| 6 --> | 5 --> |
| 6 <html> |
| 7 <head> |
| 8 <title> |
| 9 sample-accurate-scheduling.html |
| 10 </title> |
| 11 <script src="../../resources/testharness.js"></script> |
| 12 <script src="../../resources/testharnessreport.js"></script> |
| 13 <script src="../resources/audit-util.js"></script> |
| 14 <script src="../resources/audit.js"></script> |
| 15 <script src="../resources/buffer-loader.js"></script> |
| 16 </head> |
| 17 <body> |
| 18 <script id="layout-test-code"> |
| 19 let audit = Audit.createTaskRunner(); |
| 7 | 20 |
| 8 <html> | 21 let sampleRate = 44100.0; |
| 9 <head> | 22 let lengthInSeconds = 4; |
| 10 <script src="../../resources/testharness.js"></script> | |
| 11 <script src="../../resources/testharnessreport.js"></script> | |
| 12 <script src="../resources/audit-util.js"></script> | |
| 13 <script src="../resources/audit.js"></script> | |
| 14 <script src="../resources/buffer-loader.js"></script> | |
| 15 </head> | |
| 16 | 23 |
| 17 <body> | 24 let context = 0; |
| 25 let bufferLoader = 0; |
| 26 let impulse; |
| 18 | 27 |
| 19 <script> | 28 // See if we can render at exactly these sample offsets. |
| 20 let audit = Audit.createTaskRunner(); | 29 let sampleOffsets = [0, 3, 512, 517, 1000, 1005, 20000, 21234, 37590]; |
| 21 | 30 |
| 22 let sampleRate = 44100.0; | 31 function createImpulse() { |
| 23 let lengthInSeconds = 4; | 32 // An impulse has a value of 1 at time 0, and is otherwise 0. |
| 33 impulse = context.createBuffer(2, 512, sampleRate); |
| 34 let sampleDataL = impulse.getChannelData(0); |
| 35 let sampleDataR = impulse.getChannelData(1); |
| 36 sampleDataL[0] = 1.0; |
| 37 sampleDataR[0] = 1.0; |
| 38 } |
| 24 | 39 |
| 25 let context = 0; | 40 function playNote(time) { |
| 26 let bufferLoader = 0; | 41 let bufferSource = context.createBufferSource(); |
| 27 let impulse; | 42 bufferSource.buffer = impulse; |
| 43 bufferSource.connect(context.destination); |
| 44 bufferSource.start(time); |
| 45 } |
| 28 | 46 |
| 29 // See if we can render at exactly these sample offsets. | 47 function checkSampleAccuracy(buffer, should) { |
| 30 let sampleOffsets = [0, 3, 512, 517, 1000, 1005, 20000, 21234, 37590]; | 48 let bufferDataL = buffer.getChannelData(0); |
| 49 let bufferDataR = buffer.getChannelData(1); |
| 31 | 50 |
| 32 function createImpulse() { | 51 let impulseCount = 0; |
| 33 // An impulse has a value of 1 at time 0, and is otherwise 0. | 52 let badOffsetCount = 0; |
| 34 impulse = context.createBuffer(2, 512, sampleRate); | |
| 35 let sampleDataL = impulse.getChannelData(0); | |
| 36 let sampleDataR = impulse.getChannelData(1); | |
| 37 sampleDataL[0] = 1.0; | |
| 38 sampleDataR[0] = 1.0; | |
| 39 } | |
| 40 | 53 |
| 41 function playNote(time) { | 54 // Left and right channels must be the same. |
| 42 let bufferSource = context.createBufferSource(); | 55 should(bufferDataL, 'Content of left and right channels match and') |
| 43 bufferSource.buffer = impulse; | 56 .beEqualToArray(bufferDataR); |
| 44 bufferSource.connect(context.destination); | |
| 45 bufferSource.start(time); | |
| 46 } | |
| 47 | 57 |
| 48 function checkSampleAccuracy(buffer, should) { | 58 // Go through every sample and make sure it's 0, except at positions in |
| 49 let bufferDataL = buffer.getChannelData(0); | 59 // sampleOffsets. |
| 50 let bufferDataR = buffer.getChannelData(1); | 60 for (let i = 0; i < buffer.length; ++i) { |
| 51 | 61 if (bufferDataL[i] != 0) { |
| 52 let impulseCount = 0; | |
| 53 let badOffsetCount = 0; | |
| 54 | |
| 55 // Left and right channels must be the same. | |
| 56 should(bufferDataL, "Content of left and right channels match and") | |
| 57 .beEqualToArray(bufferDataR); | |
| 58 | |
| 59 // Go through every sample and make sure it's 0, except at positions in | |
| 60 // sampleOffsets. | |
| 61 for (let i = 0; i < buffer.length; ++i) { | |
| 62 if (bufferDataL[i] != 0) { | |
| 63 // Make sure this index is in sampleOffsets | 62 // Make sure this index is in sampleOffsets |
| 64 let found = false; | 63 let found = false; |
| 65 for (let j = 0; j < sampleOffsets.length; ++j) { | 64 for (let j = 0; j < sampleOffsets.length; ++j) { |
| 66 if (sampleOffsets[j] == i) { | 65 if (sampleOffsets[j] == i) { |
| 67 found = true; | 66 found = true; |
| 68 break; | 67 break; |
| 69 } | 68 } |
| 70 } | 69 } |
| 71 ++impulseCount; | 70 ++impulseCount; |
| 72 should(found, "Non-zero sample found at sample offset " + i) | 71 should(found, 'Non-zero sample found at sample offset ' + i) |
| 73 .beTrue(); | 72 .beTrue(); |
| 74 if (!found) { | 73 if (!found) { |
| 75 ++badOffsetCount; | 74 ++badOffsetCount; |
| 76 } | 75 } |
| 76 } |
| 77 } | 77 } |
| 78 } | |
| 79 | 78 |
| 80 should(impulseCount, "Number of impulses found") | 79 should(impulseCount, 'Number of impulses found') |
| 81 .beEqualTo(sampleOffsets.length); | 80 .beEqualTo(sampleOffsets.length); |
| 82 | 81 |
| 83 if (impulseCount == sampleOffsets.length) { | 82 if (impulseCount == sampleOffsets.length) { |
| 84 should(badOffsetCount, "bad offset") | 83 should(badOffsetCount, 'bad offset').beEqualTo(0); |
| 85 .beEqualTo(0); | 84 } |
| 86 } | 85 } |
| 87 } | |
| 88 | 86 |
| 89 audit.define({ | 87 audit.define( |
| 90 label: "test", | 88 {label: 'test', description: 'Test sample-accurate scheduling'}, |
| 91 description: "Test sample-accurate scheduling" | 89 function(task, should) { |
| 92 }, function (task, should) { | |
| 93 | 90 |
| 94 // Create offline audio context. | 91 // Create offline audio context. |
| 95 context = new OfflineAudioContext(2, sampleRate * lengthInSeconds, | 92 context = new OfflineAudioContext( |
| 96 sampleRate); | 93 2, sampleRate * lengthInSeconds, sampleRate); |
| 97 createImpulse(); | 94 createImpulse(); |
| 98 | 95 |
| 99 for (let i = 0; i < sampleOffsets.length; ++i) { | 96 for (let i = 0; i < sampleOffsets.length; ++i) { |
| 100 let timeInSeconds = sampleOffsets[i] / sampleRate; | 97 let timeInSeconds = sampleOffsets[i] / sampleRate; |
| 101 playNote(timeInSeconds); | 98 playNote(timeInSeconds); |
| 102 } | 99 } |
| 103 | |
| 104 context.startRendering() | |
| 105 .then(function (buffer) { | |
| 106 checkSampleAccuracy(buffer, should); | |
| 107 task.done(); | |
| 108 }); | |
| 109 }); | |
| 110 | 100 |
| 111 audit.run(); | 101 context.startRendering().then(function(buffer) { |
| 112 </script> | 102 checkSampleAccuracy(buffer, should); |
| 103 task.done(); |
| 104 }); |
| 105 }); |
| 113 | 106 |
| 114 </body> | 107 audit.run(); |
| 108 </script> |
| 109 </body> |
| 115 </html> | 110 </html> |
| OLD | NEW |