swharden/FftSharp

How to read audio values from a WAV file

Closed this issue · 2 comments

Hi,

Could you please let me know how you create audio sample data using the below parameters as you mentioned. I ma trying to do it but it's a failure to process the data.

These data simulate a sample of audio with the following parameters: * sample rate: 48 kHz * points: 512 (2^9) * offset: 0.1 (above zero) * tone: 2 kHz (amplitude 2) * tone: 10 kHz (amplitude 10) * tone: 20 kHz (amplitude .5)

Please provide some guidelines.

Thank you
D

Below is the code that converting the ".wav" data to the sample data and passing to the algorithm but it's not working.

Please help me to run the application with any type of sound file.

Approach 1

static Double[] SampleData1( string filename )
{
 // L = R = null;
  double[] asFloat = null;

  try {
           using (FileStream fs = File.Open(filename,FileMode.Open))
           {
                  BinaryReader reader = new BinaryReader(fs);

                  // chunk 0
                  int chunkID       = reader.ReadInt32();
                  int fileSize      = reader.ReadInt32();
                  int riffType      = reader.ReadInt32();


              // chunk 1
              int fmtID         = reader.ReadInt32();
              int fmtSize       = reader.ReadInt32(); // bytes for this chunk (expect 16 or 18)

              // 16 bytes coming...
              int fmtCode       = reader.ReadInt16();
              int channels      = reader.ReadInt16();
              int sampleRate    = reader.ReadInt32();
              int byteRate      = reader.ReadInt32();
              int fmtBlockAlign = reader.ReadInt16();
              int bitDepth      = reader.ReadInt16();

              if (fmtSize == 18)
              {
                  // Read any extra values
                  int fmtExtraSize = reader.ReadInt16();
                  reader.ReadBytes(fmtExtraSize);
              }

              // chunk 2
              int dataID = reader.ReadInt32();
              int bytes = reader.ReadInt32();

              // DATA!
              byte[] byteArray = reader.ReadBytes(bytes);

              int bytesForSamp = bitDepth/8;
              int nValues = bytes / bytesForSamp;


  
              switch( bitDepth ) {
                  case 64:
                      double[] 
                          asDouble = new double[nValues];  
                      Buffer.BlockCopy(byteArray, 0, asDouble, 0, bytes);
                      asFloat = Array.ConvertAll( asDouble, e => (double)e );
                      break;
                  case 32:
                      asFloat = new double[nValues];   
                      Buffer.BlockCopy(byteArray, 0, asFloat, 0, bytes);
                      break;
                  case 16:
                      Int16 [] 
                          asInt16 = new Int16[nValues];   
                      Buffer.BlockCopy(byteArray, 0, asInt16, 0, bytes);
                      asFloat = Array.ConvertAll( asInt16, e => e / (double)(Int16.MaxValue+1) );
                      break;
                  default:
                      return null;
              }
          
                      /*
              switch( channels ) {
              case 1:
                  L = asFloat;
                  R = null;
                  return true;
              case 2:
                  // de-interleave
                  int nSamps = nValues / 2;
                  L = new float[nSamps];
                  R = new float[nSamps];
                  for( int s=0, v=0; s<nSamps; s++ ) {
                      L[s] = asFloat[v++];
                      R[s] = asFloat[v++];
                  }
                  return true;
              default:
                  return false;
              }*/
           }
  }
  catch {
          //Debug.Log( "...Failed to load: " + filename );
          return null;
  }

   return asFloat;
}

Approach 2

static Double[] SampleData()
{
         
          BinaryReader reader = new BinaryReader(File.Open(@"../../../output/abc.wav", FileMode.Open));
          //Read the wave file header from the buffer. 

          int chunkID = reader.ReadInt32();
          int fileSize = reader.ReadInt32();
          int riffType = reader.ReadInt32();
          int fmtID = reader.ReadInt32();
          int fmtSize = reader.ReadInt32();
          int fmtCode = reader.ReadInt16();
          int channels = reader.ReadInt16();
          int sampleRate = reader.ReadInt32();
          int fmtAvgBPS = reader.ReadInt32();
          int fmtBlockAlign = reader.ReadInt16();
          int bitDepth = reader.ReadInt16();

          if (fmtSize == 18)
          {
              // Read any extra values
              int fmtExtraSize = reader.ReadInt16();
              reader.ReadBytes(fmtExtraSize);
          }

          int dataID = reader.ReadInt32();
          int dataSize = reader.ReadInt32();


          // Store the audio data of the wave file to a byte array. 

          byte[] byteArray = reader.ReadBytes(dataSize);
          /*    for (int i = 0; i < byteArray.Length; i++) {
                  Console.Write(byteArray[i] + " ");
              }*/

          byte[] data = byteArray;
          double[] arrRe = new double[data.Length];
          for (int i = 0; i < arrRe.Length; i++)
          {
              arrRe[i] = data[i] / 32768.0;
          }
          double[] arrI = new double[data.Length];
          for (int i = 0; i < arrRe.Length; i++)
          {
              arrI[i] = 0;
          }

  return arrRe;
}

Hi @dhanajik, sorry it took me so long to respond to this.

I recommend against reading bytes from the wave file. Instead use a library which has already solved this problem to read the audio data. NAudio is on NuGet (https://www.nuget.org/packages/NAudio) and has extensive support for various file formats.

(double[] audio, int sampleRate) ReadWAV(string filePath, double multiplier = 16_000)
{
    using var afr = new NAudio.Wave.AudioFileReader(filePath);
    int sampleRate = afr.WaveFormat.SampleRate;
    int sampleCount = (int)(afr.Length / afr.WaveFormat.BitsPerSample / 8);
    int channelCount = afr.WaveFormat.Channels;
    var audio = new List<double>(sampleCount);
    var buffer = new float[sampleRate * channelCount];
    int samplesRead = 0;
    while ((samplesRead = afr.Read(buffer, 0, buffer.Length)) > 0)
        audio.AddRange(buffer.Take(samplesRead).Select(x => x * multiplier));
    return (audio.ToArray(), sampleRate);
}