4 <title>Test multichannel support.
</title>
5 <style type=
"text/css">
12 border: 1px solid
#999;
14 .manual-test-ui button {
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">
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>
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();
86 amp
.connect(merger
, 0, channelIndex
);
88 osc
.onended = function () {
89 var nextChannelIndex
= channelIndex
+ 1;
90 if (nextChannelIndex
< maxChannelCount
)
91 playTestToneAtChannel(nextChannelIndex
, gain
, duration
);
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
);
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';