5

Java の WAV ファイルでいくつかの問題に直面しています。

WAV 形式: PCM_SIGNED 44100.0 Hz、24 ビット、ステレオ、6 バイト/フレーム、リトルエンディアン。

  • 問題なく WAV データをバイト配列に抽出しました。
  • バイト配列を double 配列に変換しようとしていますが、一部の double にはNaN値が含まれています。

コード:

ByteBuffer byteBuffer = ByteBuffer.wrap(byteArray);
double[] doubles = new double[byteArray.length / 8];
for (int i = 0; i < doubles.length; i++) {
    doubles[i] = byteBuffer.getDouble(i * 8);
}

16/24/32 ビット、モノラル/ステレオであるという事実は、私を混乱させます。

double[]をFFT アルゴリズムに渡して、オーディオ周波数を取得するつもりです。

4

3 に答える 3

4

WAV 形式は 24 ビットですが、ダブルは 64 ビットを使用します。そのため、wav に格納される量を 2 倍にすることはできません。フレームとチャネルごとに 1 つの 24 ビット符号付き整数があり、これは上記の 6 バイトに相当します。

次のようなことができます。

private static double readDouble(ByteBuffer buf) {
  int v = (byteBuffer.get() & 0xff);
  v |= (byteBuffer.get() & 0xff) << 8;
  v |= byteBuffer.get() << 16;
  return (double)v;
}

このメソッドは、左チャネルに対して 1 回、右チャネルに対して 1 回呼び出します。正しい順序はわかりませんが、最初に左に行ったと思います。リトルエンディアンが示すように、バイトは最下位から最上位へと読み取られます。0xff符号なしとして扱うために、下位 2 バイトは でマスクされます。最上位バイトは、符号付き 24 ビット整数の符号を含むため、符号付きとして扱われます。

ByteBuffer配列を操作する場合、たとえば次のように、なしで実行できます。

double[] doubles = new double[byteArray.length / 3];
for (int i = 0, j = 0; i != doubles.length; ++i, j += 3) {
  doubles[i] = (double)( (byteArray[j  ] & 0xff) | 
                        ((byteArray[j+1] & 0xff) <<  8) |
                        ( byteArray[j+2]         << 16));
}

インターリーブされた両方のチャネルのサンプルを取得するため、後でこれらを分離することをお勧めします。

モノラルの場合、2 つのチャンネルがインターリーブされるのではなく、1 回だけインターリーブされます。16bitなら使えますbyteBuffer.getShort()、32bitなら使えますbyteBuffer.getInt()。しかし、24ビットは計算に一般的に使用されていないため、ByteBufferこれに対する方法はありません. 署名されていないサンプルがある場合は、すべての符号をマスクして結果を相殺する必要がありますが、署名されていない WAV はあまり一般的ではないと思います。

于 2013-03-20T22:19:59.387 に答える
0

DSP の浮動小数点型の場合、通常は [0, 1] または [0, 1) の範囲の値が優先されるため、各要素を 2 24 -1 で除算する必要があります。上記のMvGの答えが好きですが、いくつかの変更があります

int t = ((byteArray[j  ] & 0xff) <<  0) |
        ((byteArray[j+1] & 0xff) <<  8) |
         (byteArray[j+2]         << 16);
return t/double(0xFFFFFF);

しかし、実際にはデータ処理の目的doubleでスペースと CPU を浪費しています。代わりに 32 ビット int に変換するかfloat、同じ精度 (24 ビット) でより大きな範囲を持つものに変換することをお勧めします。実際、オーディオまたはビデオ処理を行う場合、32 ビットの int または float がデータ チャネルの最大の型です。

最後に、マルチスレッドとSIMDを利用して変換を加速できます

于 2013-09-25T04:18:03.653 に答える