Async gUM channelCount

by Alex Chronopoulos

HTML

<button id="button_default">default</button>
<button id="button_mono">mono</button>
<button id="button_stereo">stereo</button>
<button id="button_4ch">4 channels</button>
<button id="button_require_4ch">Demand 4 channels</button>

<div id="container"></div>
<div id="div"></div>

<label><input type="radio" name="apply" value="mono" id="mono" disabled>mono</label>
<label><input type="radio" name="apply" value="stereo" id="stereo" disabled>stereo</label>

<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>

CSS

canvas {
  border: 1px dashed gray;
  margin-right: 2px;
  margin-left: 2px;
}

JavaScript

let track = null;

button_default.onclick = e => start({audio: true});
button_mono.onclick = e => start({audio: {channelCount: 1}});
button_stereo.onclick = e => start({audio: {channelCount: 2}});
button_4ch.onclick = e => start({audio: {channelCount: 4}});
button_require_4ch.onclick = e => start({audio: {channelCount: {exact: 4}}});

let ac = new AudioContext();
let stream;
let src;
let splitter = ac.createChannelSplitter(2);

let left = ac.createAnalyser();
let right = ac.createAnalyser();
spectrum(ac, left);
spectrum(ac, right);

splitter.connect(left, 0);
splitter.connect(right, 1);

async function start(c) {
  close();
  try {
    stream = await navigator.mediaDevices.getUserMedia(c);
    src = ac.createMediaStreamSource(stream);
    src.connect(splitter);
    src.connect(ac.destination);
    track = stream.getAudioTracks()[0];
    update();
  } catch (e) {
    close();
    log(e);
  }
}

function close() {
  if(track) {
    track.stop();
    track = null;
  }
  stereo.disabled = mono.disabled = true;
  div.innerHTML = "";
}

function update() {
  stereo.disabled = mono.disabled = false;
  let set = track.getSettings();
  stereo.checked = set.channelCount == 2;
  mono.checked = set.channelCount == 1;
}

stereo.onclick = e => apply({channelCount: 2});
mono.onclick = e => apply({channelCount: 1});

async function apply(c) {
  await track.applyConstraints(Object.assign(track.getSettings(), c));
  update();
}

function spectrum(audioCtx, analyser) {
  var canvas = document.createElement("canvas");
  var canvasCtx = canvas.getContext("2d");
  canvas.width = window.innerWidth / 2 - 40;
  canvas.height = window.innerHeight / 1.5;
  container.appendChild(canvas);

  var data = new Uint8Array(canvas.width);
  canvasCtx.strokeStyle = 'rgb(0, 125, 0)';

  setInterval(() => {
    canvasCtx.fillStyle = "#a0a0a0";
    canvasCtx.fillRect(0, 0, canvas.width, canvas.height);

    analyser.getByteFrequencyData(data);
    canvasCtx.lineWidth = 2;
    data.forEach((y, x) => {
 ...