2012-12-14 63 views
1

對於一個項目,我通過從Java服務器的WebSockets檢索實時音頻流。在服務器上,我以8位有符號字節值(兩個字節組成一個樣本)的形式處理16Bit/8000hz/mono的樣本。但是,在瀏覽器中,支持的最低採樣率爲22050赫茲。所以我的想法是「簡單地」將現有的8000升級到32000赫茲,這在我看來很容易計算。升頻音頻PCM數據在Javascript與WebAudioApi

到目前爲止,我已經試過linear upsamplingcosine interpolation,但都沒有奏效。除了聽起來真的扭曲之外,第一個還增加了一些點擊聲音。我在Chrome中也可能遇到WebAudioAPI的問題,但至少聲音在播放,並且幾乎不可辨認。所以我想沒有codec或endianess問題。

下面是當接收到帶有聲音數據的二進制數據包被執行的完整代碼。爲了簡單起見,我一直在創建新的緩衝區和緩衝區資源(是的,對性能沒有好處)。 data是一個ArrayBuffer。首先,我將樣品轉換爲Float,然後我進行上採樣。

//endianess-aware buffer view 
var bufferView=new DataView(data), 
//the audio buffer to set for output 
buffer=_audioContext.createBuffer(1,640,32000), 
//reference to underlying buffer array 
buf=buffer.getChannelData(0), 
floatBuffer8000=new Float32Array(160); 


//16Bit => Float 
for(var i=0,j=null;i<160;i++){ 
    j=bufferView.getInt16(i*2,false); 
    floatBuffer8000[i]=(j>0)?j/32767:j/-32767; 
} 

//convert 8000 => 32000 
var point1,point2,point3,point4,mu=0.2,mu2=(1-Math.cos(mu*Math.PI))/2; 
for(var i=0,j=0;i<160;i++){ 
    //index for dst buffer 
    j=i*4; 

    //the points to interpolate between 
    point1=floatBuffer8000[i]; 
    point2=(i<159)?floatBuffer8000[i+1]:point1; 
    point3=(i<158)?floatBuffer8000[i+2]:point1; 
    point4=(i<157)?floatBuffer8000[i+3]:point1; 


    //interpolate 
    point2=(point1*(1-mu2)+point2*mu2); 
    point3=(point2*(1-mu2)+point3*mu2); 
    point4=(point3*(1-mu2)+point4*mu2); 

    //put data into buffer 
    buf[j]=point1; 
    buf[j+1]=point2; 
    buf[j+2]=point3; 
    buf[j+3]=point4; 
} 

//playback 
var node=_audioContext.createBufferSource(0); 
node.buffer=buffer; 
node.connect(_audioContext.destination); 
node.noteOn(_audioContext.currentTime); 

回答

0

終於找到了解決方案。從16位到浮動轉換是錯誤的,它只是需要

floatBuffer8000[i]=j/32767.0; 

此外,餵食了很多小樣本的API不能很好地工作,所以你需要緩衝一些樣品,一起玩他們。

+1

我怎樣才能將任何一個採樣率轉換爲另一個採樣率?不僅8000到32000 – noamtcohen