Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / ManualTests / webaudio / multichannel.html
blobd5958520c2f0f8d65fea74e05c0e5347a6122a53
1 <!doctype html>
2 <html>
3 <head>
4 <title>Test multichannel support.</title>
5 <style type="text/css">
6 body {
7 margin: 2em;
9 .manual-test-ui {
10 font-family: Arial;
11 padding: 1em;
12 border: 1px solid #999;
14 .manual-test-ui button {
15 padding: 1em;
16 font-size: 1em;
18 </style>
19 </head>
21 <body>
22 <h1>Test Multichannel Audio Output</h1>
24 <p>Tests that multichannel audio output (> 8 channels) is working correctly.
25 This test cannot be run with an offline audio context because it requires
26 an actual audio hardware with the multichannel capability.</p>
28 <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
30 to the last channel.</p>
32 <p>Note that this test only works on OSX because CoreAudio driver supports
33 the multichannel streams (more than 2) on a single audio device whereas
34 other platforms do not.</p>
36 <p>CRBUG issue: <a href="https://code.google.com/p/chromium/issues/detail?id=424795" target="_blank">
37 424795</a></p>
39 <div class="manual-test-ui">
40 <p>Max Channel Count: <span id="eMaxChannelCount">2</span></p>
41 <p>Currently playing: <span id="eChannelIndex">NONE</span></p>
42 <button id="eButton" onclick="startTestTones()">Start Test Tone</button>
43 </div>
45 <script type="text/javascript">
46 // Silent interval between the test tones.
47 var testToneInterval = 0.1;
49 // 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
51 // 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
53 // F6(89), which is 1396Hz.
54 var startMIDIPitch = 57;
56 var eMaxChannelCount = document.querySelector('#eMaxChannelCount');
57 var eButton = document.querySelector('#eButton');
58 var eChannelIndex = document.querySelector('#eChannelIndex');
60 var context = new AudioContext();
61 var maxChannelCount = context.destination.maxChannelCount;
63 // Sets the destination properties for multichannel access.
64 context.destination.channelCount = maxChannelCount;
65 context.destination.channelCountMode = 'explicit';
66 context.destination.channelInterpretation = 'discrete';
68 // The ChannelMerger for the individual channel access.
69 var merger = context.createChannelMerger(maxChannelCount);
70 merger.channelCountMode = 'explicit';
71 merger.channelInterpretation = 'discrete';
72 merger.connect(context.destination);
74 eMaxChannelCount.textContent = maxChannelCount;
76 // Convert the MIDI pitch to frequency.
77 function midi2freq(midiPitch) {
78 return 440 * Math.pow(2, (midiPitch - 69) / 12);
81 // Play a test tone for the specified amount of duration at the channel.
82 function playTestToneAtChannel(channelIndex, gain, duration) {
83 var osc = context.createOscillator();
84 var amp = context.createGain();
85 osc.connect(amp);
86 amp.connect(merger, 0, channelIndex);
88 osc.onended = function () {
89 var nextChannelIndex = channelIndex + 1;
90 if (nextChannelIndex < maxChannelCount)
91 playTestToneAtChannel(nextChannelIndex, gain, duration);
92 else
93 endTestTone();
96 // The pitch for each speaker goes up as the channel index increases.
97 // Note that the interval is 2, whole tone.
98 osc.frequency.value = midi2freq(startMIDIPitch + channelIndex * 2);
100 // The channel index starts from 1.
101 eChannelIndex.textContent = 'Channel #' + (channelIndex + 1);
103 var now = context.currentTime;
104 var toneDuration = duration - testToneInterval;
106 // Add fade in and out to avoid the click noise.
107 amp.gain.setValueAtTime(0.0, now);
108 amp.gain.linearRampToValueAtTime(gain, now + toneDuration * 0.1);
109 amp.gain.setValueAtTime(gain, now + toneDuration * 0.9);
110 amp.gain.linearRampToValueAtTime(0.0, now + toneDuration);
112 osc.start(now);
113 osc.stop(now + duration);
116 // 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
118 // over. (producing sounds multiple times in a short period time will
119 // hurt the speaker).
120 function startTestTones() {
121 eButton.disabled = true;
123 // Math.SQRT1_2(=0.707..) is -3dB. This is necessary because 1.0
124 // amplitude can cause overload/distortion on some speakers.
125 playTestToneAtChannel(0, Math.SQRT1_2, 1.0);
128 // The button needs to be active back again when the test tone is over.
129 // The index number in DIV should also be reset.
130 function endTestTone() {
131 eButton.disabled = false;
132 eChannelIndex.textContent = 'NONE';
134 </script>
135 </body>
136 </html>