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

前端 未结 2 1824
深忆病人
深忆病人 2020-12-09 00:31

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

2条回答
  •  有刺的猬
    2020-12-09 01:01

    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;
    }

    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.

提交回复
热议问题