This project has moved and is read-only. For the latest updates, please go here.

Scrolling Waveform WPF C#

Jan 18, 2016 at 7:10 PM
Hi All,

I'm a hobbyist coder, learning what I can as I trundle along.

I been trying to code a music player for some time now and keep hitting this impasse and restarting the project through frustration.

I want to display a zoomed in scrolling waveform as an audio file plays. I have tried a few options but only one seems the right way to do it but I can't code it. In my minds eye I need to get a portion of the samples that would be displayed on the screen and draw the lines to show the peaks. I have tried this in a DispatcherTimer and try and grab a number of samples based on the current position in the MediaFoundationReader and the size of the container.

This does do something but the audio drops out every time the timer fires and the image doesn't draw completely. I think it has something to do with the fact I am reading in the whole file every time.

Any help would be very much appreciated.

Here is the timer code.
        string TrackFileName;
        DispatcherTimer timer = new DispatcherTimer();
        MediaFoundationReader NewAudioreader;
        WaveOut NewWaveOut;
        WriteableBitmap FullWaveForm;
        WriteableBitmap ZoomWaveForm;
        void timer_Tick(object sender, EventArgs e)
        {

            
            ZoomWaveForm.Clear();

            long samplesRequired = (long)(NewAudioreader.Length / FullWaveForm.Width);
            long trackStartPos = NewAudioreader.Position;

            //*** I think this is my problem as I read the whole file into the reader.***
            using (var reader = new AudioFileReader(TrackFileName))
            {
                reader.Position = trackStartPos;
                var samples = samplesRequired / (reader.WaveFormat.Channels * reader.WaveFormat.BitsPerSample);
                var samplesPerPixel = (int)(samplesRequired / ZoomWaveForm.Width);
                var max = 0.0f;
                var batch = (int)samplesPerPixel;
                var mid = ZoomWaveForm.Height / 2;
                var yScale = ZoomWaveForm.Height / 2;
                float[] buffer = new float[samplesPerPixel];
                int read;
                var xPos = 0;
                while ((read = reader.Read(buffer, 0, batch)) == batch)
                {
                    for (int n = 0; n < read; n = n + 2)
                    {
                        max = Math.Max(Math.Abs(buffer[n]), max);
                    }
                    ZoomWaveForm.DrawLineAa(xPos, (int)(mid + (max * yScale)), xPos, (int)(mid - (max * yScale)), Colors.Orange, 1);
                    max = 0;
                    xPos++;
                    if (reader.Position >= (NewAudioreader.Position) + samplesRequired)
                    {
                        break;
                    }
                }
            }

           // WPF <Image> container
            imgZoomWaveForm.Source = ZoomWaveForm;
        }