Index: third_party/WebKit/LayoutTests/webaudio/Convolver/convolver-response-1-chan.html |
diff --git a/third_party/WebKit/LayoutTests/webaudio/Convolver/convolver-response-1-chan.html b/third_party/WebKit/LayoutTests/webaudio/Convolver/convolver-response-1-chan.html |
new file mode 100644 |
index 0000000000000000000000000000000000000000..2bc21ab96ca395ce326b57319f068438f720ab74 |
--- /dev/null |
+++ b/third_party/WebKit/LayoutTests/webaudio/Convolver/convolver-response-1-chan.html |
@@ -0,0 +1,230 @@ |
+<!doctype html> |
+<html> |
+ <head> |
+ <title>Test Convolver Channel Outputs for Response with 1 channel</title> |
+ <script src="../../resources/testharness.js"></script> |
+ <script src="../../resources/testharnessreport.js"></script> |
+ <script src="../resources/audit-util.js"></script> |
+ <script src="../resources/audit.js"></script> |
+ </head> |
+ |
+ <body> |
+ <script> |
+ // Test various convolver configurations when the convolver response has |
+ // one channel (mono). |
+ // |
+ // Fairly arbitrary sample rate, except that we want the rate to be a |
+ // power of two so that 1/sampleRate is exactly respresentable as a |
+ // single-precision float. |
+ let sampleRate = 8192; |
+ |
+ // A fairly arbitrary number of frames, except the number of frames should |
+ // be more than a few render quanta. |
+ let renderFrames = 10 * 128; |
+ |
+ let audit = Audit.createTaskRunner(); |
+ |
+ // Convolver response |
+ let response; |
+ |
+ audit.define( |
+ { |
+ label: 'initialize', |
+ description: 'Convolver response with one channel' |
+ }, |
+ (task, should) => { |
+ // Convolver response |
+ should( |
+ () => { |
+ response = new AudioBuffer( |
+ {numberOfChannels: 1, length: 2, sampleRate: sampleRate}); |
+ response.getChannelData(0)[1] = 1; |
+ }, |
+ 'new AudioBuffer({numberOfChannels: 1, length: 2, sampleRate: ' + |
+ sampleRate + '})') |
+ .notThrow(); |
+ |
+ task.done(); |
+ }); |
+ |
+ audit.define( |
+ {label: '1-channel input', description: 'produces 1-channel output'}, |
+ (task, should) => { |
+ // Create a 3-channel context: channel 0 = convolver under test, |
+ // channel 1: test that convolver output is not stereo, channel 2: |
+ // expected output. The context MUST be discrete so that the |
+ // channels don't get mixed in some unexpected way. |
+ let context = new OfflineAudioContext(3, renderFrames, sampleRate); |
+ context.destination.channelInterpretation = 'discrete'; |
+ |
+ let src = new OscillatorNode(context); |
+ let conv = new ConvolverNode( |
+ context, {disableNormalization: true, buffer: response}); |
+ |
+ // Splitter node to verify that the output of the convolver is mono. |
+ // channelInterpretation must be 'discrete' so we don't do any |
+ // mixing of the input to the node. |
+ let splitter = new ChannelSplitterNode( |
+ context, |
+ {numberOfOutputs: 2, channelInterpretation: 'discrete'}); |
+ |
+ // Final merger to feed all of the individual channels into the |
+ // destination. |
+ let merger = new ChannelMergerNode(context, {numberOfInputs: 3}); |
+ |
+ src.connect(conv).connect(splitter); |
+ splitter.connect(merger, 0, 0); |
+ splitter.connect(merger, 1, 1); |
+ |
+ // The convolver response is a 1-sample delay. Use a delay node to |
+ // implement this. |
+ let delay = |
+ new DelayNode(context, {delayTime: 1 / context.sampleRate}); |
+ src.connect(delay); |
+ delay.connect(merger, 0, 2); |
+ |
+ merger.connect(context.destination); |
+ |
+ src.start(); |
+ |
+ context.startRendering() |
+ .then(audioBuffer => { |
+ // Extract out the three channels |
+ let actual = audioBuffer.getChannelData(0); |
+ let c1 = audioBuffer.getChannelData(1); |
+ let expected = audioBuffer.getChannelData(2); |
+ |
+ // c1 is expected to be zero. |
+ should(c1, '1: Channel 1').beConstantValueOf(0); |
+ |
+ // The expected and actual results should be identical |
+ should(actual, 'Convolver output').beEqualToArray(expected); |
+ }) |
+ .then(() => task.done()); |
+ }); |
+ |
+ audit.define( |
+ {label: '2-channel input', description: 'produces 2-channel output'}, |
+ (task, should) => { |
+ downMixTest({numberOfInputs: 2, prefix: '2'}, should) |
+ .then(() => task.done()); |
+ }); |
+ |
+ audit.define( |
+ { |
+ label: '3-channel input', |
+ description: '3->2 downmix producing 2-channel output' |
+ }, |
+ (task, should) => { |
+ downMixTest({numberOfInputs: 3, prefix: '3'}, should) |
+ .then(() => task.done()); |
+ }); |
+ |
+ audit.define( |
+ { |
+ label: '4-channel input', |
+ description: '4->2 downmix producing 2-channel output' |
+ }, |
+ (task, should) => { |
+ downMixTest({numberOfInputs: 4, prefix: '4'}, should) |
+ .then(() => task.done()); |
+ }); |
+ |
+ audit.define( |
+ { |
+ label: '5.1-channel input', |
+ description: '5.1->2 downmix producing 2-channel output' |
+ }, |
+ (task, should) => { |
+ downMixTest({numberOfInputs: 6, prefix: '5.1'}, should) |
+ .then(() => task.done()); |
+ }); |
+ |
+ function downMixTest(options, should) { |
+ // Create an 4-channel offline context. The first two channels are for |
+ // the stereo output of the convolver and the next two channels are for |
+ // the reference stereo signal. |
+ let context = new OfflineAudioContext(4, renderFrames, sampleRate); |
+ context.destination.channelInterpretation = 'discrete'; |
+ |
+ // Create oscillators for use as the input. The type and frequency is |
+ // arbitrary except that oscillators must be different. |
+ let src = new Array(options.numberOfInputs); |
+ for (let k = 0; k < src.length; ++k) { |
+ src[k] = new OscillatorNode( |
+ context, {type: 'square', frequency: 440 + 220 * k}); |
+ } |
+ |
+ // Merger to combine the oscillators into one output stream. |
+ let srcMerger = |
+ new ChannelMergerNode(context, {numberOfInputs: src.length}); |
+ |
+ for (let k = 0; k < src.length; ++k) { |
+ src[k].connect(srcMerger, 0, k); |
+ } |
+ |
+ // Convolver under test. |
+ let conv = new ConvolverNode( |
+ context, {disableNormalization: true, buffer: response}); |
+ srcMerger.connect(conv); |
+ |
+ // Splitter to get individual channels of the convolver output so we can |
+ // feed them (eventually) to the context in the right set of channels. |
+ let splitter = new ChannelSplitterNode(context, {numberOfOutputs: 2}); |
+ conv.connect(splitter); |
+ |
+ // Reference graph consists of a delay node to simulate the response of |
+ // the convolver. (The convolver response is designed this way.) |
+ let delay = new DelayNode(context, {delayTime: 1 / context.sampleRate}); |
+ |
+ // Gain node to mix the sources to stereo in the desired way. (Could be |
+ // done in the delay node, but let's keep the mixing separated from the |
+ // functionality.) |
+ let gainMixer = new GainNode( |
+ context, {channelCount: 2, channelCountMode: 'explicit'}); |
+ srcMerger.connect(gainMixer); |
+ |
+ // Splitter to extract the channels of the reference signal. |
+ let refSplitter = |
+ new ChannelSplitterNode(context, {numberOfOutputs: 2}); |
+ gainMixer.connect(delay).connect(refSplitter); |
+ |
+ // Final merger to bring back the individual channels from the convolver |
+ // and the reference in the right order for the destination. |
+ let finalMerger = new ChannelMergerNode( |
+ context, {numberOfInputs: context.destination.channelCount}); |
+ |
+ // First two channels are for the convolver output, and the next two are |
+ // for the reference. |
+ splitter.connect(finalMerger, 0, 0); |
+ splitter.connect(finalMerger, 1, 1); |
+ refSplitter.connect(finalMerger, 0, 2); |
+ refSplitter.connect(finalMerger, 1, 3); |
+ |
+ finalMerger.connect(context.destination); |
+ |
+ // Start the sources at last. |
+ for (let k = 0; k < src.length; ++k) { |
+ src[k].start(); |
+ } |
+ |
+ return context.startRendering().then(audioBuffer => { |
+ // Extract the various channels out |
+ let actual0 = audioBuffer.getChannelData(0); |
+ let actual1 = audioBuffer.getChannelData(1); |
+ let expected0 = audioBuffer.getChannelData(2); |
+ let expected1 = audioBuffer.getChannelData(3); |
+ |
+ // Verify that each output channel of the convolver matches |
+ // the delayed signal from the reference |
+ should(actual0, options.prefix + ': Channel 0') |
+ .beEqualToArray(expected0); |
+ should(actual1, options.prefix + ': Channel 1') |
+ .beEqualToArray(expected1); |
+ }); |
+ } |
+ |
+ audit.run(); |
+ </script> |
+ </body> |
+</html> |