Reputation: 81
I'm task with analyzing a wav audio file (filtering, FFT, etc.) in C#. Currently I'm stuck trying to properly convert the bytes to double in order to plot the audio signal of the waveform with scottplot, I have tried using Naudio library but didn't find any success with reading the audio data and plotting it, ended up corrupting my project. the code below is where I read the wav byte into an array and convert it to a double array to plot the signal using scottplot which is not working, I'm using windows forms app(.NET core)
byte[] wavData = File.ReadAllBytes(@"C:\Users\me\Documents\africa-song.wav");
double[] values = new double[wavData.Length / 8];
Buffer.BlockCopy(wavData, 0, values, 0, values.Length * 8);
formsPlot1.plt.PlotSignal(values, 44100);
if there's a better library I can use or a work around to achieve this, would be really appreciated
Upvotes: 1
Views: 3667
Reputation: 146
You could read bytes right out of the WAV file, but this isn't always easy because different WAV files have differently sized headers so you don't always know where the first data byte is located. You also have to read and interpret the header to learn what the data format is (number of bytes per sample, whether it's floating point or not, etc) and how many channels there are.
A simpler way to read values from a WAV file is using NAudio. I use this method to convert values from any WAV file data into a double array:
static (double[] audio, int sampleRate) ReadWav(string filePath)
{
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 => (double)x));
return (audio.ToArray(), sampleRate);
}
Unlike the built-in graphing libraries, ScottPlot allows mouse-interactive pan and zoom for datasets with millions of points, so even if your audio file is an hour long you can easily display it. It looks like you got pretty close with your original code!
(double[] audio, int sampleRate) = ReadWav("demo.wav");
formsPlot1.plt.PlotSignal(audio, sampleRate);
formsPlot1.plt.Title("WAV File Data");
formsPlot1.plt.XLabel("Time (seconds)");
formsPlot1.plt.YLabel("Audio Value");
formsPlot1.plt.AxisAuto(0);
formsPlot1.Render();
Upvotes: 2