Conversion de données d’octets brutes en données flottantes

J’ai ce code pour convertir un byte[] en 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; } 

Le problème, c’est que j’obtiens généralement un résultat NaN ! Pourquoi cela devrait-il être? J’ai vérifié s’il y avait des données dans l’ byte[] et les données semblent aller bien. Si cela vous aide, voici un exemple de valeurs:

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

Mais cela retourne NaN (pas un nombre) après la conversion en float. Quel pourrait être le problème? Existe-t-il d’autres moyens plus efficaces de convertir byte[] en float[] ? Je suis sûr que les valeurs lues dans la mémoire tampon sont correctes puisque je l’ai comparé à mon autre programme (qui effectue l’amplification pour un fichier .wav).

    Si le problème est BitConverter.IsLittleEndian , vous devez vérifier la valeur de BitConverter.IsLittleEndian pour déterminer si les octets doivent être inversés:

     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; } 

    Le problème n’est-il pas que le 255 dans l’exposant représente NaN (voir Wikipedia dans la section exposant), vous devriez donc obtenir un NaN. Essayez de changer le dernier 255 en quelque chose d’autre …

    Si c’est le caractère final qui est faux (vous lisez des nombres big endian), essayez-les (sachez qu’ils sont “dangereux”, vous devez donc cocher l’indicateur “dangereux” dans les propriétés de votre projet)

     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; } 

    Je suppose que votre octet [] ne contient pas la représentation binary de floats, mais soit une séquence de Int8 ou Int16 . Les exemples que vous avez publiés ne ressemblent pas à des échantillons audio basés sur float (ni NaN ni -2.41E + 24 ne sont compris entre -1 et 1. Bien que certains nouveaux formats audio puissent prendre en charge les float en dehors de cette plage, les données audio consistent traditionnellement en Échantillons entiers de 8 ou 16 bits.

    Vous devez également être conscient du fait que souvent, les différents canaux sont entrelacés. Par exemple, il pourrait contenir le premier échantillon pour le canal de gauche, puis pour le canal de droite, puis le deuxième échantillon pour les deux … Vous devez donc séparer les canaux lors de l’parsing.

    C’est également possible, mais peu commun que les échantillons ne soient pas signés. Dans ce cas, vous devez supprimer le décalage des fonctions de conversion.

    Donc, vous devez d’abord parsingr la position actuelle dans le tableau d’octets dans un Int8 / 16. Et ensuite, convertissez cet entier en un float compris entre -1 et 1.

    Si le format est little endian, vous pouvez utiliser BitConverter. Une autre possibilité qui fonctionne avec les deux endianités consiste à obtenir deux octets manuellement et à les combiner avec un décalage de bits. Je ne me souviens pas si petit ou grand endian est commun. Donc, vous devez essayer cela vous-même.

    Cela peut être fait avec les fonctions suivantes (je ne les ai pas testées):

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

    Cela dépend de la manière dont vous voulez convertir les octets en float. Commencez par essayer de localiser ce qui est réellement stocké dans le tableau d’octets. Peut-être il y a une spécification de format de fichier? D’autres transformations dans votre code?

    Dans le cas où chaque octet devrait être converti en un float compris entre 0 et 255:

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

    Si le tableau d’octets contient une représentation binary de floats, il existe plusieurs représentations et si la représentation stockée dans votre fichier ne correspond pas à la représentation à virgule flottante standard du langage c # ( IEEE 754 ), il se produira de telles choses étranges.