Finally figured it out. Thanks @MarkHeath for your comments and suggestions (and for creating the wonderful NAudio / NLayer libraries)!
The key is that WaveFloatTo16Provider
does not have a Length
attribute, so you cannot calculate the number of samples per pixel, so you need to have two loops. One that sequentially reads all the individual samples, and then another, which then groups the samples into pixels and calculates the maximum amplitude. The final loop then displays the values ββat the pixel position and draws them onto the image. If you don't need AutoFit
code, you can combine the second and third loops.
Bitmap bmp = new Bitmap(Width, Height); using (Graphics g = Graphics.FromImage(bmp)) { g.Clear(Color.White); Pen pen1 = new Pen(Color.Gray); string hexValue = "#" + sColor; Color colour1 = System.Drawing.ColorTranslator.FromHtml(hexValue); pen1.Color = colour1; int maxAmplitude = 0; short[,] dataArray = new short[Width, 2]; using (Mp3FileReader wavestreamFloat = new Mp3FileReader( new MemoryStream(new WebClient().DownloadData(URL)), new Mp3FileReader.FrameDecompressorBuilder( waveFormat => new NLayer.NAudioSupport.Mp3FrameDecompressorwaveFormat)))) { IWaveProvider stream16 = new WaveFloatTo16Provider(wavestreamFloat); int bytesPerSample = (stream16.WaveFormat.BitsPerSample / 8) * stream16.WaveFormat.Channels; int bytesRead = 0; byte[] buffer = new byte[8192]; List<short> rawDataArray = new List<short>(); do { bytesRead = stream16.Read(buffer, 0, buffer.Length); for (int n = 0; n < bytesRead; n += bytesPerSample) { short sample = BitConverter.ToInt16(buffer, n); rawDataArray.Add(sample); } } while (bytesRead != 0);
source share