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
}
}