Audio Visualization
November 12, 2021
I’ve been meaning to delve into the Web Audio API for a while, but I didn’t know enough about Canvas to do anything interesting. Until now!
The javascript can be found here.
Edit 11/17
After experimenting a little with progressively rendering to a canvas, I added a spectrogram. I also made a few optimization tweaks to the oscilloscope, and I finally made a favicon!
The code is mostly a standard use of the API, but I did run into one problem: the Analyser’s frequency data is linear, but human hearing is logarithmic. Displaying the raw frequency data would result in 6 octaves (of the 10 that healthy human ears can hear) being condensed into about 6% of the graph. Half of the graph would be displaying just the highest octave, which is almost nonexistent in the mp3 I’m using!
For the histogram, I converted the data like so:
function logAverage(arr) {
let ret = [];
let i = 0;
while (i < arr.length) {
let next_i = 2 * i + 1;
let average = arr.slice(i, next_i).reduce((acc, el) => acc + el) / (i + 1);
ret.push(average);
i = next_i;
}
return ret;
}
Each iteration of the while
loop averages twice as many data points as the previous one, which makes each bar on the frequency graph represent the same perceptual frequency range. I thought of initializing the return array size using Math.log2()
to prevent multiple allocations, but it felt like a premature optimization. The push
syntax is cleaner.
For the spectrogram, this method didn’t provide enough resolution, so I used Math.sqrt()
when calculating color placement instead.
I’d still like to add a waveform-seek display, but I’m not sure yet how I want to generate the waveform image.