Is there a way get something like decibel levels from an audio file and transform that information into a json array?

天大地大妈咪最大 提交于 2019-11-27 13:18:42

问题


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


回答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.




回答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));


来源:https://stackoverflow.com/questions/13734710/is-there-a-way-get-something-like-decibel-levels-from-an-audio-file-and-transfor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!