![](/img/trans.png)
[英]Is there a way to use the Web Audio API to sample audio faster than real-time?
[英]real-time processing web audio api
我正在使用web audio api和requestAnimationFrame來可視化麥克風的音頻輸入。 我可以成功地可視化時域頻率數據,但問題在於,由於web audio api以秒為單位計算時間,因此我的界面每秒都會根據輸入的變化而變化。
所以我的問題是,我如何可視化聲音並使圖形保持在屏幕上,因此我可以在一定時間內看到我的所有頻率數據(假設我說話,同時在畫布上可視化僅5秒)。
我使用以下代碼(從這里的例子中獲取):
MicrophoneSample.prototype.visualize = function() {
this.canvas.width = this.WIDTH;
this.canvas.height = this.HEIGHT;
var drawContext = this.canvas.getContext('2d');
var times = new Uint8Array(this.analyser.frequencyBinCount);
this.analyser.getByteTimeDomainData(times);
for (var i = 0; i < times.length; i++) {
var value = times[i];
var percent = value / 256;
var height = this.HEIGHT * percent;
var offset = this.HEIGHT - height - 1;
var barWidth = this.WIDTH/times.length;
drawContext.fillStyle = 'purple';
drawContext.fillRect(i * barWidth, offset, 1, 1);
}
requestAnimFrame(this.visualize.bind(this));
}
getByteTimeDomainData不會為您提供頻率信息。 這些是實時的時域波形值,也稱為幅度值。 如果要隨着時間的推移將它們可視化,請將值附加到數組中並繪制它。 如果您想要實際頻率值,請使用getByteFrequencyData。
OP,這里有一些偽代碼。 僅供參考,這真的不是一個網絡音頻問題,而是一個動畫問題。
在可視化器原型函數中存儲一個變量/字段,該函數可以跟蹤您想要延遲重繪畫布的秒數,保留一個單獨的計數器,每當requestAnimFrame(...)被繪制時它將遞增。 計數器達到延遲量后,重新繪制畫布。
編輯現在,我想到了......解決方案應該非常簡單。 如果我錯了,請糾正我,但是這個粗略的解決方案是假設您在動畫循環中調用MicrophoneSample.visualize()...因此,其中的代碼每秒執行一次。 如果您發布MicrophoneSample對象代碼,或者至少是您的動畫循環,我可以提供更多幫助。
/* NOTE!
*
*/
// Find a way to put these into your PARENT MicrophoneSample object
var delay = 5;
// Note that I am setting delayCount initially to zero - during the loop
// the delayCount will actually get reset to 1 from thereafter (not 0)...
// this gives us a way to initially draw your visualization on the first frame.
var delayCount = 0;
// Pull var times out so it doesn't get calculated each time.
var times = new Uint8Array(MicrophoneSample.analyser.frequencyBinCount);
// Same goes for the canvas...
// I would set these values inside of the PARENT MicrophoneSample object
MicrophoneSample.canvas.width = this.WIDTH;
MicrophoneSample.canvas.height = this.HEIGHT;
// you only need to establish the drawing context once. Do it in the PARENT
// MicrophoneSample object
var drawContext = this.canvas.getContext('2d');
MicrophoneSample.prototype.visualize = function() {
/*
* NOTE!
*/
// Here's the juicy meat & potatoes:
// only if the delayCount reaches the delay amount, should you UPDATE THE
// TIME DOMAIN DATA ARRAY (times)
// if your loop runs every second, then delayCount increments each second
// and after 5 seconds will reach your designated delay amount and update your
// times array.
if(delayCount == 0 || delayCount == delay) {
this.analyser.getByteTimeDomainData(times);
// Now, it would be redundant (and totally noob-programmer of you) to
// redraw the same visualization onto the canvas 5 times in a row, so
// only draw the visualization after the first pass through the loop and then
// every 5th pass after that :]
for (var i = 0; i < times.length; i++) {
var value = times[i];
var percent = value / 256;
var height = this.HEIGHT * percent;
var offset = this.HEIGHT - height - 1;
var barWidth = this.WIDTH/times.length;
drawContext.fillStyle = 'purple';
drawContext.fillRect(i * barWidth, offset, 1, 1);
}
// Note: 1, not 0!
delayCount = 1;
}
else {
delayCount++;
}
requestAnimFrame(this.visualize.bind(this));
}
請記住,我實際上沒有測試過這些。 但它至少應該指向正確的方向。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.