The fastest way in C # to read a block of bytes from a file and convert to float []

I need a fast way in C # to convert / cast a byte array encoding one short (int16) value for 2 bytes into a float representation, as quickly as possible. The performance bottleneck was the method:

samples[sample] = (float)binraryReader.readInt16();

(a huge number of IO calls, so I had to convert to reading a block)

Basically I have a file containing a block of audio samples (~ 100-600 mb) of type short, and then, since I can only block the read byte set, I need to build a short one from each pair of bytes, and then convert this to short to float, since I need to store samples in the form of floats.

my current code looks something like this (about 2 performance improvements over the above method, but longer):

    float[] samples = new float[_samplesPerSplit];
    byte[] data = new byte[_samplesPerSplit * 2];

    for (int c = 0; c < numberOfChunks; c += 1)
    {
        br.Read(data, 0, _samplesPerSplit * 2);

        fixed (byte* bytePtr = data)
        {
            fixed (float* floatPtr = samples)
            {
                byte* rPos = bytePtr;
                float* fPos = floatPtr;

                byte byte0;
                byte byte1;
                short sampleShort;

                for (int sample = 0; sample < _samplesPerSplit; sample += 1)
                {
                    byte1 = *(rPos++);
                    byte0 = *(rPos++);

                    // I occasionaly get 
                    //          "Negating  the minimum value of a 
                    //          twos complement number is invalid" 
                    // error if i skip this check, but it slows down 
                    // whole process even more
                    if (byte0 == 128 && byte1 == 0)
                    {
                        sampleShort = 32767;
                    }
                    else
                    {
                        sampleShort = (short)(((ushort)(byte0)) << 8 | ((ushort)(byte1)));
                    }

                    *(fPos++) = (float)sampleShort;
                }
            }
        }
        ProcessChunk(samples);
    }
+5
source share
2 answers

you can try the following:

    fixed (byte* bytePtr = data)
    {
        fixed (float* floatPtr = samples)
        {
            short* rPos = (short*)bytePtr;
            float* fPos = floatPtr;

            for (int sample = 0; sample < _samplesPerSplit; sample += 1)
            {
                *fPos++ = (float)(*rPos++);
            }

        }
    }
+1
source

You tried to use Bitwise Operation

I don’t know much about them, but from the Wiki and MY previous SO here I found out about this:

Bitwise operations are usually significantly faster than multiplication and division operations.

0
source

All Articles