2

プロジェクトでは、Java サーバーから WebSocket 経由でライブ オーディオ ストリームを取得しています。サーバー上で、16Bit/8000hz/mono のサンプルを 8 ビットの符号付きバイト値 (2 バイトで 1 つのサンプルを構成) の形式で処理しています。ただし、ブラウザーでサポートされている最低のサンプルレートは 22050 Hz です。したがって、私の考えは、既存の 8000 から 32000 Hz を「単純に」アップサンプリングすることでした。これはサポートされており、簡単な計算のように思えます。

これまで、線形アップサンプリングコサイン補間を試しましたが、どちらもうまくいきませんでした。最初のものは本当に歪んだ音に加えて、いくつかのクリックノイズも追加しました. Chrome の WebAudioAPI にも問題があるかもしれませんが、少なくともサウンドは再生されており、本来あるべきものとしてほとんど認識できません。したがって、コーデックまたはエンディアンの問題はないと思います。

サウンド データを含むバイナリ パケットを受信したときに実行される完全なコードを次に示します。簡単にするために、常に新しいバッファとバッファソースを作成しています(パフォーマンスには適していません)。dataArrayBuffer です。まず、サンプルを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);
4

1 に答える 1

2

最後に、これに対する解決策を見つけました。16Bit から Float への変換は間違っています。

floatBuffer8000[i]=j/32767.0;

また、多くの小さなサンプルを API に供給するのはうまくいかないため、いくつかのサンプルをバッファリングして一緒に再生する必要があります。

于 2012-12-17T13:21:35.207 に答える