CustWaveViewer.cs

Download CustWaveViewer.cs File

using System; using System.Collections; using System.ComponentModel; using System.Drawing; using System.Data; using System.Windows.Forms; using NAudio.Wave; namespace NAudio.Gui { /// Control for viewing waveforms public class CustWaveViewer : System.Windows.Forms.UserControl { public Color PenColor { get; set; } public float PenWidth { get; set; } public TimeSpan fromStart { get; set; } public TimeSpan fromEnd { get; set; } public Point startPoint { get; set; } public Point endPoint { get; set; } public void FitToScreen() { if (waveStream == null) return; DrawVertLine(startPoint.X); DrawVertLine(endPoint.X); int samples = (int)(waveStream.Length / bytesPerSample); startPosition = 0; SamplesPerPixel = samples / this.Width; startPoint = new Point(-1, -1); endPoint = new Point(-1, -1); } public void drawWavePosition(double wavX) { int x = (int)wavX; ControlPaint.DrawReversibleLine(PointToScreen(new Point(x, 0)), PointToScreen(new Point(x, Height)), Color.Black); } public double pixelPerMillisecond() { return (this.Width / waveStream.TotalTime.TotalMilliseconds); } public void CutSample(int leftSample, int rightSample) { fromStart = new TimeSpan(0, 0, 0, 0, (int)(leftSample * bytesPerSample / bytesPerMilliecond)); fromEnd = new TimeSpan(0, 0, 0, 0, (int)((totalBytes - rightSample * bytesPerSample) / bytesPerMilliecond)); } public void ZoomOut() { int samples = (int)(waveStream.Length / bytesPerSample); startPosition = 0; SamplesPerPixel = samples / this.Width; } private void DrawVertLine(int x) { ControlPaint.DrawReversibleLine(PointToScreen(new Point(x, 0)), PointToScreen(new Point(x, Height)), Color.Black); } protected override void OnResize(EventArgs e) { base.OnResize(e); FitToScreen(); } private Point mousePos, startPos; private bool mouseDrag = false; protected override void OnMouseDown(MouseEventArgs e) { if (waveStream == null) return; if(e.Button == System.Windows.Forms.MouseButtons.Left) { if (Math.Abs(e.X - startPoint.X) </= 1) // close to startpoint { mousePos = startPoint; startPoint = endPoint; endPoint = new Point(-1, -1); mouseDrag = true; } else if (Math.Abs(e.X - endPoint.X) </= 1) { mousePos = endPoint; mouseDrag = true; } else { if (startPoint.X != -1) DrawVertLine(startPoint.X); if (endPoint.X != -1) DrawVertLine(endPoint.X); startPoint = new Point(-1, -1); endPoint = new Point(-1, -1); startPos = e.Location; mousePos = new Point(-1, -1); //invalid point so we dont erase first line mouseDrag = true; startPoint = new Point(e.X, e.Y); DrawVertLine(e.X); } } base.OnMouseDown(e); } protected override void OnMouseMove(MouseEventArgs e) { if (waveStream == null) return; if(startPoint.X != -1 && endPoint.X != -1 && (Math.Abs(startPoint.X - e.X) </= 1 || Math.Abs(endPoint.X - e.X) </= 1)) { Cursor.Current = Cursors.SizeWE; } else { Cursor.Current = Cursors.Default; } if (mouseDrag) { DrawVertLine(e.X); if (mousePos.X != -1) DrawVertLine(mousePos.X); mousePos = e.Location; } base.OnMouseMove(e); } protected override void OnMouseUp(MouseEventArgs e) { if (waveStream == null) return; if(mouseDrag && e.Button == System.Windows.Forms.MouseButtons.Left) { mouseDrag = false; endPoint = new Point(mousePos.X, mousePos.Y); int leftSample = (int)(startPosition / bytesPerSample + samplesPerPixel * Math.Min(startPos.X, mousePos.X)); int rightSample = (int)(startPosition / bytesPerSample + samplesPerPixel * Math.Max(startPos.X, mousePos.X)); CutSample(leftSample, rightSample); } else if(!mouseDrag) { } base.OnMouseUp(e); } protected override void OnMouseLeave(EventArgs e) { base.OnMouseLeave(e); Cursor.Current = Cursors.Default; } /// < summary > /// Required designer variable. /// < /summary > private System.ComponentModel.Container components = null; private WaveStream waveStream; private int samplesPerPixel = 128; private long startPosition; private int bytesPerSample; private long bytesPerMilliecond; private long totalBytes; /// < summary > /// Creates a new WaveViewer control /// < /summary > public CustWaveViewer() { // This call is required by the Windows.Forms Form Designer. InitializeComponent(); this.DoubleBuffered = true; this.PenColor = Color.DodgerBlue; this.PenWidth = 1; this.fromStart = new TimeSpan(0, 0, 0, 0, 0); this.fromEnd = new TimeSpan(0, 0, 0, 0, 0); } /// < summary > /// sets the associated wavestream /// < /summary > public WaveStream WaveStream { get { return waveStream; } set { waveStream = value; if (waveStream != null) { bytesPerSample = (waveStream.WaveFormat.BitsPerSample / 8) * waveStream.WaveFormat.Channels; bytesPerMilliecond = (long)(waveStream.Length / waveStream.TotalTime.TotalMilliseconds); totalBytes = waveStream.Length; } this.Invalidate(); } } /// < summary > /// The zoom level, in samples per pixel /// < /summary > public int SamplesPerPixel { get { return samplesPerPixel; } set { samplesPerPixel = Math.Max(1, value); this.Invalidate(); } } /// < summary > /// Start position (currently in bytes) /// < /summary > public long StartPosition { get { return startPosition; } set { startPosition = value; } } /// < summary > /// Clean up any resources being used. /// < /summary > protected override void Dispose(bool disposing) { if (disposing) { if (components != null) { components.Dispose(); } } base.Dispose(disposing); } /// < summary > /// < see cref="Control.OnPaint"/> /// < /summary > protected override void OnPaint(PaintEventArgs e) { if (waveStream != null) { waveStream.Position = 0; int bytesRead; byte[] waveData = new byte[samplesPerPixel * bytesPerSample]; waveStream.Position = startPosition + (e.ClipRectangle.Left * bytesPerSample * samplesPerPixel); using (Pen linePen = new Pen(PenColor, PenWidth)) { for (float x = e.ClipRectangle.X; x < e.ClipRectangle.Right; x += 1) { short low = 0; short high = 0; bytesRead = waveStream.Read(waveData, 0, samplesPerPixel * bytesPerSample); if (bytesRead == 0) break; for (int n = 0; n < bytesRead; n += 2) { short sample = BitConverter.ToInt16(waveData, 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); e.Graphics.DrawLine(linePen, x, this.Height * lowPercent, x, this.Height * highPercent); } } } base.OnPaint(e); } #region Component Designer generated code /// < summary > /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// < /summary > private void InitializeComponent() { components = new System.ComponentModel.Container(); } #endregion } }