Playing with sound - 2

Creating some procedural art using audio as an input

by blackpolygon

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.0/p5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.0/addons/p5.sound.min.js"></script>
<html>

  <head>
    <title>Playing with sound</title>
  </head>

  <body>
    <canvas id="canvas"></canvas>
  </body>

</html>

CSS

html {
  width: 100%;
  height: 100%;
}

body {
  margin: 0 auto;
  overflow: hidden;
  height: 100%;
}

JavaScript

var canvas, ctx, w2, mic, h2, fft, spectrum, energySlots, halfPI;

function setup() {
  energySlots = 100;
  halfPI = Math.PI / 2;
  canvas = document.getElementById('canvas');
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;

  ctx = canvas.getContext('2d');
  ctx.lineWidth = 1;
  ctx.fillStyle = '#000';

  w2 = window.innerWidth / 2;
  h2 = window.innerHeight / 2;

  mic = new p5.AudioIn()
  mic.start();
  fft = new p5.FFT(0.8);
  fft.setInput(mic);

}

function draw() {
  // Clear the previous drawing  
  ctx.fillRect(0, 0, canvas.width, canvas.height);

  // We need to call analyze before doing the next computations
  spectrum = fft.analyze();

  // Divide the spectrum in N slots, get the energy level for each frequency
  // Draw an arc with a circumference that represents that amount of energy
  var seRatio = spectrum.length / energySlots; // Spectrum/energy ratio

  for (var i = 0; i < energySlots; i++) {
    // Get the energy for that frequency
    var freq = seRatio * i;
    var e = fft.getEnergy(freq);

    // The color of the circle will change depending on its index
    var green = 155 + i;
    ctx.strokeStyle = "rgba(0, " + green + ", 255, 1)";

    var circleRadius = Math.floor(i * (h2 / energySlots));
    var maxAngle = map(e, 0, 255, 0, 2 * Math.PI);
    var initialAngle = halfPI - maxAngle / 2;
    var finalAngle = halfPI + maxAngle / 2;
    // Draw the arc
    ctx.beginPath();
    ctx.arc(w2, h2, circleRadius, initialAngle, finalAngle);
    ctx.stroke();
    ctx.closePath();
  }
}