2015-10-06 69 views
2

我刚开始查看Web Audio API,并试图对音频进行视觉同步。当音频中的音量(节拍?)增加时,我想在屏幕上闪烁白色。我到目前为止所做的:使用Web Audio API的音频反应式视觉

var mp3  = "08 - No More Sorrow.mp3"; 
var context = new AudioContext(); 
var request = new XMLHttpRequest(); 
request.open('GET', mp3, true); 
request.responseType = "arraybuffer"; 
request.onload = function() { 
    context.decodeAudioData(request.response, function (buffer) { 
     var sourceBuffer = context.createBufferSource(); 
     sourceBuffer.buffer = buffer; 
     sourceBuffer.connect(context.destination); 
     sourceBuffer.start(context.currentTime); 
    }); 
}; 
request.send(); 

......这只是使用Web Audio API播放音频。不知道下一步该怎么做。我已经选择了Beat Detection Using JavaScript and the Web Audio APIMaking Audio Reactive Visuals页面,但是无法真正理解任何内容。

如果我告诉你什么是我想要做的,而不使用网络音频API,它会是这样的:

Array.prototype.pushIfExists = function(item) { 
 
    if (item) { 
 
    this.push(item); 
 
    } 
 
} 
 

 
function random(min, max) { 
 
    var min = min || 0; 
 
    var max = max || 100; 
 
    var num = Math.floor(Math.random() * max); 
 
    while (num < min) { 
 
    num = Math.floor(Math.random() * max); 
 
    } 
 
    return num; 
 
} 
 

 
function avarage(array) { 
 
    var sum = 0; 
 
    var avarage = 0; 
 
    for (var i = 0; i < array.length; i++) { 
 
    sum += array[i]; 
 
    } 
 
    avarage = sum/array.length; 
 
    return avarage; 
 
} 
 

 
var beats = []; 
 
var delay = 500; 
 
var delayIncrement = 200; 
 
var threshold = 50; 
 
var thresholdLimit = 100; 
 
var beatAvarageRange = 5; 
 
var flashDuration = 100; 
 

 
for (var i = 0; i < 100; i++) { 
 
    beats.push(random(0, thresholdLimit)); 
 
} 
 

 
for (var i = 0; i < beats.length; i++) { 
 
    (function(i) { 
 
    setTimeout(function() { 
 
     var recentBeats = []; 
 
     for (var j = 1; j < beatAvarageRange + 1; j++) { 
 
     recentBeats.pushIfExists(beats[i - j]); 
 
     } 
 
     threshold = avarage(recentBeats); 
 
     if (beats[i] > threshold) { 
 
     document.body.style.backgroundColor = "white"; 
 
     setTimeout(function() { 
 
      document.body.style.backgroundColor = "black"; 
 
     }, flashDuration); 
 
     } 
 
    }, delay); 
 
    delay += delayIncrement; 
 
    })(i); 
 
}
body { 
 
    background-color: black; 
 
}

+0

我喜欢在SO这里看到关于Web Audio API的好问题,并且只是在给你一些(小)帮助以获得答案的精神下进行一些副本编辑。 (和upvoted。) – sideshowbarker

+1

@sideshowbarker看来这是我解决自己的问题之一。很高兴看到没有人回答。 – akinuri

回答

2

我已经做了一些更多的挖并找到了解决方案。使用在Exploring the HTML5 Web Audio: visualizing sound | Smartjava.org页的解释,我想出了以下内容:

var volumeBars = { 
 
    mono : document.getElementById("monoFill") 
 
}; 
 

 
document.getElementById("open-file").onchange = function (evt) { 
 
    var file = evt.target.files[0]; 
 
    var reader = new FileReader(); 
 
    reader.onload = function(e) { 
 
     playSound(e.target.result); 
 
    } 
 
    reader.readAsArrayBuffer(file); 
 
} 
 

 
var context = new AudioContext(); 
 

 
function playSound(arraybuffer) { 
 
    context.close(); 
 
    context = new AudioContext(); 
 

 
    var source = context.createBufferSource(); 
 
    context.decodeAudioData(arraybuffer, function (buffer) { 
 
     source.buffer = buffer; 
 
    }); 
 

 
    var analyser = context.createAnalyser(); 
 
    analyser.smoothingTimeConstant = 0.3; 
 
    analyser.fftSize = 1024; 
 

 
    jsNode = context.createScriptProcessor(2048, 1, 1); 
 
    jsNode.onaudioprocess = function() { 
 
     var array = new Uint8Array(analyser.frequencyBinCount); 
 
     analyser.getByteFrequencyData(array); 
 
     volumeBars.mono.style.height = Math.average(array) * 2 + "px"; 
 
     volumeBars.mono.innerHTML = Math.floor(Math.average(array)); 
 
    } 
 

 
    source.connect(analyser); 
 
    source.connect(context.destination); 
 
    jsNode.connect(context.destination); 
 
    analyser.connect(jsNode); 
 

 
    source.start(); 
 
} 
 

 
Math.average = function(arguments) { 
 
    var numbers; 
 
    if (arguments[0] instanceof Array) { 
 
     numbers = arguments[0]; 
 
    } 
 
    else if (typeof arguments[0] == "number") { 
 
     numbers = arguments; 
 
    } 
 
    var sum = 0; 
 
    var average = 0; 
 
    for (var i = 0; i < numbers.length; i++) { 
 
     sum += numbers[i]; 
 
    } 
 
    average = sum/numbers.length; 
 
    return average; 
 
}
* { 
 
    margin: 0; 
 
    padding: 0; 
 
    box-sizing: border-box; 
 
} 
 
body { 
 
    background-color: gainsboro; 
 
} 
 
#container { 
 
    height: 340px; 
 
} 
 
.bar { 
 
    width: 50px; 
 
    height: 100%; 
 
    position: relative; 
 
    float: left; 
 
    margin: 20px; 
 
    height: calc(100% - 40px); 
 
} 
 
.fill { 
 
    background: LawnGreen; 
 
    height: 20px; 
 
    width: 100%; 
 
    box-shadow: 0 0 3px rgba(0,0,0,.25), 
 
     inset 1px 1px 1px rgba(255,255,255,.75), 
 
     inset -1px -1px 1px rgba(0,0,0,.4); 
 
    position: absolute; 
 
    bottom: 0; 
 
    padding: 5px; 
 
    color: rgba(0,0,0,.75); 
 
} 
 
input { 
 
    margin: 20px; 
 
}
<div id="container"> 
 
\t <div class="bar" id="mono"> 
 
\t \t <div class="fill" id="monoFill"></div> 
 
\t </div> 
 
</div> 
 

 
<input type="file" id="open-file" accept="audio/*" />

Web Audio API - Volume Meter - JSFiddle

这不是我试图做最后的可视化,但创建一个首先,音量计似乎是理解Web Audio API如何工作的更好的主意。