4

に変換するためのこのコードがありbyte[]ますfloat[]

public float[] ConvertByteToFloat(byte[] array)
{
    float[] floatArr = new float[array.Length / sizeof(float)];
    int index = 0;
    for (int i = 0; i < floatArr.Length; i++)
    {
        floatArr[i] = BitConverter.ToSingle(array, index);
        index += sizeof(float);
    }
    return floatArr;
}

問題は、私は通常NaN結果を得るということです!なぜこれが必要ですか?にデータがあるかどうかを確認しましたがbyte[]、データは問題ないようです。それが役立つ場合、値の例は次のとおりです。

new byte[] {
    231,
    255,
    235,
    255,
}

ただし、NaNfloatに変換すると、これは(数値ではなく)戻ります。何が問題なのですか?byte[]に変換する他のより良い方法はありfloat[]ますか?バッファに読み込まれた値は、他のプログラム(.wavファイルの増幅を実行する)と比較したので正しいと確信しています。

4

5 に答える 5

4

エンディアンが問題である場合は、の値をチェックしてBitConverter.IsLittleEndian、バイトを逆にする必要があるかどうかを判断する必要があります。

public static float[] ConvertByteToFloat(byte[] array) {
  float[] floatArr = new float[array.Length / 4];
  for (int i = 0; i < floatArr.Length; i++) {
    if (BitConverter.IsLittleEndian) {
      Array.Reverse(array, i * 4, 4);
    }
    floatArr[i] = BitConverter.ToSingle(array, i * 4);
  }
  return floatArr;
}
于 2011-02-20T11:30:48.723 に答える
2

指数の255がNaNを表すという問題ではないので(指数セクションのウィキペディアを参照)、NaNを取得する必要があります。最後の255を別のものに変更してみてください...

于 2011-02-20T11:26:42.300 に答える
1

エンディアンが間違っている場合(ビッグエンディアンの数値を読み取っている場合)、これらを試してください(これらは「安全ではない」ため、プロジェクトのプロパティで安全でないフラグを確認する必要があることに注意してください)

public static unsafe int ToInt32(byte[] value, int startIndex)
{
    fixed (byte* numRef = &value[startIndex])
    {
        var num = (uint)((numRef[0] << 0x18) | (numRef[1] << 0x10) | (numRef[2] << 0x8) | numRef[3]);
        return (int)num;
    }
}

public static unsafe float ToSingle(byte[] value, int startIndex)
{
    int val = ToInt32(value, startIndex);
    return *(float*)&val;
}
于 2011-02-20T11:28:15.107 に答える
1

byte []に​​は、floatのバイナリ表現は含まれていませんが、Int8sまたはInt16sのシーケンスが含まれていると思います。投稿した例は、floatに基づくオーディオサンプルのようには見えません(NaNも-2.41E + 24も-1から1の範囲ではありません)一部の新しいオーディオ形式はその範囲外のfloatをサポートする場合がありますが、従来のオーディオデータは署名付きで構成されています8ビットまたは16ビットの整数サンプル。

注意する必要があるもう1つのことは、多くの場合、異なるチャネルがインターリーブされていることです。たとえば、左側の最初のサンプル、次に右側のチャネル、次に両方の2番目のサンプルを含めることができます...したがって、解析中にチャネルを分離する必要があります。

可能ですが、サンプルが署名されていないことはまれです。この場合、変換関数からオフセットを削除する必要があります。

したがって、最初にバイト配列の現在の位置をInt8/16に解析する必要があります。次に、その整数を-1から1の範囲のfloatに変換します。

フォーマットがリトルエンディアンの場合は、BitConverterを使用できます。両方のエンディアンネスで機能するもう1つの可能性は、2バイトを手動で取得し、それらをビットシフトと組み合わせることです。リトルエンディアンとビッグエンディアンのどちらが一般的かは覚えていません。だからあなたはそれを自分で試す必要があります。

これは、次のような関数で実行できます(私はそれらをテストしませんでした):

float Int8ToFloat(Int8 i)
{
  return ((i-Int8.MinValue)*(1f/0xFF))-0.5f;
}

float Int16ToFloat(Int16 i)
{
  return ((i-Int16.MinValue)*(1f/0xFFFF))-0.5f;
}
于 2011-02-20T12:34:59.220 に答える
0

バイトをfloatに変換する方法によって異なります。バイト配列に実際に格納されているものを正確に特定することから始めます。おそらくファイル形式の仕様がありますか?コード内の他の変換?

各バイトを0から255の間のfloatに変換する必要がある場合:

public float[] ConvertByteToFloat(byte[] array)
{
    return array.Select(b => (float)b).ToArray();
}

バイト配列にfloatのバイナリ表現が含まれている場合、いくつかの表現があり、ファイルに格納されている表現がc#言語の標準浮動小数点表現(IEEE 754)と一致しない場合、このような奇妙なことが起こります。

于 2011-02-20T11:19:47.243 に答える