I want to use NAudio to extract the peak values of wav audio files like the audiowaveform library provides. Which is an array of short values like:
{
"version": 2,
"channels": 2,
"sample_rate": 48000,
"samples_per_pixel": 512,
"bits": 8,
"length": 3,
"data": [-65,63,-66,64,-40,41,-39,45,-55,43,-55,44]
}
https://github.com/bbc/audiowaveform/blob/master/doc/DataFormat.md
I saw that NAudio has a built-in WaveformRenderer that outputs png images, but I just need the raw peak data. Built-in NAudio classes like MaxPeakProvider (which is initialized with waveReader.ToSampleProvider()) etc works with floats, I need them as short values. Is it possible?
Edit after @Blindy's response
I have this piece of code, converting peak data to shorts, but it produces slightly wrong values when comparing with the output of audiowaveform. What might be the problem? I guess there is a data type conversion or rounding error?
var waveReader = new WaveFileReader(openFileDialog1.FileName);
var wave = new WaveChannel32(waveReader);
var peakProvider = new MaxPeakProvider();
int bytesPerSample = (waveReader.WaveFormat.BitsPerSample / 8);
var samples = waveReader.Length / bytesPerSample;
int pixelsPerPeak = 1;
int spacerPixels = 0;
var samplesPerPixel = 32;
var stepSize = pixelsPerPeak + spacerPixels;
peakProvider.Init(waveReader.ToSampleProvider(), samplesPerPixel * stepSize);
List<short> resultValuesAsShort = new List<short>();
List<float> resultValuesAsFloat= new List<float>();
PeakInfo currentPeak = null;
for (int i = 0; i < samples / samplesPerPixel; i++)
{
currentPeak = peakProvider.GetNextPeak();
resultValuesAsShort.Add((short)(currentPeak.Min * short.MaxValue));
resultValuesAsShort.Add((short)(currentPeak.Max * short.MaxValue));
//resultValuesAsFloat.Add(currentPeak.Min);
//resultValuesAsFloat.Add(currentPeak.Max);
}
Here are the results comparison:
Edit2: Examining further, I noticed that it is generating quite different results for the latter values than audiowaveform library and I don't have any idea for the reason:
NAudio in general works with floats, it's just how it was designed. To get the 2-byte short representation, multiply each
float
byshort.MaxValue
(the floats are in the[-1..1]
range).