Aphiwad Chhoeun

Creating Audio Visualizer

Audio Visualization with Web Audio API

Creating an audio visualizer on the web sounds fun, so I tried to dive into it on my weekend. After some reading and testing, here’s a short summary of what I’ve learnt:

How digital audio works (in a very short summary)

In the real world, sound is a wave form, lots lots of this wave form constantly broadcasted. So in order to store these data, computer converts them into digital data by a process called “sampling”; and fetching them back one-fraction of a second at a time to reverse the process whenever you play a sound on your computer.

And that’s where we want to step in and analyses those data, then render a visualizer bars or wave line.

Concept of the demo

Thanks to the Web Audio API, they have made it very easy to read audio data.

The concept for my demo is very simple, I play back an audio file, then for every tiny-bit of second, I read the frequency data and render them into a visual presentation. I’m using DOM <div> elements to do that.

Setting up

HTML markups:

<div id="app">
  <div id="visual"></div>
  <div class="controls">
    <button id="btn__play" class="button">Play</button>
    <button id="btn__pause" class="button">Pause</button>
  </div>
</div>

First, let’s create an audio element:

let audio = document.createElement('audio')
audio.src = 'audiofile.mp3'

To extract audio frequency data, you need AnalyserNode, you can create it by AudioContext.createAnalyser()

let audioCtx = new (window.AudioContext || window.webkitAudioContext)()
let analyser = audioCtx.createAnalyser()

Then create an audio source to work with, and connect them into the analyser:

let source = this.audioCtx.createMediaElementSource(audio)
source.connect(analyser)

/**
 * you can use soure or analyser to connect to `audioCtx.destination`,
 * otherwise the audio will plays, but you won't hear it.
 */
analyser.connect(audioCtx.destination)

Start extracting and analysing frequency data

To start extracting audio data, I use analyser.getByteFrequencyData() , this method copies frequency data into a specified array that you pass as a parameter. The array produced need to be an Uint8Array type. I also set analyser.fftSize to 256, this is to indicate how granular details of data you want to work with; for normal audio anything more details than this you can’t detect it with your ears anyway. (more about FFT)

analyser.fftSize = 256;
let bufferLength = analyser.frequencyBinCount;
let dataArray = new Uint8Array(bufferLength);

...

// inside a loop because you want to constantly fetching & analysing the data,
// and render it into visual presentation
analyser.getByteFrequencyData(dataArray);

// do rendering task here using `dataArray`

Rendering visualizer

And there you go, you have dataArray that contains the frequency data for that split of second, each element inside the array has value ranging from 0 - 255. (more about Frequency Data)

You can generate a collection of DOM elements and set each of their height based on element in the array, then you will have a bars visualizer.

I decided to combine the the liquid effect with SVG with this practice. The result is quite interesting, you can check out the demo here!

References: