Skip to content Skip to sidebar Skip to footer

Is There A Way Get Something Like Decibel Levels From An Audio File And Transform That Information Into A Json Array?

So that I can use the information to coordinate a page animation like making elements brighter as the decibel levels get higher

Solution 1:

This approach will work in Chrome / Safari:

+function(){
  
  var ctx = new AudioContext()
    , url = 'https://cf-media.sndcdn.com/OfjMZo27DlvH.128.mp3?Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiKjovL2NmLW1lZGlhLnNuZGNkbi5jb20vT2ZqTVpvMjdEbHZILjEyOC5tcDMiLCJDb25kaXRpb24iOnsiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE1MTUwNDM5Njd9fX1dfQ__&Signature=FfmL2qUssAKs3Z7EPoYo0Yq8-SAg8rKLPs65EasXwuVkfsOB4joFqeCvVR2elpaG-lJaV4hXpXFiRCDWXNOYyAtO4Oz~sexiPwIoSk8-jWiVbGQRS8TMmUmj7TJzxemMOIj7ugWJKk6PHsrUdgqs9woDpHzxmkGCzk6sfqJEIsdeZJ4rWUFAh4iGWn9M6b0xfzTgndAJmytkNj9raCpWCBVmdr5u-r9nt~q5uF1easNSW9oaFilM4s1Hq2ei~VJye8zW9bzvrGm8idVdy-tiPeMWAKcE8J2VuaS1Ret6jRTRaHTDuiNgA5sZvgTzNpEpKtWI7UmAWI5TrqNVSlxpgQ__&Key-Pair-Id=APKAJAGZ7VMH2PFPW6UQ'  
    , audio = new Audio(url)
    // 2048 sample buffer, 1 channel in, 1 channel out  
    , processor = ctx.createScriptProcessor(2048, 1, 1)
    , meter = document.getElementById('meter')
    , source
    
  audio.crossOrigin = 'anonymous'

  audio.addEventListener('canplaythrough', function(){
    source = ctx.createMediaElementSource(audio)
    source.connect(processor)
    source.connect(ctx.destination)
    processor.connect(ctx.destination)
    audio.play()
  }, false);
  
  // loop through PCM data and calculate average
  // volume for a given 2048 sample buffer
  processor.onaudioprocess = function(evt){
    var input = evt.inputBuffer.getChannelData(0)
      , len = input.length   
      , total = i = 0
      , rms
    while ( i < len ) total += Math.abs( input[i++] )
    rms = Math.sqrt( total / len )
    meter.style.width = ( rms * 100 ) + '%'
  }
  
}()
#meter {
  width: 0%;
  height: 15px;
  margin: 2px 0;
  background: green;
  -webkit-transition: width .05s;
}
<div id="meter"></div>

The important stuff happens here:

processor.onaudioprocess = function(evt){
  var input = evt.inputBuffer.getChannelData(0)
    , len = input.length   
    , total = i = 0
    , rms
  while ( i < len ) total += Math.abs( input[i++] )
  rms = Math.sqrt( total / len )
  meter.style.width = ( rms * 100 ) + '%' 
}

Basically, you grab the raw PCM data (values from -1 to 1) every 2048 samples and you loop through them, calculating the average signal level over the given period of time.

You can then use that value to do your animations.

Edit: Updated to use RMS, which as Jason pointed out is a more meaningful measurement.


Solution 2:

Yes, you need to grab the raw PCM samples (like Kennis mentions). However, to calculate the overall volume levels, you want to grab the RMS (Root Mean Square) of the values. Also, you will likely want to pay attention to all the channels in the stream, not just the first channel (so you can accurately reflect the volume level for a stereo stream for example).

There are some tricks (make sure you use multiplication of the same samples across channels, not addition). Then you will be adding them all together (again like Kennis is doing). If you want it an actual decibels, there is a log step that is required as well.

There is an example as an answer to this other question.

Relevant code:

var rms = Math.sqrt(sum / (_buffer.length / 2));
var decibel = 20 * (Math.log(rms) / Math.log(10));

Post a Comment for "Is There A Way Get Something Like Decibel Levels From An Audio File And Transform That Information Into A Json Array?"