Animate object by sound amplitude?

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-04 07:20:17

I've created an example that changes the radius and color of an svg circle element based on audio amplitude.

This will work in WebKit browsers, but nothing else. Webkit browsers are the only browsers that come even close to implementing the W3C Web Audio API Spec, as far as I know, but the Mozilla Audio Data API Documentation seems to indicate that Mozilla has abandoned that spec and will be implementing the Web Audio API too. I'm blissfully unaware of the state of Internet Explorer's implementation (or lack thereof) of the the spec.

Unfortunately, the answer right now is that there's no great cross-browser solution for this other than Flash, but if you go that route, you're screwed on mobile devices.

Here's the full, working JSBin example.

And here's the code:

HTML:

<!DOCTYPE html>
<html>
    <head>
        <meta charset=utf-8 />
        <title>Drums</title>
    </head>
    <body>
        <svg width="200" height="200">
            <circle id="circle" r="10" cx="100" cy="100" />
        </svg>
    </body>
</html>

Javascript:

var context = new webkitAudioContext();

// Here's where most of the work happens
function processAudio(e) {
  var buffer = e.inputBuffer.getChannelData(0);
  var out = e.outputBuffer.getChannelData(0);
  var amp = 0;

  // Iterate through buffer to get the max amplitude for this frame
  for (var i = 0; i < buffer.length; i++) {
    var loud = Math.abs(buffer[i]);
    if(loud > amp) {
      amp = loud;
    }
    // write input samples to output unchanged
    out[i] = buffer[i];
  }

  // set the svg circle's radius according to the audio's amplitude
  circle.setAttribute('r',20 + (amp * 15));

  // set the circle's color according to the audio's amplitude
  var color = Math.round(amp * 255);
  color = 'rgb(' + color + ',' + 0 + ',' + color + ')';
  circle.setAttribute('fill',color);
}

window.addEventListener('load',function() {
  var circle = document.getElementById('circle');

  // Add an audio element
  var audio = new Audio();
  audio.src = 'http://www.mhat.com/phatdrumloops/audio/acm/mole_on_the_dole.wav';
  audio.controls = true;
  audio.preload = true;
  document.body.appendChild(audio);


  audio.addEventListener('canplaythrough',function() {
    var node = context.createMediaElementSource(audio);

    // create a node that will handle the animation, but won't alter the audio
    // in any way        
    var processor = context.createJavaScriptNode(2048,1,1);
    processor.onaudioprocess = processAudio;

    // connect the audio element to the node responsible for the animation
    node.connect(processor);

    // connect the "animation" node to the output
    processor.connect(context.destination);

    // play the sound
    audio.play();
  });
});

Using a Javascript node to assess amplitude will work, but is less than ideal for performance reasons. I'd suggest using a RealtimeAnalyser on a requestAnimationFrame timer. You can start with the code from http://updates.html5rocks.com/2012/02/HTML5-audio-and-the-Web-Audio-API-are-BFFs, just use a smaller fftSize (128) and RMS the values.

KievII library ( http://kievii.net ) is targeted for audio applications. Maybe you can find something useful there (for example, you can animate a Wavebox object or a series of ClickBar objects). Take a look at the examples there: http://kievII.net/examples.html

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