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

Side by Side Diff: third_party/WebKit/ManualTests/webaudio/multichannel-mediastreamdestination.html

Issue 1464673002: Support multichannel audio stream more than 2 in MediaStreamDestinationNode (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added tests Created 5 years, 1 month 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
1 <!doctype html> 1 <!doctype html>
2 <html> 2 <html>
3 <head> 3 <head>
4 <title>Test multichannel support.</title> 4 <title>Test multichannel support for MediaStreamDestination.</title>
5 <style type="text/css"> 5 <style type="text/css">
6 body { 6 body {
7 margin: 2em; 7 margin: 2em;
8 } 8 }
9 .manual-test-ui { 9 .manual-test-ui {
10 font-family: Arial; 10 font-family: Arial;
11 padding: 1em; 11 padding: 1em;
12 border: 1px solid #999; 12 border: 1px solid #999;
13 } 13 }
14 .manual-test-ui button { 14 .manual-test-ui button {
15 padding: 1em; 15 padding: 1em;
16 font-size: 1em; 16 font-size: 1em;
17 } 17 }
18 </style> 18 </style>
19 </head> 19 </head>
20 20
21 <body> 21 <body>
22 <h1>Test Multichannel Audio Output</h1> 22 <h1>Test Multichannel Audio Output for MediaStreamDestination</h1>
23 23
24 <p>Tests that multichannel audio output (> 8 channels) is working correctly. 24 <p><strong>NOTE: This test requires HTTP server.</strong></p>
25 This test cannot be run with an offline audio context because it requires 25
26 an actual audio hardware with the multichannel capability.</p> 26 <p>This test is for multichannel (> 2 channels) support for
Raymond Toy 2015/11/20 14:47:18 Do you need to change ">" to "&gt;"?
hongchan 2015/11/20 18:02:59 Although the DOM parser is smart enough to do this
27 MediaStreamDestination. This test cannot be run with an offline audio
28 context because the node is not compatible with the offline context.</p>
27 29
28 <p>Press "Start Test Tone" to run the test. You should hear an one-second 30 <p>Press "Start Test Tone" to run the test. You should hear an one-second
29 sine tone from all the available audio output channels from the channel 1 31 sine tone from all the available audio output channels from the channel 1
30 to the last channel.</p> 32 to the last channel.</p>
31 33
32 <p>Note that this test only works on OSX because CoreAudio driver supports 34 <p>CRBUG issue: <a href="https://code.google.com/p/chromium/issues/detail?id =557185" target="_blank">
33 the multichannel streams (more than 2) on a single audio device whereas 35 557185</a></p>
34 other platforms do not.</p>
35
36 <p>CRBUG issue: <a href="https://code.google.com/p/chromium/issues/detail?id =424795" target="_blank">
37 424795</a></p>
38 36
39 <div class="manual-test-ui"> 37 <div class="manual-test-ui">
40 <p>Max Channel Count: <span id="eMaxChannelCount">2</span></p> 38 <p>Max Channel Count: <span id="eMaxChannelCount">2</span></p>
41 <p>Currently playing: <span id="eChannelIndex">NONE</span></p> 39 <p>Currently playing: <span id="eChannelIndex">NONE</span></p>
42 <button id="eButton" onclick="startTestTones()">Start Test Tone</button> 40 <button id="eButton" onclick="startTestTones()">Start Test Tone</button>
43 </div> 41 </div>
44 42
45 <script type="text/javascript"> 43 <script type="text/javascript">
46 // Silent interval between the test tones. 44 // Silent interval between the test tones.
47 var testToneInterval = 0.1; 45 var testToneInterval = 0.1;
48 46
49 // The safe range for the equal loudness of sinusoid is roughly between 47 // The safe range for the equal loudness of sinusoid is roughly between
50 // 200 ~ 1000Hz, which is A3(57) ~ C6(84). In this test, the starting 48 // 200 ~ 1000Hz, which is A3(57) ~ C6(84). In this test, the starting
51 // pitch is 220Hz and the interval is the whole tone. (2 MIDI pitch) 49 // pitch is 220Hz and the interval is the whole tone. (2 MIDI pitch)
52 // With 16 speakers, the last test tone will play the MIDI pitch of 50 // With 16 speakers, the last test tone will play the MIDI pitch of
53 // F6(89), which is 1396Hz. 51 // F6(89), which is 1396Hz.
54 var startMIDIPitch = 57; 52 var startMIDIPitch = 57;
55 53
56 var eMaxChannelCount = document.querySelector('#eMaxChannelCount'); 54 var eMaxChannelCount = document.querySelector('#eMaxChannelCount');
57 var eButton = document.querySelector('#eButton'); 55 var eButton = document.querySelector('#eButton');
58 var eChannelIndex = document.querySelector('#eChannelIndex'); 56 var eChannelIndex = document.querySelector('#eChannelIndex');
59 57
60 var context = new AudioContext(); 58 var context = new AudioContext();
59 var mediaStreamDestination = context.createMediaStreamDestination();
60
61 var maxChannelCount = context.destination.maxChannelCount; 61 var maxChannelCount = context.destination.maxChannelCount;
62 62
63 // Sets the destination properties for multichannel access. 63 // The maximum channel count of MediaStreamDestination is 8.
64 context.destination.channelCount = maxChannelCount; 64 mediaStreamDestination.channelCount =
65 context.destination.channelCountMode = 'explicit'; 65 maxChannelCount < 8 ? maxChannelCount : 8;
Raymond Toy 2015/11/20 14:47:18 I think this code would be more robust if you adde
hongchan 2015/11/20 18:02:59 Done.
66 context.destination.channelInterpretation = 'discrete'; 66
67 var audioElement = new Audio();
68 audioElement.src = URL.createObjectURL(mediaStreamDestination.stream);
69 audioElement.play();
67 70
68 // The ChannelMerger for the individual channel access. 71 // The ChannelMerger for the individual channel access.
69 var merger = context.createChannelMerger(maxChannelCount); 72 var merger = context.createChannelMerger(maxChannelCount);
70 merger.channelCountMode = 'explicit'; 73 merger.channelCountMode = 'explicit';
71 merger.channelInterpretation = 'discrete'; 74 merger.channelInterpretation = 'discrete';
72 merger.connect(context.destination); 75 merger.connect(mediaStreamDestination);
73 76
74 eMaxChannelCount.textContent = maxChannelCount; 77 eMaxChannelCount.textContent = maxChannelCount;
75 78
76 // Convert the MIDI pitch to frequency. 79 // Convert the MIDI pitch to frequency.
77 function midi2freq(midiPitch) { 80 function midi2freq(midiPitch) {
78 return 440 * Math.pow(2, (midiPitch - 69) / 12); 81 return 440 * Math.pow(2, (midiPitch - 69) / 12);
79 } 82 }
80 83
84 // A global storage to keep the OSC reference alive.
85 var oscs = [];
86
81 // Play a test tone for the specified amount of duration at the channel. 87 // Play a test tone for the specified amount of duration at the channel.
82 function playTestToneAtChannel(channelIndex, gain, duration) { 88 function playTestToneAtChannel(channelIndex, gain, duration) {
83 var osc = context.createOscillator(); 89 var osc = context.createOscillator();
84 var amp = context.createGain(); 90 var amp = context.createGain();
85 osc.connect(amp); 91 osc.connect(amp);
86 amp.connect(merger, 0, channelIndex); 92 amp.connect(merger, 0, channelIndex);
87 93
88 osc.onended = function () { 94 osc.onended = function () {
89 var nextChannelIndex = channelIndex + 1; 95 var nextChannelIndex = channelIndex + 1;
90 if (nextChannelIndex < maxChannelCount) 96 if (nextChannelIndex < maxChannelCount)
91 playTestToneAtChannel(nextChannelIndex, gain, duration); 97 playTestToneAtChannel(nextChannelIndex, gain, duration);
92 else 98 else
93 endTestTone(); 99 endTestTone();
94 }; 100 };
95 101
96 // The pitch for each speaker goes up as the channel index increases. 102 // The pitch for each speaker goes up as the channel index increases.
97 // Note that the interval is 2, whole tone. 103 // Note that the interval is 2, whole tone.
98 osc.frequency.value = midi2freq(startMIDIPitch + channelIndex * 2); 104 osc.frequency.value = midi2freq(startMIDIPitch + channelIndex * 2);
99 105
100 // The channel index starts from 1. 106 // The channel index starts from 1.
101 eChannelIndex.textContent = 'Channel #' + (channelIndex + 1); 107 eChannelIndex.textContent = 'Channel #' + (channelIndex + 1);
102 108
103 var now = context.currentTime; 109 var now = context.currentTime;
104 var toneDuration = duration - testToneInterval; 110 var toneDuration = duration - testToneInterval;
105 111
106 // Add fade in and out to avoid the click noise. 112 // Add fade in and out to avoid the click noise.
107 amp.gain.setValueAtTime(0.0, now); 113 amp.gain.setValueAtTime(0.0, now);
108 amp.gain.linearRampToValueAtTime(gain, now + toneDuration * 0.1); 114 amp.gain.linearRampToValueAtTime(gain, now + toneDuration * 0.1);
109 amp.gain.setValueAtTime(gain, now + toneDuration * 0.9); 115 amp.gain.setValueAtTime(gain, now + toneDuration * 0.9);
110 amp.gain.linearRampToValueAtTime(0.0, now + toneDuration); 116 amp.gain.linearRampToValueAtTime(0.0, now + toneDuration);
111 117
112 osc.start(now); 118 osc.start(now);
113 osc.stop(now + duration); 119 osc.stop(now + duration);
120
121 // Push osc to keep the reference alive. Otherwise |osc| will be
122 // collected and the |onended| event won't be fired.
Raymond Toy 2015/11/20 14:47:18 File a bug on this, and put a link to the bug here
hongchan 2015/11/20 18:02:59 Done. https://code.google.com/p/chromium/issues/d
Raymond Toy 2015/11/30 18:06:09 Add link to this bug in the comments.
hongchan 2015/11/30 18:10:43 This bug is not directly related to this CL, so I
123 oscs.push(osc);
114 } 124 }
115 125
116 // When the button is clicked the button to produce the test sound, 126 // When the button is clicked the button to produce the test sound,
117 // the button is grayed out so one cannot press again until the tone is 127 // the button is grayed out so one cannot press again until the tone is
118 // over. (producing sounds multiple times in a short period time will 128 // over. (producing sounds multiple times in a short period time will
119 // hurt the speaker). 129 // hurt the speaker).
120 function startTestTones() { 130 function startTestTones() {
121 eButton.disabled = true; 131 eButton.disabled = true;
122 132
123 // Math.SQRT1_2(=0.707..) is -3dB. This is necessary because 1.0 133 // Math.SQRT1_2(=0.707..) is -3dB. This is necessary because 1.0
124 // amplitude can cause overload/distortion on some speakers. 134 // amplitude can cause overload/distortion on some speakers.
125 playTestToneAtChannel(0, Math.SQRT1_2, 1.0); 135 playTestToneAtChannel(0, Math.SQRT1_2, 1.0);
126 } 136 }
127 137
128 // The button needs to be active back again when the test tone is over. 138 // The button needs to be active back again when the test tone is over.
129 // The index number in DIV should also be reset. 139 // The index number in DIV should also be reset.
130 function endTestTone() { 140 function endTestTone() {
131 eButton.disabled = false; 141 eButton.disabled = false;
132 eChannelIndex.textContent = 'NONE'; 142 eChannelIndex.textContent = 'NONE';
133 } 143 }
134 </script> 144 </script>
135 </body> 145 </body>
136 </html> 146 </html>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698