Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert 32 bit float audio to 16 bit byte array?

I am getting audio using the NAudio library which returns a 32 bit float[] of audio data. I'm trying to find a way to convert this to a 16 bit byte[] for playback.

private void sendData(float[] samples)
{
    Buffer.BlockCopy(samples, 0, byteArray, 0, samples.Length);
    byte[] encoded = codec.Encode(byteArray, 0, byteArray.Length);
    waveProvider.AddSamples(byteArray, 0, byteArray.Length);
    s.Send(encoded, SocketFlags.None);
}

The audio being sent to waveProvider is coming out static-y — I don't think I'm converting correctly. How can I convert to a byte array of 16 bit samples?

like image 794
user547794 Avatar asked Oct 22 '25 12:10

user547794


1 Answers

Buffer.BlockCopy copies a number of bytes, but you're passing it a number of elements. Since a float is 4 bytes and a byte is obviously 1, you're using a fourth of samples to fill up half of byteArray, leaving the rest untouched. That probably won't give you very good audio, to say the least.

What you'll need to do is convert from a floating-point value between −1 and 1 to a 16-bit integer value between −215 and 215−1. If we convert to shorts rather than bytes, it's rather simple:

shortSample = (short)Math.Floor(floatSample * 32767);

(If you know that floatSample will always be less than 1, you should multiply by 32,768 rather than 32,767.)
Of course, you want a byte array rather than a short array. Unfortunately, you've not given enough information for that last step. There's two things that you'll need to know: endianness and signedness. If it's unsigned, you'll need to convert that short to a ushort by adding 32,768. Then you need to split each short or ushort up into two bytes. Endianness determines the order, but you'll probably need to do some bit-shifting.

like image 76
icktoofay Avatar answered Oct 25 '25 02:10

icktoofay