forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
multichannel.html
136 lines (112 loc) · 4.99 KB
/
multichannel.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
<!doctype html>
<html>
<head>
<title>Test multichannel support.</title>
<style type="text/css">
body {
margin: 2em;
}
.manual-test-ui {
font-family: Arial;
padding: 1em;
border: 1px solid #999;
}
.manual-test-ui button {
padding: 1em;
font-size: 1em;
}
</style>
</head>
<body>
<h1>Test Multichannel Audio Output</h1>
<p>Tests that multichannel audio output (> 8 channels) is working correctly.
This test cannot be run with an offline audio context because it requires
an actual audio hardware with the multichannel capability.</p>
<p>Press "Start Test Tone" to run the test. You should hear an one-second
sine tone from all the available audio output channels from the channel 1
to the last channel.</p>
<p>Note that this test only works on OSX because CoreAudio driver supports
the multichannel streams (more than 2) on a single audio device whereas
other platforms do not.</p>
<p>CRBUG issue: <a href="https://code.google.com/p/chromium/issues/detail?id=424795" target="_blank">
424795</a></p>
<div class="manual-test-ui">
<p>Max Channel Count: <span id="eMaxChannelCount">2</span></p>
<p>Currently playing: <span id="eChannelIndex">NONE</span></p>
<button id="eButton" onclick="startTestTones()">Start Test Tone</button>
</div>
<script type="text/javascript">
// Silent interval between the test tones.
var testToneInterval = 0.1;
// The safe range for the equal loudness of sinusoid is roughly between
// 200 ~ 1000Hz, which is A3(57) ~ C6(84). In this test, the starting
// pitch is 220Hz and the interval is the whole tone. (2 MIDI pitch)
// With 16 speakers, the last test tone will play the MIDI pitch of
// F6(89), which is 1396Hz.
var startMIDIPitch = 57;
var eMaxChannelCount = document.querySelector('#eMaxChannelCount');
var eButton = document.querySelector('#eButton');
var eChannelIndex = document.querySelector('#eChannelIndex');
var context = new AudioContext();
var maxChannelCount = context.destination.maxChannelCount;
// Sets the destination properties for multichannel access.
context.destination.channelCount = maxChannelCount;
context.destination.channelCountMode = 'explicit';
context.destination.channelInterpretation = 'discrete';
// The ChannelMerger for the individual channel access.
var merger = context.createChannelMerger(maxChannelCount);
merger.channelCountMode = 'explicit';
merger.channelInterpretation = 'discrete';
merger.connect(context.destination);
eMaxChannelCount.textContent = maxChannelCount;
// Convert the MIDI pitch to frequency.
function midi2freq(midiPitch) {
return 440 * Math.pow(2, (midiPitch - 69) / 12);
}
// Play a test tone for the specified amount of duration at the channel.
function playTestToneAtChannel(channelIndex, gain, duration) {
var osc = context.createOscillator();
var amp = context.createGain();
osc.connect(amp);
amp.connect(merger, 0, channelIndex);
osc.onended = function () {
var nextChannelIndex = channelIndex + 1;
if (nextChannelIndex < maxChannelCount)
playTestToneAtChannel(nextChannelIndex, gain, duration);
else
endTestTone();
};
// The pitch for each speaker goes up as the channel index increases.
// Note that the interval is 2, whole tone.
osc.frequency.value = midi2freq(startMIDIPitch + channelIndex * 2);
// The channel index starts from 1.
eChannelIndex.textContent = 'Channel #' + (channelIndex + 1);
var now = context.currentTime;
var toneDuration = duration - testToneInterval;
// Add fade in and out to avoid the click noise.
amp.gain.setValueAtTime(0.0, now);
amp.gain.linearRampToValueAtTime(gain, now + toneDuration * 0.1);
amp.gain.setValueAtTime(gain, now + toneDuration * 0.9);
amp.gain.linearRampToValueAtTime(0.0, now + toneDuration);
osc.start(now);
osc.stop(now + duration);
}
// When the button is clicked the button to produce the test sound,
// the button is grayed out so one cannot press again until the tone is
// over. (producing sounds multiple times in a short period time will
// hurt the speaker).
function startTestTones() {
eButton.disabled = true;
// Math.SQRT1_2(=0.707..) is -3dB. This is necessary because 1.0
// amplitude can cause overload/distortion on some speakers.
playTestToneAtChannel(0, Math.SQRT1_2, 1.0);
}
// The button needs to be active back again when the test tone is over.
// The index number in DIV should also be reset.
function endTestTone() {
eButton.disabled = false;
eChannelIndex.textContent = 'NONE';
}
</script>
</body>
</html>