2013-03-28 100 views
3

我正在使用web音頻api和requestAnimationFrame來顯示來自麥克風的音頻輸入。我可以成功地將時域頻率數據可視化,但問題是,由於網絡音頻API會以秒爲單位計算時間,因此每隔一秒,我的界面就會根據輸入的內容而變化。實時處理web音頻api

所以我的問題是,我如何可視化聲音並使圖形保持在屏幕上,因此我可以在一定的時間內看到我的所有頻率數據(假設我說話,同時在畫布上可視化爲5秒)。

我使用下面的代碼(從花例子here):

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

} 
+0

Rq:調整畫布大小/獲取每次調用的上下文是一個矯枉過正的做法:做一次並存儲ctx。是否需要將聲源連接到分析儀以獲取頻率? – GameAlchemist 2013-03-28 09:52:45

+0

輸入已連接到分析儀,我也可以獲取波形值可以提取或其他聲音屬性。主要問題是如何讓他們的居民可視化? – user2039789 2013-03-28 10:07:37

回答

2

getByteTimeDomainData不給你的頻率信息。這些是實時的時域波形值,也稱爲幅度值。如果你想隨着時間的推移想象它們,將它們的值附加到數組中並繪製。如果你想要真正的頻率值使用getByteFrequencyData。

+0

如果getByteTimeDomainData允許創建一個有用的波形。這些例子已經將輸入可視化了,但正如我所說的每秒圖表消失。我怎樣才能讓它留在那裏? – user2039789 2013-03-28 09:54:19

+1

正如我所說:將times [i]數據推送到另一個數組中,該數組存儲在MicrophoneSample類中並繪製該數組。 – headchant 2013-03-28 10:33:29

+0

沿着這個線:http://jsfiddle.net/ez6R6/1/ – headchant 2013-03-28 10:46:06

2

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

只是要記住,我沒有真正測試過這些。但它至少應該指向正確的方向。

+0

我試圖用你的僞代碼來實現一個解決方案,但沒有成功。不知道是否是因爲我的編程技巧或... 你能在這裏或在PM中寫更詳細的代碼嗎?謝謝哥們:))) – user2039789 2013-04-01 10:23:44

+0

好吧,只是爲了確保,你知道僞代碼不是從字面上理解的嗎?只是爲了讓首先和最重要的:] – 2013-04-01 10:48:14

+0

有你去。去拿他們。 – 2013-04-01 11:25:26