| 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>
|
|
|