Creative Audio Visualizers

An exploration of modern, line-style sound visualization powered by p5.js and its p5.sound library.

Today we’ll explore how to build a basic, line-style music visualization in the browser. We’ll be using p5.js for our drawings and its p5.sound library for analyzing sounds.

The demo is kindly sponsored by monday.com: the visual & intuitive project management and software development tool. If you would like to sponsor one of our demos, find out more here.

Analyzing Sound

When you want to make a drawing respond to an audio signal, the most basic thing you could do is to make it respond to the overall signal’s volume, its amplitude. This will give you the ability to animate your drawing, but only based on a single input. What if you would want to create different animations for the bass frequencies and for the high ones, or use a custom range of frequencies to animate different parts of your drawing? Here is where a Fast Fourier Transform can broaden your options.

At its heart FFT is an algorithm, that analyses a waveform and provides data about its different frequencies. So after you run an FFT analysis on an audio track, you can get a detailed report of its complete frequency spectrum and the amplitude of each frequency range. Then, using these different ranges, you can make your drawing respond differently for the bass, mid, or high frequencies of the signal.

The p5.sound library has a built-in FFT object, which comes in handy with a lot of useful methods depending on what you need to do. For our demos, we mostly use getEnergy() which returns a value from 0 to 255, representing the volume of that frequency.

Running this analysis while the music plays, you can make your visuals respond to different frequencies!

// Initiate the FFT object
  var fft = new p5.FFT();

  // Run the analysis, while the audio is playing
  fft.analyze();

  // Get different values for different frequency ranges
  // -----------------------------------------------------
  // p5.sound comes with predefined keywords, 
  // but giving getEnergy() 2 numbers instead of a keyword 
  // you could use your custom range if needed
  var bass    = fft.getEnergy( "bass" );
  var treble  = fft.getEnergy( "treble" );
  var mid     = fft.getEnergy( "mid" );     
  var custom  = fft.getEnergy( 100, 200 );

Drawing in the canvas

The main concept of all demos can be summed up in 4 parts:

  1. Create an initial drawing
  2. Analyze the audio signal
  3. Animate the drawing based on the different frequency ranges
  4. Add some visual interactions when the mouse is moved

In order to create our base drawing, we divide the circle in even pieces and draw some basic shapes around it. In the following image you can see the different options you get if you divide the circle in 4 pieces, 8 pieces, and so on (the black lines represent the effect of also going to the opposite direction for each line).

circle_


  // Define in how many pieces you want to divide the circle
  var pieces = 32;

  // Circle's radius
  var radius = 200;

  // Move the origin to the center of the canvas
  translate( width/2, height/2 );

  // The centered circle
  stroke( 0, 0, 255 );
  ellipse( 0, 0, radius );

  // For each piece draw a line
  for( i = 0; i < pieces; i++ ) {
    
    // Rotate the point of origin
    rotate( TWO_PI / pieces );
    
    // Draw the red lines
    stroke( 255, 0, 0 );
    line( 10, radius/2, 0, radius );
    
    //Optionally also draw to the opposite direction
    stroke( 0 );
    line( -10, radius/2, 0, radius ); 
  }

Tiny break: 📬 Want to stay up to date with frontend and trends in web design? Subscribe and get our Collective newsletter twice a tweek.

The fun part begins if you switch these static variables with a dynamic number, that constantly changes over time, like the volume of a specific frequency, the bass, the mid frequency, etc. Then you can map these values with your own custom range that fits your animation and gain complete control over the motion of your shapes.


  // Run the FFT analysis
  fft.analyze();

  // Get the volumes of different frequency ranges
  var bass    = fft.getEnergy("bass");
  var mid     = fft.getEnergy("mid");     
  var treble  = fft.getEnergy("treble");

  // Map the range of each volume with your desired numbers 
  var mapBass     = map( bass, 0, 255, -100, 100 );
  var mapMid      = map( mid, 0, 255, -150, 150 );
  var mapTreble   = map( treble, 0, 255, -200, 200 );

  
  for( i = 0; i < pieces; i++ ) {
    
    rotate( TWO_PI / pieces );
    
    // Draw the bass lines
    line( mapBass, radius/2, 0, radius );
    
    // Draw the mid lines
    line( mapMid, radius/2, 0, radius );    

    // Draw the treble lines
    line( mapTreble, radius/2, 0, radius );        
    
  }

And that’s about it! You can play around with different shapes or different mappings and create some unique shapes that respond to your favorite music.

Keep in mind that these demos need to run on a server environment.

Yannis Yannakopoulos

Interactive Developer. Currently exploring Generative Art, WebGL, GLSL & Web Audio. Musicing at The Blimp!.

Stay in the loop: Get your dose of frontend twice a week

Fresh news, inspo, code demos, and UI animations—zero fluff, all quality. Make your Mondays and Thursdays creative!

Feedback 12

Comments are closed.
  1. So awesome! This is exactly the kind of thing I have been looking for. I was not aware of the p5.sound library, which looks to be very versatile. Thank you Yannis for this inspiring post!

  2. Hi brother, I am trying to get this file played on my system but the screen keeps loading?

  3. Cool, I might give it a try! I was thinking about using it at a party to visualize the music playing from my mixer!

  4. The demo 5 was a hit for … used it as intro on my little website … respect and love for your awesome work !

  5. This is such an awesome library and very good post. Can’t wait to implement this!