| <!DOCTYPE html> |
| <html> |
| <head> |
| <title> |
| Gain Dezippering Test: Dezippering Removed |
| </title> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="/webaudio/resources/audit-util.js"></script> |
| <script src="/webaudio/resources/audit.js"></script> |
| </head> |
| <body> |
| <script id="layout-test-code"> |
| let audit = Audit.createTaskRunner(); |
| |
| audit.define( |
| {label: 'test0', description: 'Dezippering of GainNode removed'}, |
| (task, should) => { |
| // Only need a few frames to verify that dezippering has been |
| // removed from the GainNode. Sample rate is pretty arbitrary. |
| let context = new OfflineAudioContext(1, 1024, 16000); |
| |
| // Send a unit source to the gain node so we can measure the effect |
| // of the gain node. |
| let src = new ConstantSourceNode(context, {offset: 1}); |
| let g = new GainNode(context, {gain: 1}); |
| src.connect(g).connect(context.destination); |
| |
| context.suspend(RENDER_QUANTUM_FRAMES / context.sampleRate) |
| .then(() => { |
| g.gain.value = .5; |
| }) |
| .then(() => context.resume()); |
| |
| src.start(); |
| |
| context.startRendering() |
| .then(audio => { |
| let c = audio.getChannelData(0); |
| |
| // If dezippering has been removed, the gain output should |
| // instantly jump at frame 128 to 0.5. |
| should(c.slice(0, 128), 'output[0:127]').beConstantValueOf(1); |
| should(c.slice(128), 'output[128:]').beConstantValueOf(0.5); |
| }) |
| .then(() => task.done()); |
| }); |
| |
| audit.define( |
| { |
| label: 'test2', |
| description: 'Compare value setter and setValueAtTime' |
| }, |
| (task, should) => { |
| testWithAutomation(should, {prefix: ''}).then(() => task.done()); |
| }); |
| |
| audit.define( |
| {label: 'test3', description: 'Automation effects'}, |
| (task, should) => { |
| testWithAutomation(should, { |
| prefix: 'With modulation: ', |
| modulator: true |
| }).then(() => task.done()); |
| }); |
| |
| audit.run(); |
| |
| function testWithAutomation(should, options) { |
| // Sample rate must be a power of two to eliminate round-off in |
| // computing the time at render quantum boundaries. |
| let context = new OfflineAudioContext(2, 1024, 16384); |
| let merger = new ChannelMergerNode(context, {numberOfChannels: 2}); |
| merger.connect(context.destination); |
| |
| let src = new OscillatorNode(context); |
| let gainTest = new GainNode(context); |
| let gainRef = new GainNode(context); |
| |
| src.connect(gainTest).connect(merger, 0, 0); |
| src.connect(gainRef).connect(merger, 0, 1); |
| |
| if (options.modulator) { |
| let mod = new OscillatorNode(context, {frequency: 1000}); |
| let modGain = new GainNode(context); |
| mod.connect(modGain); |
| modGain.connect(gainTest.gain); |
| modGain.connect(gainRef.gain); |
| mod.start(); |
| } |
| |
| // Change the gains. Must do the change on a render boundary! |
| let changeTime = 3 * RENDER_QUANTUM_FRAMES / context.sampleRate; |
| let newGain = .3; |
| |
| gainRef.gain.setValueAtTime(newGain, changeTime); |
| context.suspend(changeTime) |
| .then(() => gainTest.gain.value = newGain) |
| .then(() => context.resume()); |
| |
| src.start(); |
| |
| return context.startRendering().then(audio => { |
| let actual = audio.getChannelData(0); |
| let expected = audio.getChannelData(1); |
| |
| // The values using the .value setter must be identical to the |
| // values using setValueAtTime. |
| let match = should(actual, options.prefix + '.value setter output') |
| .beEqualToArray(expected); |
| |
| should( |
| match, |
| options.prefix + |
| '.value setter output matches setValueAtTime output') |
| .beTrue(); |
| }); |
| } |
| </script> |
| </body> |
| </html> |