Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(13)

Side by Side Diff: third_party/WebKit/LayoutTests/webaudio/Convolver/convolver-response-4-chan.html

Issue 2732523003: Make ConvolverNode conform to spec (Closed)
Patch Set: Revert unneeded AudioNode.h change Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 <!doctype html>
2 <html>
3 <head>
4 <title>Test Convolver Channel Outputs for Response with 4 channels</title>
5 <script src="../../resources/testharness.js"></script>
6 <script src="../../resources/testharnessreport.js"></script>
7 <script src="../resources/audit-util.js"></script>
8 <script src="../resources/audit.js"></script>
9 </head>
10
11 <body>
12 <script>
13 // Test various convolver configurations when the convolver response has
14 // a four channels.
15 //
hongchan 2017/03/28 16:44:35 Ditto. Remove the comment tag.
16 // Fairly arbitrary sample rate, except that we want the rate to be a
17 // power of two so that 1/sampleRate is exactly respresentable as a
18 // single-precision float.
19 let sampleRate = 8192;
20
21 // A fairly arbitrary number of frames, except the number of frames should
22 // be more than a few render quanta.
23 let renderFrames = 10 * 128;
24
25 let audit = Audit.createTaskRunner();
26
27 // Convolver response
28 let response;
29
30 audit.define(
31 {
32 label: 'initialize',
33 description: 'Convolver response with one channel'
34 },
35 (task, should) => {
36 // Convolver response
37 should(
38 () => {
39 response = new AudioBuffer(
40 {numberOfChannels: 4, length: 8, sampleRate: sampleRate});
41 // Each channel of the response is a simple impulse (with
42 // different delay) so that we can use a DelayNode to simulate
43 // the convolver output. Channel k is delayed by k+1 frames.
44 for (let k = 0; k < response.numberOfChannels; ++k) {
45 response.getChannelData(k)[k + 1] = 1;
46 }
47 },
48 'new AudioBuffer({numberOfChannels: 2, length: 4, sampleRate: ' +
49 sampleRate + '})')
50 .notThrow();
51
52 task.done();
53 });
54
55 audit.define(
56 {label: '1-channel input', description: 'produces 2-channel output'},
57 (task, should) => {
58 fourChannelResponseTest({numberOfInputs: 1, prefix: '1'}, should)
59 .then(() => task.done());
60 });
61
62 audit.define(
63 {label: '2-channel input', description: 'produces 2-channel output'},
64 (task, should) => {
65 fourChannelResponseTest({numberOfInputs: 2, prefix: '2'}, should)
66 .then(() => task.done());
67 });
68
69 audit.define(
70 {
71 label: '3-channel input',
72 description: '3->2 downmix producing 2-channel output'
73 },
74 (task, should) => {
75 fourChannelResponseTest({numberOfInputs: 3, prefix: '3'}, should)
76 .then(() => task.done());
77 });
78
79 audit.define(
80 {
81 label: '4-channel input',
82 description: '4->2 downmix producing 2-channel output'
83 },
84 (task, should) => {
85 fourChannelResponseTest({numberOfInputs: 4, prefix: '4'}, should)
86 .then(() => task.done());
87 });
88
89 audit.define(
90 {
91 label: '5.1-channel input',
92 description: '5.1->2 downmix producing 2-channel output'
93 },
94 (task, should) => {
95 fourChannelResponseTest({numberOfInputs: 6, prefix: '5.1'}, should)
96 .then(() => task.done());
97 });
98
99 function fourChannelResponseTest(options, should) {
100 // Create an 4-channel offline context. The first two channels are for
101 // the stereo output of the convolver and the next two channels are for
102 // the reference stereo signal.
103 let context = new OfflineAudioContext(4, renderFrames, sampleRate);
104 context.destination.channelInterpretation = 'discrete';
105
106 // Create oscillators for use as the input. The type and frequency is
107 // arbitrary except that oscillators must be different.
108 let src = new Array(options.numberOfInputs);
109 for (let k = 0; k < src.length; ++k) {
110 src[k] = new OscillatorNode(
111 context, {type: 'square', frequency: 440 + 220 * k});
112 }
113
114 // Merger to combine the oscillators into one output stream.
115 let srcMerger =
116 new ChannelMergerNode(context, {numberOfInputs: src.length});
117
118 for (let k = 0; k < src.length; ++k) {
119 src[k].connect(srcMerger, 0, k);
120 }
121
122 // Convolver under test.
123 let conv = new ConvolverNode(
124 context, {disableNormalization: true, buffer: response});
125 srcMerger.connect(conv);
126
127 // Splitter to get individual channels of the convolver output so we can
128 // feed them (eventually) to the context in the right set of channels.
129 let splitter = new ChannelSplitterNode(context, {numberOfOutputs: 2});
130 conv.connect(splitter);
131
132 // Reference graph consists of a delays node to simulate the response of
133 // the convolver. (The convolver response is designed this way.)
134 let delay = new Array(4);
135 for (let k = 0; k < delay.length; ++k) {
136 delay[k] = new DelayNode(context, {
137 delayTime: (k + 1) / context.sampleRate,
138 channelCount: 1,
139 channelCountMode: 'explicit'
140 });
141 }
142
143
hongchan 2017/03/28 16:44:35 Ditto. Two blank lines.
144 // Gain node to mix the sources to stereo in the desired way. (Could be
145 // done in the delay node, but let's keep the mixing separated from the
146 // functionality.)
147 let gainMixer = new GainNode(
148 context, {channelCount: 2, channelCountMode: 'explicit'});
149 srcMerger.connect(gainMixer);
150
151 // Splitter to extract the channels of the reference signal.
152 let refSplitter =
153 new ChannelSplitterNode(context, {numberOfOutputs: 2});
154 gainMixer.connect(refSplitter);
155
156 // Connect the left channel to the first two nodes and the right channel
157 // to the second two as required for "true" stereo matrix response.
158 for (let k = 0; k < 2; ++k) {
159 refSplitter.connect(delay[k], 0, 0);
160 refSplitter.connect(delay[k + 2], 1, 0);
161 }
162
163 // Gain nodes to sum the responses to stereo
164 let gain = new Array(2);
165 for (let k = 0; k < gain.length; ++k) {
166 gain[k] = new GainNode(context, {
167 channelCount: 1,
168 channelCountMode: 'explicit',
169 channelInterpretation: 'discrete'
170 });
171 }
172
173 delay[0].connect(gain[0]);
174 delay[2].connect(gain[0]);
175 delay[1].connect(gain[1]);
176 delay[3].connect(gain[1]);
177
178 // Final merger to bring back the individual channels from the convolver
179 // and the reference in the right order for the destination.
180 let finalMerger = new ChannelMergerNode(
181 context, {numberOfInputs: context.destination.channelCount});
182
183 // First two channels are for the convolver output, and the next two are
184 // for the reference.
185 splitter.connect(finalMerger, 0, 0);
186 splitter.connect(finalMerger, 1, 1);
187 gain[0].connect(finalMerger, 0, 2);
188 gain[1].connect(finalMerger, 0, 3);
189
190 finalMerger.connect(context.destination);
191
192 // Start the sources at last.
193 for (let k = 0; k < src.length; ++k) {
194 src[k].start();
195 }
196
197 return context.startRendering().then(audioBuffer => {
198 // Extract the various channels out
199 let actual0 = audioBuffer.getChannelData(0);
200 let actual1 = audioBuffer.getChannelData(1);
201 let expected0 = audioBuffer.getChannelData(2);
202 let expected1 = audioBuffer.getChannelData(3);
203
204 // Verify that each output channel of the convolver matches
205 // the delayed signal from the reference
206 should(actual0, options.prefix + ': Channel 0')
207 .beEqualToArray(expected0);
208 should(actual1, options.prefix + ': Channel 1')
209 .beEqualToArray(expected1);
210 });
211 }
212
213 audit.run();
214 </script>
215 </body>
216 </html>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698