Getting WAV samples in a array

Aug 29, 2011 at 1:03 PM
Edited Aug 29, 2011 at 1:04 PM

Hi,

For a project where I need to analyze audio (FFT, DTMF decoding, ...) I need to extract the samples from a WAV file.

What I exactly need is an array of double (or a C# List ...) so I can work on the samples.

More (or better!) I would like to convert the input WAV file so the format of the array is always the same (Let's consider 8kHz).

Here is what I already was able to do:

 

WaveFileReader wfr = new WaveFileReader(filename);
WaveStream ws = WaveFormatConversionStream.CreatePcmStream(wfr);

WaveStream blockAlignedStream = new BlockAlignReductionStream(ws);
WaveChannel32 waveChannel = new WaveChannel32(blockAlignedStream);

WaveFormat format = new WaveFormat(waveChannel.WaveFormat.SampleRate, waveChannel.WaveFormat.BitsPerSample, waveChannel.WaveFormat.Channels);
byte[] buffer1 = new byte[waveChannel.WaveFormat.SampleRate];

int bytesRead;
while (waveChannel.Position < waveChannel.Length)
{
    bytesRead = waveChannel.Read(buffer1, 0, waveChannel.WaveFormat.SampleRate);


    // ... there I'm lost !
} Them, now, how could I convert the bytes to the array of double?
Is there another class to do that?

Thanks for helping
Fred

Coordinator
Sep 22, 2011 at 3:52 PM

have a look at the code inside WaveChannel32 and you will see how it reads in the 16 bit audio and converts it to floats.

Mark

Sep 23, 2011 at 6:13 AM

Hello markheath,

Sorry, I was not really able to understand how to do that in your code.

However, I have finally found a solution; here it is, for those who might need it:

 

using (WaveFileReader wfr = new WaveFileReader(m_filename))
{
  using (WaveStream ws = WaveFormatConversionStream.CreatePcmStream(wfr))
  {
    using (WaveStream baStream = new BlockAlignReductionStream(ws))
    {
      WaveFormat format = new WaveFormat(baStream.WaveFormat.SampleRate, baStream.WaveFormat.BitsPerSample, baStream.WaveFormat.Channels);
      byte[] buffer1 = new byte[baStream.WaveFormat.BitsPerSample / 8];

      SampleRate = baStream.WaveFormat.SampleRate;
      wavFormat = baStream.WaveFormat;

      int bytesRead = 0;
      long previousPosition = 0;
      List<double> lst = new List<double>();
      double currentValue;
      double avg = 0;
      while (baStream.Position < baStream.Length)
      {
        bytesRead = baStream.Read(buffer1, 0, baStream.WaveFormat.BitsPerSample / 8);

        if (wfr.WaveFormat.Channels > 1 && rdbReadTrack2.Checked == true) // Use 2nd channel
          bytesRead = baStream.Read(buffer1, 0, baStream.WaveFormat.BitsPerSample / 8);

        if (baStream.WaveFormat.BitsPerSample / 8 > 1)
        {
          currentValue = 100.0 * BitConverter.ToInt16(buffer1, 0) / short.MaxValue;
        }
        else // Special case for 8 bit signal
        {
          currentValue = 100.0 * 255 * (buffer1[0] - 128) / short.MaxValue;
        }
        lst.Add(currentValue);
        avg += currentValue;

        if (wfr.WaveFormat.Channels > 1 && rdbReadTrack1.Checked == true) // Skip 2nd channel
          bytesRead = baStream.Read(buffer1, 0, baStream.WaveFormat.BitsPerSample / 8);
      }

      avg /= baStream.Length;

      // ... Now lst contain the data I need!
 } }
}

Best regards,

Fred