2D real time visualization: waveforms

2D real time visualization: waveforms

 Bookmark this page

Live video coding: animating a waveform

0:00 / 6:50

Click on this button to mute or unmute this video or press UP or DOWN buttons to increase or decrease volume level.

Maximum Volume.

Downloads and transcripts

2D real time visualizations: waveforms

Introduction

WebAudio offers an Analyser node that provides real-time frequency and time-domain analysis information. It leaves the audio stream unchanged from the input to the output, but allows us to acquire data about the sound signal being played. This data is easy for us to process since complex computations such as Fast Fourier Transforms are being executed, behind the scenes,.

Example 1: audio player with waveform visualization

Example at JSBin

Audio player with waveform visualization

Do things in order – Select the audio context AND the canvas context, build the audio graph, and run the animation loop

Typical operations to perform once the HTML page is loaded:

  1. window.onload = function() {
  2.    // get the audio context
  3.    audioContext= ;
  4.    // get the canvas, its graphic context…
  5.    canvas = document.querySelector(“#myCanvas”);
  6.    width = canvas.width;
  7.    height = canvas.height;
  8.    canvasContext = canvas.getContext(‘2d’);
  9.    // Build the audio graph with an analyser node at the end
  10.    buildAudioGraph();
  11.    // starts the animation at 60 frames/s
  12.    requestAnimationFrame(visualize);
  13. };

Step 1 – build the audio graph with an analyser node at the end

If we want to visualize the sound that is coming out of the speakers, we have to put an analyser node at almost the end of the sound graph. Example 1 shows a typical use: an <audio> element, a MediaElementElementSource node connected to an Analyser node, and the analyser node connected to the speakers (audioContext.destination). The visualization is a graphic animation that uses the requestAnimationFrame API presented in HTML5 part 1, Week 4.

Typical code for building the audio graph:

HTML code:

  1. <audio src=http://mainline.i3s.unice.fr/mooc/guitarRiff1.mp3&#8221;
  2.     id=“player” controls loop crossorigin=“anonymous”>
  3. </audio>
  4. <canvas id=“myCanvas” width=300 height=100></canvas>

JavaScript code:

  1. function buildAudioGraph() {
  2.    var mediaElement = document.getElementById(‘player’);
  3.    var sourceNode = audioContext.createMediaElementSource(mediaElement);
  4.    // Create an analyser node
  5.    analyser = audioContext.createAnalyser();
  6.    // set visualizer options, for lower precision change 1024 to 512,
  7.    // 256, 128, 64 etc. bufferLength will be equal to fftSize/2
  8.    analyser.fftSize = 1024;
  9.    bufferLength = analyser.frequencyBinCount;
  10.    dataArray = new Uint8Array(bufferLength);
  11.    sourceNode.connect(analyser);
  12.    analyser.connect(audioContext.destination);
  13. }

With the exception of lines 8-12, where we set the analyser options (explained later), we build the following graph:

Audio graph with analyser node and properties

Step 2 – write the animation loop

The visualization itself depends on the options which we set for the analyser node. In this case we set the FFT size to 1024 (FFT is a kind of accuracy setting: the bigger the value, the more accurate the analysis will be. 1024 is common for visualizing waveforms, while lower values are preferred for visualizing frequencies). Here is what we set in this example:

  1. analyser.fftSize = 1024;
  2. bufferLength = analyser.frequencyBinCount;
  3. dataArray = new Uint8Array(bufferLength);

    • Line 2: we set the size of the FFT,
    • Line 3: this is the byte array that will contain the data we want to visualize. Its length is equal to fftSize/2.

When we build the graph, these parameters are set – effectively as constants, to control the analysis during play-back 

Here is the code that is run 60 times per second to draw the waveform:

  1. function visualize() {
  2.   // 1 – clear the canvas
  3.   // like this: canvasContext.clearRect(0, 0, width, height);
  4.   // Or use rgba fill to give a slight blur effect
  5.   canvasContext.fillStyle = ‘rgba(0, 0, 0, 0.5)’;
  6.   canvasContext.fillRect(0, 0, width, height);
  7.   // 2 – Get the analyser data – for waveforms we need time domain data
  8.   analyser.getByteTimeDomainData(dataArray);
  9.   // 3 – draws the waveform
  10.   canvasContext.lineWidth = 2;
  11.   canvasContext.strokeStyle = ‘lightBlue’;
  12.   // the waveform is in one single path, first let’s
  13.   // clear any previous path that could be in the buffer
  14.   canvasContext.beginPath();
  15.   var sliceWidth = width / bufferLength;
  16.   var x = 0;
  17.   for(var i = 0; i < bufferLength; i++) {
  18.     // dataArray values are between 0 and 255,
  19.     // normalize v, now between 0 and 1
  20.     var v = dataArray[i] / 255;
  21.     // y will be in [0, canvas height], in pixels
  22.     var y = v * height;
  23.     if(i === 0) {
  24.       canvasContext.moveTo(x, y);
  25.     } else {
  26.       canvasContext.lineTo(x, y);
  27.     }
  28.     x += sliceWidth;
  29.   }
  30.   canvasContext.lineTo(canvas.width, canvas.height/2);
  31.   // draw the path at once
  32.   canvasContext.stroke();
  33.   // once again call the visualize function at 60 frames/s
  34.   requestAnimationFrame(visualize);
  35. }

Explanations:

Below are other examples that draw waveforms.

Example 2: video player with waveform visualization

Using a <video> element is very similar to using an <audio> element. We have made no changes to the JavaScript code here; we Just changed “audio” to “video” in the HTML code. 

Example at JSBin:

a video player with real time waveform visualization

Example 3: both examples, this time with the graphic equalizer

Adding the graphic equalizer to the graph changes nothing, we visualize the sound that goes to the speakers. Try lowering the slider values – you should see the waveform changing.

Example at JSBin

audio player + equalizer + visualization

Example at JSBin:

Video player + equalizer + waveform visualization

Leave a comment