Преобразование необработанных байтов в float [] - PullRequest
3 голосов
/ 20 февраля 2011

У меня есть этот код для преобразования 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,
}

Но это возвращает NaN (не число) после преобразования в число с плавающей запятой.В чем может быть проблема?Существуют ли другие способы конвертации byte[] в float[]?Я уверен, что значения, считанные в буфер, являются правильными, поскольку я сравнил их с другой моей программой (которая выполняет усиление для файла .wav).

Ответы [ 5 ]

4 голосов
/ 20 февраля 2011

Если проблема заключается в порядке байтов, вы должны проверить значение BitConverter.IsLittleEndian, чтобы определить, нужно ли инвертировать байты:

2 голосов
/ 20 февраля 2011

Проблема не в том, что 255 в показателе степени представляет NaN (см. Википедия в разделе экспоненты), поэтому вы должны получить NaN.Попробуйте заменить последние 255 на что-то другое ...

1 голос
/ 20 февраля 2011

Я предполагаю, что ваш байт [] не содержит двоичного представления чисел с плавающей запятой, но представляет собой последовательность Int8 с или Int16 с.Приведенные вами примеры не похожи на аудиосэмплы, основанные на числах с плавающей запятой (ни NaN, ни -2.41E + 24 не находятся в диапазоне от -1 до 1. Хотя некоторые новые форматы аудио могут поддерживать операции с плавающей запятой вне этого диапазона, традиционно аудиоданные состоят из подписанных8 или 16-битные целочисленные выборки.

Еще одна вещь, о которой вам нужно знать, это то, что часто различные каналы чередуются. Например, он может содержать первую выборку для левого, затем для правого канала, а затемвторой сэмпл для обоих ... Так что вам нужно разделить каналы при разборе.

Также возможно, но редко, что сэмплы не подписаны. В этом случае вам нужно удалить смещение из функций преобразования.

Итак, сначала вам нужно проанализировать текущую позицию в байтовом массиве в Int8 / 16, а затем преобразовать это целое число в число с плавающей точкой в ​​диапазоне от -1 до 1.

Если форматВы можете использовать BitConverter с прямым порядком байтов.Другая возможность, которая работает с обоими порядками байтов, это получить два байтаи объединяя их со сдвигом.Я не помню, встречается ли маленький или большой порядок байтов.Поэтому вам нужно попробовать это самостоятельно.

Это можно сделать с помощью функций, подобных следующим (я их не проверял):

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

float Int16ToFloat(Int16 i)
{
  return ((i-Int16.MinValue)*(1f/0xFFFF))-0.5f;
}
1 голос
/ 20 февраля 2011

Если это порядковый номер, который является неправильным (вы читаете большие порядковые числа), попробуйте это (знайте, что они «небезопасны», поэтому вы должны проверить флаг unsafe в свойствах вашего проекта)

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;
}
0 голосов
/ 20 февраля 2011

Зависит от того, как вы хотите преобразовать байты в число с плавающей запятой.Начните с попытки определить, что на самом деле хранится в байтовом массиве.Возможно, есть спецификация формата файла?Другие преобразования в вашем коде?

В случае, если каждый байт должен быть преобразован в число с плавающей запятой между 0 и 255:

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

Если массив байтов содержит двоичное представление чисел с плавающей запятой, существует несколькопредставление, и если представление, хранящееся в вашем файле, не соответствует стандартному представлению с плавающей запятой c # ( IEEE 754 ), произойдут странные вещи, подобные этому.

...