This project has moved. For the latest updates, please go here.

32-bit float and WaveFileReader performance

Jun 23, 2010 at 1:43 AM
Edited Jun 23, 2010 at 3:18 AM

Hi, first up Mark I just wanted to say thank you for such a brilliant library. It's extremely well designed and just as extremely generous for you to publish it for public use, so thank you.

I've recently been using NAudio to load and provide audio data as 32-bit float. I've been using the WaveFileReader to open a wave file, then the overloaded public int Read(float[][] buffer, int samples) method to provide me with an n-channel 32-bit float nested array. This works as I would expect it to, aside from in its performance. A 13 second mono wave file is taking almost as long to read with the provided method, which I find very surprising. I wrote a comparison routine (below) and the performance is around 140ms for the same file.

I'm wondering whether I'm completely misusing the WaveFileReader in this way... is there another method I should be using to grab 16-bit wav data and converting it to 32-bit float? I've seen the WaveChannel32 class, but the only way of getting data out of that seems to be through the Sample event.

Thanks Mark,


--- SNIP ---


      const int SamplesToRead = 256;
      using (WaveFileReader reader = new WaveFileReader(@"X:\test.wav"))
        int samplesRead;
        int blockAlign = reader.WaveFormat.BlockAlign;
        int channels = reader.WaveFormat.Channels;
        float[][] buffer = new float[channels][];
        float[] tempBuffer = new float[SamplesToRead];
        byte[] rawData = new byte[SamplesToRead * blockAlign];
        short[] shortData = new short[SamplesToRead];
        int size;
        TimeSpan time2 = Time(() =>
                                  while ((samplesRead = reader.Read(buffer, SamplesToRead)) > 0)
                                    samplePos2 += samplesRead;
        int samplePos2 = samplesRead = 0;
        reader.Seek(0, SeekOrigin.Begin);
        TimeSpan time = Time(() =>
                                 int samplePos = 0;
                                 while ((samplesRead = reader.Read(rawData, 0, SamplesToRead)) > 0)
                                   samplePos += samplesRead;
                                   Buffer.BlockCopy(rawData, 0, shortData, 0, SamplesToRead);
                                   SampleConverter.Convert(shortData, tempBuffer);
                                   size = SampleConverter.DeInterleave(tempBuffer, ref buffer);


Jul 12, 2010 at 9:58 AM

the method you are using is very old and obsolete

I would suggest using the WaveChannel32 class, use the Read method combined with a WaveBuffer to allow you to "cast" easily from Byte[] to float[] (samples will be interleaved left, right)