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