Analyzing wav and drawing a graph

半腔热情 提交于 2019-12-02 22:39:19

Your question is about two different visualisations of audio. To draw the waveform, the code you posted is close to being ready to draw from, but you are adding a single entry per sample to your list. Since audio is often 44100 samples per second, the waveform for a 3 minute song would require almost 8 million pixels across. So what you do is batch them up. For every say 4410 pixels (i.e. 100ms), find the one with the highest and lowest values, and then use that to draw the line. in fact, you can usually get away with just finding the max Abs value, and drawing a symetrical waveform.

Here is some code to draw a basic WaveForm of an audio file in WPF, using NAudio for easier access to the sample values (it can do WAV or MP3 files). I haven't included any splitting out of left and right channels, but that should be fairly easy to add:

var window = new Window();
var canvas = new Canvas();
using(var reader = new AudioFileReader(file))
{
    var samples = reader.Length / (reader.WaveFormat.Channels * reader.WaveFormat.BitsPerSample / 8);
    var f = 0.0f;
    var max = 0.0f;
    // waveform will be a maximum of 4000 pixels wide:
    var batch = (int)Math.Max(40, samples / 4000);
    var mid = 100;
    var yScale = 100;
    float[] buffer = new float[batch];
    int read;
    var xPos = 0;
    while((read = reader.Read(buffer,0,batch)) == batch)
    {
        for(int n = 0; n < read; n++)
        {
            max = Math.Max(Math.Abs(buffer[n]), max);
        }
        var line = new Line();
        line.X1 = xPos;
        line.X2 = xPos;
        line.Y1 = mid + (max * yScale); 
        line.Y2 = mid - (max * yScale);
        line.StrokeThickness = 1;
        line.Stroke = Brushes.DarkGray;
        canvas.Children.Add(line);
        max = 0;    
        xPos++;
    }
    canvas.Width = xPos;
    canvas.Height = mid * 2;
}
window.Height = 260;
var scrollViewer = new ScrollViewer();
scrollViewer.Content = canvas;
scrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
window.Content = scrollViewer;
window.ShowDialog();

The second visualisation is sometimes called a spectogram or a spectrum analyser. It does not represent 1 sample, but represents the frequencies present in a block of samples. To get at this information you need to pass your samples through a Fast Fourier Transform (FFT). Usually you pass through blocks of 1024 samples (it should be a power of 2). Unforunately FFTs can be tricky to work with if you are new to DSP, as there are several things you need to learn how to do:

  • apply a windowing function
  • get your audio into the right input format (many FFTs expect input as complex numbers)
  • work out which bin numbers correspond to which frequency,
  • find the magnitude of each bin and convert it to a decibel scale.

You should be able to find further information on each of those topics here on StackOverflow. I've written a bit about how you can use FFT in C# in this article.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!