Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Normalize audio data from getByteFrequencyData by volume

I've created a getSpectrum method using the getByteFrequencyData method on the Web Audio API's Analyser Node. The array of audio data returned is relative to the audio source's (either an el, or Audio() instance) volume, a value from 0 to 1.

Using the audio source's volume I'm trying to normalize each value received from getByteFrequencyData so that the user of getSpectrum doesn't have to worry about volume when they're visualizing the audio data.

This is the striped down version of getSpectrum

var audioData = new Uint8Array(analyser.binCount);
var spectrum = [];

analyser.getByteFrequencyData(audioData);

for (var i = 0; i < audioData.length; i++) {
  var value = audioData[i];

  //Where I'm trying to calculate the value independent of volume
  value = ((value / audioEl.volume) / 255);

  spectrum.push(value);
}

return spectrum;

The W3C spec references the equation used to calculate the returned value given a maxDecibels and minDecibels. With my rudimentary understanding, I've tried to inverse the math so I get a normalized value, but I can't getting it working exactly right. I'm having trouble accomplishing this with just a volume value from 0 to 1.

Any incite would be greatly appreciated! Heres a working example of the issue. Changing the volume slider will illustrate the problem.

Update 7/22/16: Thanks to @raymond-toy's answer I figured out how to convert the 0 to 1 volume value to decibels.

volumeDB = Math.abs((Math.log(volume)/Math.LN10)*20);

After getting the DB, I inversed the equation in the W3C spec,

value = ((audioDataValue * volumeDB) / 255) - volumeDB

Unfortunately, value somehow still ends up relative to volume. Does anyone see what I'm missing?

like image 283
Chris Dolphin Avatar asked Jul 22 '16 18:07

Chris Dolphin


2 Answers

getByteFrequencyData returns values in dB. You don't want to divide these values by the audioE1.volume. You want to convert (somehow!) audioE1.volume to a dB value and add (or subtract) that from values from getByteFrequencyData

It might be easier to understand things if you used getFloatFrequencyData first to see what's happening.

like image 187
Raymond Toy Avatar answered Oct 02 '22 01:10

Raymond Toy


Apparently I was on a fool's errand. As @raymond-toy pointed out, Spectrum values are implicitly relative to volume. Normalizing would mean losing a portion of data "off the bottom of the spectrum", which was not my goal.

If anyone's curious, I ended up just dividing the audioDataValue by 255, getting a float from 0 to 1.

like image 23
Chris Dolphin Avatar answered Oct 01 '22 23:10

Chris Dolphin