Listen to your Web Pages

Always notice how in sci-fi movies the computers make those weird bleepy sounds?

Tom Hicks has created a JavaScript snippet that combines MutationObserver with AudioContext to recreate that effect.

Copy this into the console of any web page that is interactive and doesn’t do hard reloads. You will hear your DOM changes as different pitches of audio.


const audioCtx = new (window.AudioContext || window.webkitAudioContext)()
const observer = new MutationObserver(function(mutationsList) {
  const oscillator = audioCtx.createOscillator()

  oscillator.connect(audioCtx.destination)
  oscillator.type = "sine"
  oscillator.frequency.setValueAtTime(
    Math.log(mutationsList.length + 5) * 880,
    audioCtx.currentTime,
  )

  oscillator.start()
  oscillator.stop(audioCtx.currentTime + 0.01)
})

observer.observe(document, {
  attributes: true,
  childList: true,
  subtree: true,
  characterData: true,
})

Try it on Facebook for example. It beeps all over the place πŸ˜†

There’s also an alternate version that mimics the effect as heard on TV better:


const audioCtx = new window.AudioContext();
const oscillator = audioCtx.createOscillator();
oscillator.connect(audioCtx.destination);
oscillator.type = "sine";

let numItems = 0

oscillator.frequency.setValueAtTime(
  1,
  audioCtx.currentTime
);

oscillator.start();

const observer = new MutationObserver(function (mutationsList) {
  numItems += mutationsList.length

  oscillator.frequency.setValueAtTime(
    Math.log(numItems + 1) * 440,
    audioCtx.currentTime
  );

  setTimeout(() => {
    numItems -= mutationsList.length
    if (numItems === 0) {
      oscillator.frequency.setValueAtTime(
          1,
          audioCtx.currentTime
        )
    } else {
        oscillator.frequency.setValueAtTime(
          Math.log(numItems + 1) * 440,
          audioCtx.currentTime
        )
    }
  }, 100)
});

observer.observe(document, {
  attributes: true,
  childList: true,
  subtree: true,
  characterData: true
});

There’s also a browser extension available, but be warned: there’s no off switch (you’ll have to remove it to disable it)

Feeding the Audio Graph – Using Web Audio’s AnalyserNode

Good article on 24ways (yes, that still is a thing) on using Web Audio’s AnalyserNode.

const waveform = new Uint8Array(analyser.fftSize);
const frequencies = new Uint8Array(analyser.frequencyBinCount);
const ctx = canvas.getContext('2d');

const loop = () => {
    requestAnimationFrame(loop);
    analyser.getByteTimeDomainData(waveform);
    analyser.getByteFrequencyData(frequencies);

    ctx.beginPath();
    waveform.forEach((f, i) => ctx.lineTo(i, f));
    ctx.lineTo(0,255);
    frequencies.forEach((f, i) => ctx.lineTo(i, 255-f));
    ctx.stroke();
}

loop();

I especially like the demo where the emoji are animated based on the frequency.

Feeding the Audio Graph →

audio-effects – Create Audio Effects Using the Web Audio API

Great stuff by Sam Bellen, in which me mimics the effect-pedals for guitars:

Audio-effects is a JavaScript library to create audio effects using the Web Audio API. This library contains the Volume, Distortion, Delay, Flanger, Reverb, and Tremolo effects

He recently gave a talk about this at JSConf Budapest 2016 and at a local Fronteers Meetup:

audio-effects (GitHub) →

Sidenote: To play audio in browsers I’m still a huge fan of Howler.

Lightyear.fm – A journey through space, time, and music

lightyearfm

Radio broadcasts leave Earth at the speed of light and travel outwards into space. Follow them through the Milky Way as you scroll backwards through time and listen to what the stars hear.

Built using Three.js. Taking a look at the source code reveals all tracks used.

And oh, don’t forget the β€œInverse Square Law of Propagation”:

Although Lightyear.fm has radiowaves reaching over 100 lightyears into space, due to the Inverse Square Law of Propagation, any terrestrial radio broadcast would become nothing but background noise just a few light years away from Earth.

Lightyear.fm →

Realtime Audio-Visualizations with JavaScript

window.onload = function() {
  var ctx = new AudioContext();
  var audio = document.getElementById('myAudio');
  var audioSrc = ctx.createMediaElementSource(audio);
  var analyser = ctx.createAnalyser();
  // we have to connect the MediaElementSource with the analyser 
  audioSrc.connect(analyser);
  // we could configure the analyser: e.g. analyser.fftSize (for further infos read the spec)
 
  // frequencyBinCount tells you how many values you'll receive from the analyser
  var frequencyData = new Uint8Array(analyser.frequencyBinCount);
 
  // we're ready to receive some data!
  // loop
  function renderFrame() {
     requestAnimationFrame(renderFrame);
     // update data in frequencyData
     analyser.getByteFrequencyData(frequencyData);
     // render frame based on values in frequencyData
     // console.log(frequencyData)
  }
  audio.start();
  renderFrame();
};

Web Audio API + Canvas + Some math. I would have chosen a different track though πŸ˜‰

How to create Audio-Visualizations with JavaScript & HTML →
Realtime Audio-Visualizations (Demo) →