2014-02-22 43 views
3

因此,我已將通道數據從AudioBuffer中取出,並通過可傳輸對象將其發送給網絡工作人員以對其進行一些處理,現在我要將其重新放入。真的要拷貝它回來了嗎?手動將pcm數據放入AudioBuffer

var myData = new Float32Array(audioBuf.length); 
var chanData = audioBuf.getChannelData(0); 

for (var n = 0; n < chanData.length; n++) { 
    chanData[n] = myData[n]; 
} 

我真的希望有一些辦法只是改變了ArrayBuffer每個AudioBuffer渠道參考。像...

audioBuf.channel[0].buffer = myData.buffer; 

...會非常簡單而有效,但看似不存在。有沒有像這樣改變參考並避免複製數據的方法?

編輯:經過一些進一步的調查,我發現使用帶有可傳輸對象的web音頻API的問題更令人討厭。當您將陣列緩衝區傳輸給工作人員時,AudioBuffer的基礎陣列緩衝區被清除,我相信甚至通過getChannelData返回的Float32Array不可能進行復制操作。我現在唯一能看到完成我想要的東西的方法是放棄原始的AudioBuffer,創建一個全新的AudioBuffer,然後將我的數據複製到其中。真??

回答

1

有幾件事情:

1),對一種類型數組的數據複製到另一個不需要你去通過循環的頭痛低成本漂亮的方法。

var copy = new Float32Array(orig.length); 
copy.set(orig); 

2)您AudioBuffer的問題得到清除僅僅是規範與網絡工作者()轉讓對象https://developer.mozilla.org/en-US/docs/Web/Guide/Performance/Using_web_workers#Passing_data_by_transferring_ownership_(transferable_objects)的一部分。這是他們保證線程安全的唯一方法。如果兩個線程同時訪問同一個對象,他們可能會同時對它進行變異,最終會產生各種瘋狂。

我不完全確定爲什麼你對創建一個新的AudioBuffer並將數據複製到它的前景感到非常惱火。你可以在2行中做單聲道緩衝區。 3線立體聲。您已經完成了更多的工作,比如設置所有需要的樣板以啓動Web工作人員。無論如何,如果您可以提供關於您的應用程序的更多細節以及它在做什麼,我很樂意提出一些建議。

2

我們最近在AudioBuffer中添加了兩個新方法,使用copyFromChannel可能對您有用。它按照它在tin上的說法(將一個ArrayBuffer放在AudioBuffer的一個通道中),也許在該過程中保存一個副本(避免複製的原因和條件解釋爲here)。

我相信它目前只在Firefox中實現,但我沒有檢查。

+0

這在現代瀏覽器中得到了相當廣泛的支持。值得注意的是,'copyFromChannel'方法在主線程上不需要額外的數組分配,並且比'getChannelData'快兩倍(儘管它不能直接用於可傳送數據,通道數據將被放入數組中,需要再次通過'getChannelData'完成相同的額外分配)。 –

2

我一整天都在努力,所以我想我應該分享我的解決方案。

var PCM = [0,1,2,3,4,5,6,7,8,9,8,7,6,5,4,3,2,1]; 


var room = new window.AudioContext(); 
var sampleRate = 44100; 
var channels = 1; 

var audioBuffer = room.createBuffer(channels, 0, sampleRate); 

var channelObject = audioBuffer.getChannelData(0); 

var audioBufferDataArray = channelObject.data; 


// actual code to set the data 

audioBuffer.length = PCM.length; // optional 

for(var i=0; i<PCM.length; i++){ 
    audioBufferDataArray[i] = PCM[i]; 
}