2

こんにちは、クライアント側でバッファリングされた PCM データ (Float32) の配列があります (これらのオーディオ配列はすべて同じ曲の一部です)。PCM データのクライアント側バッファリングのようなものです。N 個の配列がサーバーからダウンロードされた後、これらのバッファーの再生を開始し、以下の関数を呼び出してサンプル配列を再生します。

var AudioStart =0;

function playPcmChunk(data){

    var source = audioContext.createBufferSource();

    var audio=new Float32Array(data);

    var audioBuffer = audioContext.createBuffer(1, audio.length , 44100);

    audioBuffer.getChannelData(0).set(audio);

    source.buffer = audioBuffer;

    source.start(AudioStart);

    AudioStart += audioBuffer.duration;
}

すべてのサンプルの間にクリックが発生します。

サーバー側のデータを確認するために、Audacity で問題なくスムーズに動作します。

次に、デバッグするために、値を文字通り印刷し、クライアント側とサーバー側でそれらを比較して、トランスポートに問題があるかどうか、それらが同じかどうかを確認しました。

では、バッファリングされたサンプルの配列間でクリック音が聞こえるのはなぜですか。

私の正確な時間の計算は正しくありませんか。これは既知の Web オーディオ API の問題ですか?

これは私が得ることができる限り正確だと思います。クリックを取り除くためにフィルターを適用する必要がありますか? そのフィルターの名前は何ですか? あったとしてもハックだと思います。

どんなアイデアでも大歓迎です

編集:

これは、websocket を読み取り、これらのサンプルの 30 個 (これは完全に乱数です) を配列に格納する場所です。それらの 30 が保存された後、各サンプルでループを開始し、playPcmChunk を呼び出して、入ってくるオーディオの残りを破棄します (これはテスト用です)。

それぞれ 44100 32bitFloat、Mono です。

wsAudio.onmessage = function (messageEvent) {
        if (messageEvent.data instanceof Blob) {


            var fileReader = new FileReader();
            fileReader.onload = function (e) {
                if (currentCount == -1) {
                    return;
                }
                if (currentCount < 30) {
                    audioChunks[currentCount] = e.target.result;
                    currentCount++;
                } else {

                    for (var j = 0; j < 30; j++) {

                        playPcmChunk(audioChunks[j]);
                    }
                    currentCount = -1;
                }



            };
            fileReader.readAsArrayBuffer(messageEvent.data);



        }
    }
4

2 に答える 2

2

私は同様のことをしていて、同じ問題を経験しました。解決策は、audioContext.createJavaScriptNode() を使用することです。

Websocket からチャンクを受信したときにチャンクを再生する代わりに、チャンクをどこかに保存し、要求されたときに出力バッファーを埋める必要があります。

==

var audioNode = audioContext.createJavaScriptNode(4096, 1, 1);

audioNode.onaudioprocess = function(event) {
                           if (decodedAudioBuffer.length >= bufferSize) {
                                  var decoded = decodedAudioBuffer.splice(0, bufferSize);
                                  var samples = new Float32Array(bufferSize);
                                  for (var i=0; i<decoded.length; i++) {
                                         samples[i] = decoded[i];
                                  }

                                  samples = resampler.resample(samples);
                                  var output = event.outputBuffer.getChannelData(0);
                                    for (var i = 0; i < output.length; i++) {
                                      output[i] = samples[i];
                                    }

                           }
};

audioNode.connect(audioContext.destination);
于 2013-10-27T04:55:07.373 に答える
0

audioContext.currentTime問題は、合計バッファ期間に基づいてスケジュールを設定していることだと考えてください。しかし、問題は、それcurrentTimeが移動するターゲットであることです。すべてのタイミングの基礎となる一貫したアンカーが必要です。

あなたがおそらくやりたいことは、最初にプレイを開始するとき、言ってvar AudioStart = audioContext.currentTime、それからあなたが今までのようにそれに追加し続けることです. 次に、再生をスケジュールするだけsource.start(AudioStart);です。

于 2013-06-17T20:54:52.997 に答える