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 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
<!doctype html>
<html>
<head>
<title>Test multichannel support for MediaStreamDestination.</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;
}
#eError {
font-family: Arial;
margin: 0.75em;
color: red;
}
</style>
</head>
<body>
<h1>Test Multichannel Audio Output for MediaStreamDestination</h1>
<p><strong>NOTE: This test requires HTTP server.</strong></p>
<p>This test is for multichannel (> 2 channels) support for
MediaStreamDestination. This test cannot be run with an offline audio
context because the node is not compatible with the offline context.</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>CRBUG issue: <a href="https://code.google.com/p/chromium/issues/detail?id=557185" target="_blank">
557185</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>
<div id="eError"></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 eError = document.querySelector('#eError');
var context = new AudioContext();
var mediaStreamDestination = context.createMediaStreamDestination();
var maxChannelCount = context.destination.maxChannelCount;
try {
mediaStreamDestination.channelCount = maxChannelCount;
} catch (error) {
eError.textContent = error;
}
var audioElement = new Audio();
audioElement.src = URL.createObjectURL(mediaStreamDestination.stream);
audioElement.play();
// The ChannelMerger for the individual channel access.
var merger = context.createChannelMerger(maxChannelCount);
merger.channelCountMode = 'explicit';
merger.channelInterpretation = 'discrete';
merger.connect(mediaStreamDestination);
eMaxChannelCount.textContent = maxChannelCount;
// Convert the MIDI pitch to frequency.
function midi2freq(midiPitch) {
return 440 * Math.pow(2, (midiPitch - 69) / 12);
}
// A global storage to keep the OSC reference alive.
var oscs = [];
// 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);
// Push osc to keep the reference alive. Otherwise |osc| will be
// collected and the |onended| event won't be fired.
oscs.push(osc);
}
// 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>
|