如何渲染音频波形?

  1. 有没有与音频/编程相关的堆栈交换站点?
  2. 我正试图在WinForms中制作波形
  3. 我应该使用什么算法?

例如,如果每个像素有200个样本(垂直线),我应该从200个样本的那部分中绘制最低和最高样本吗? 或者我应该绘制低和高样本的平均值? 也许两者都有不同的颜色?

  1. 试试dsp.stackexchange.com

  2. 每像素200个样本,您可以尝试几种方法。 无论你做什么,它通常最适合绘制0和0以上的每条垂直线,即。 单独处理正负样本值。 可能最简单的是计算RMS。 在如此低的分辨率下,峰值可能会给您一个误导性的波形表示。

这将帮助您使用C#中的nAudio从音频文件生成波形…

using NAudio.Wave; using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; public partial class test : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { string strPath = Server.MapPath("audio/060.mp3"); string SongID = "2"; byte[] bytes = File.ReadAllBytes(strPath); WriteToFile(SongID,strPath, bytes); Response.Redirect("Main.aspx"); } private void WriteToFile(string SongID, string strPath, byte[] Buffer) { try { int samplesPerPixel = 128; long startPosition = 0; //FileStream newFile = new FileStream(GeneralUtils.Get_SongFilePath() + "/" + strPath, FileMode.Create); float[] data = FloatArrayFromByteArray(Buffer); Bitmap bmp = new Bitmap(1170, 200); int BORDER_WIDTH = 5; int width = bmp.Width - (2 * BORDER_WIDTH); int height = bmp.Height - (2 * BORDER_WIDTH); NAudio.Wave.Mp3FileReader reader = new NAudio.Wave.Mp3FileReader(strPath, wf => new NAudio.FileFormats.Mp3.DmoMp3FrameDecompressor(wf)); NAudio.Wave.WaveChannel32 channelStream = new NAudio.Wave.WaveChannel32(reader); int bytesPerSample = (reader.WaveFormat.BitsPerSample / 8) * channelStream.WaveFormat.Channels; using (Graphics g = Graphics.FromImage(bmp)) { g.Clear(Color.White); Pen pen1 = new Pen(Color.Gray); int size = data.Length; string hexValue1 = "#009adf"; Color colour1 = System.Drawing.ColorTranslator.FromHtml(hexValue1); pen1.Color = colour1; Stream wavestream = new NAudio.Wave.Mp3FileReader(strPath, wf => new NAudio.FileFormats.Mp3.DmoMp3FrameDecompressor(wf)); wavestream.Position = 0; int bytesRead1; byte[] waveData1 = new byte[samplesPerPixel * bytesPerSample]; wavestream.Position = startPosition + (width * bytesPerSample * samplesPerPixel); for (float x = 0; x < width; x++) { short low = 0; short high = 0; bytesRead1 = wavestream.Read(waveData1, 0, samplesPerPixel * bytesPerSample); if (bytesRead1 == 0) break; for (int n = 0; n < bytesRead1; n += 2) { short sample = BitConverter.ToInt16(waveData1, n); if (sample < low) low = sample; if (sample > high) high = sample; } float lowPercent = ((((float)low) - short.MinValue) / ushort.MaxValue); float highPercent = ((((float)high) - short.MinValue) / ushort.MaxValue); float lowValue = height * lowPercent; float highValue = height * highPercent; g.DrawLine(pen1, x, lowValue, x, highValue); } } string filename = Server.MapPath("image/060.png"); bmp.Save(filename); bmp.Dispose(); } catch (Exception e) { } } public float[] FloatArrayFromStream(System.IO.MemoryStream stream) { return FloatArrayFromByteArray(stream.GetBuffer()); } public float[] FloatArrayFromByteArray(byte[] input) { float[] output = new float[input.Length / 4]; for (int i = 0; i < output.Length; i++) { output[i] = BitConverter.ToSingle(input, i * 4); } return output; } } 

您可以从代码项目中使用AudioControl 。

并看到这一个: 在C#中生成各种音频波形

如果最初实现您的代码,这些项目可能对您有用:

  • 高速function丰富,和易于使用,图表
  • 还有这个

任何人遇到这个:

您可以将每个像素的样本视为缩放级别,在更高级别(缩小更多),您可能希望根据性能原因对其进行子采样。

您很可能需要一个适合屏幕的固定宽度来绘制并使用虚拟滚动(因此您可能没有数百万像素的绘制区域)。

您可以通过迭代音频数据来计算每个像素的值:skip(滚动位置*每个像素的样本数)+(像素*每个像素的样本数)获取每个像素的样本。 这允许高性能无限缩放和滚动,因为您只读取并绘制最小量以填充视图。 使用每像素的音频数据长度/样本计算滚动宽度。

音频样本通常以两种方式之一显示,即样本范围的峰值或rms值。 有效值的计算方法是,对样本范围内所有值的平方求和,除以样本长度,如果平方根有效值(rms将略高于平均值,并且是感知响度的一个很好的度量)

您可以通过多种方式提高性能,例如增加子采样(导致细节丢失),限制滚动并使绘制请求可取消,以便在渲染之前进行新的滚动触发。