audiobuffersource-playbackrate-zero.html (3788B)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>audiobuffersource-playbackrate-zero.html</title> 5 <script src="/resources/testharness.js"></script> 6 <script src="/resources/testharnessreport.js"></script> 7 <script src="/webaudio/resources/audit-util.js"></script> 8 </head> 9 <body> 10 <script> 11 // Sample rate should be power of 128 to observe the change of AudioParam 12 // at the beginning of rendering quantum. (playbackRate is k-rate) This is 13 // the minimum sample rate in the valid sample rate range. 14 const sampleRate = 8192; 15 16 // The render duration in seconds, and the length in samples. 17 const renderDuration = 1.0; 18 const renderLength = renderDuration * sampleRate; 19 20 const context = new OfflineAudioContext(1, renderLength, sampleRate); 21 22 promise_test(async t => { 23 const ramp = new AudioBufferSourceNode(context); 24 const rampBuffer = createLinearRampBuffer(context, renderLength); 25 ramp.buffer = rampBuffer; 26 27 ramp.connect(context.destination); 28 ramp.start(); 29 30 // Leave the playbackRate as 1 for the first half, then change it 31 // to zero at the exact half. The zero playback rate should hold the 32 // sample value of the buffer index at the moment. (sample-and-hold) 33 ramp.playbackRate.setValueAtTime(1.0, 0.0); 34 ramp.playbackRate.setValueAtTime(0.0, renderDuration / 2); 35 36 const renderedBuffer = await context.startRendering(); 37 38 const data = renderedBuffer.getChannelData(0); 39 const rampData = rampBuffer.getChannelData(0); 40 const half = rampData.length / 2; 41 42 let passed = true; 43 let i; 44 45 for (i = 1; i < rampData.length; i++) { 46 if (i < half) { 47 if (data[i] !== rampData[i]) { 48 passed = false; 49 break; 50 } 51 } else { 52 if (data[i] !== rampData[half]) { 53 passed = false; 54 break; 55 } 56 } 57 } 58 59 assert_true( 60 passed, 61 `The zero playbackRate should hold the sample value. Expected` + 62 `${rampData[half]} but got ${data[i]} at index ${i}`); 63 }, 'Synthesize and verify sample-and-hold behavior when playbackRate ' + 64 'is set to zero halfway'); 65 66 promise_test(async t => { 67 const context = new OfflineAudioContext(1, renderLength, sampleRate); 68 const rampBuffer = new AudioBuffer({ 69 length: renderLength, 70 sampleRate: context.sampleRate 71 }); 72 73 const data = new Float32Array(renderLength); 74 const startValue = 5; 75 76 for (let k = 0; k < data.length; ++k) { 77 data[k] = k + startValue; 78 } 79 80 rampBuffer.copyToChannel(data, 0); 81 82 const src = new AudioBufferSourceNode(context, { 83 buffer: rampBuffer, 84 playbackRate: 0 85 }); 86 87 src.connect(context.destination); 88 89 // Purposely start the source between frame boundaries 90 const startFrame = 27.3; 91 src.start(startFrame / context.sampleRate); 92 93 const audioBuffer = await context.startRendering(); 94 const actualStartFrame = Math.ceil(startFrame); 95 const audio = audioBuffer.getChannelData(0); 96 97 assert_constant_value( 98 audio.slice(0, actualStartFrame), 99 0, 100 'output before startFrame should be silence: '); 101 assert_constant_value( 102 audio.slice(actualStartFrame), 103 startValue, 104 `output after startFrame (starting at index ${actualStartFrame}) ` + 105 `should match start value: `); 106 }, 'Subsample start with playbackRate 0 should produce sample-and-hold ' + 107 'from exact start frame'); 108 </script> 109 </body> 110 </html>