⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wavedisplaycontrol.cs

📁 visual c++编写关于声音分析的 傅立叶变换.超牛
💻 CS
字号:
using System;
using System.IO;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using System.Drawing;
using System.Drawing.Imaging;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace SteganoTape {
	public partial class WaveDisplayControl : UserControl {

		private String currentFile;
		private WaveSound waveSound;
		private WaveOutPlayer player;
		private Stream playerStream;
		private float zoomPercent;
		private short maxSampleValue;
		private Collection<CheckBox> checkBoxes;
		private String soxPath;

		/// <summary>Is called after a wave file has been opened</summary>
		public event EventHandler Open;

		/// <summary>Returns path and name of the currently displayed file</summary>
		public String CurrentFile{
			get { return currentFile; }
		}

		/// <summary>Gets or sets path and name of sox.exe</summary>
		/// <remarks>Sound Exchange is only used to convert 8 bit files to 16 bit.</remarks>
		public String SoxPath
		{
			get { return soxPath; }
			set { soxPath = value; }
		}

		/// <summary>Gets or sets the zoom factor</summary>
		public float ZoomPercent
		{
			get { return zoomPercent; }
			set {
				zoomPercent = value;
				tstZoom.Text = zoomPercent.ToString("n2", CultureInfo.CurrentCulture);
				if (waveSound != null) {
					DrawWave();
				}
			}
		}

		/// <summary>Gets the duration of the displayed file in seconds</summary>
		public float Duration{
			get{
				return (float)waveSound.Count / (float)waveSound.Format.SamplesPerSec;
			}
		}

		/// <summary>Gets the value of the loudest sample</summary>
		public int MaxSampleValue
		{
			get
			{
				return maxSampleValue;
			}
		}

		/// <summary>Gets or sets the displayed wave sound</summary>
		/// <remarks>Setting the sound raises an "Open" event</remarks>
		public WaveSound WaveSound
		{
			get { return waveSound; }
			set {
				waveSound = value;

				foreach (CheckBox chk in checkBoxes) {
					chk.Parent.Controls.Remove(chk);
				}
				checkBoxes.Clear();
				
				if (waveSound != null) {
					DrawWave();
				}
				
				tsbPlay.Enabled = true;
				tsbStop.Enabled = true;

				if (Open != null) {
					Open(this, EventArgs.Empty);
				}
			}
		}

		/// <summary>Gets the selected beeps</summary>
		public Collection<Beep> SelectedItems
		{
			get
			{
				Collection<Beep> selectedItems = new Collection<Beep>();
				foreach (CheckBox checkBox in checkBoxes) {
					if (checkBox.Checked) {
						selectedItems.Add((Beep)checkBox.Tag);
					}
				}
				return selectedItems;
			}
		}
		
		/// <summary>Constructor</summary>
		public WaveDisplayControl()
		{
			InitializeComponent();
			checkBoxes = new Collection<CheckBox>();
			zoomPercent = int.Parse(tstZoom.Text);
			currentFile = String.Empty;

			tsbPlay.Enabled = false;
			tsbStop.Enabled = false;
		}

		/// <summary>Create a WaveUtility for the displayed sound</summary>
		/// <returns></returns>
		public WaveUtility CreateWaveUtility(){
			WaveUtility waveUtility = new WaveUtility(waveSound);
			waveUtility.BeepFound += new BeepFoundHandler(HandleBeepFound);
			return waveUtility;
		}

		/// <summary>Handle "BeepFound" events from a WaveUtility</summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void HandleBeepFound(object sender, BeepFoundEventArgs e)
		{
			MarkBeep(e);
			Application.DoEvents();
		}

		/// <summary>Forget all beeps</summary>
		public void ClearBeeps()
		{
			foreach (CheckBox chk in checkBoxes) { panelContainer.Controls.Remove(chk); }
			checkBoxes.Clear();
			DrawWave();
		}

		/// <summary>Draw the wave and display statistics</summary>
		public void DrawWave()
		{
			Control topLevelControl = this.FindForm();
			if (topLevelControl == null) { topLevelControl = this; };
			topLevelControl.Cursor = Cursors.WaitCursor;

			try {

				short[] channelSamples = waveSound.Samples;
				float zoom = zoomPercent / 100;
				maxSampleValue = 0;

				//remove existing checkboxes
				foreach (CheckBox chk in checkBoxes) { panelContainer.Controls.Remove(chk); }

				//resize picturebox
				int scaledWidth = (int)((float)channelSamples.Length * zoom);
				picWave.Width = scaledWidth;

				//Skalierung berechnen
				picWave.Height = panelContainer.Height - SystemInformation.HorizontalScrollBarHeight;
				int samplesPerPixel;
				int spacePerSample;
				if (picWave.Width > channelSamples.Length) {
					//mehrere Pixel pro Sample
					samplesPerPixel = 1;
					spacePerSample = picWave.Width / channelSamples.Length;
				} else {
					//mehrere Samples pro Pixel
					spacePerSample = 1;
					samplesPerPixel = channelSamples.Length / picWave.Width;
				}

				//Breite einer Sekunde berechnen
				int pixelsPerSecond = (int)(waveSound.Format.SamplesPerSec * spacePerSample / samplesPerPixel);

				Bitmap bitmap = new Bitmap(picWave.Width, picWave.Height, PixelFormat.Format24bppRgb);
				Graphics graphics = Graphics.FromImage(bitmap);
				Pen pen = new Pen(Color.Black);
				graphics.Clear(Color.White);

				int absValue;
				for (int channelSamplesIndex = 0; channelSamplesIndex < channelSamples.Length; channelSamplesIndex++) {
					absValue = Math.Abs((int)channelSamples[channelSamplesIndex]);
					if (absValue > maxSampleValue) {
						maxSampleValue = (absValue > short.MaxValue) ? (short)(absValue - 1) : (short)absValue;
					}
				}

				float yOffset = bitmap.Height / 2;

				if (maxSampleValue != 0) { //not trying to display silence (all pixels == 0)

					float yScale = yOffset / maxSampleValue;

					float xPosition = 0;
					int pixelMaximum = 0;
					int pixelMinimum = 0;
					short currentSample;

					PointF previousPoint = new PointF(0, yOffset);
					for (int n = 0; n < channelSamples.Length; n += samplesPerPixel) {
						currentSample = channelSamples[n];
						pixelMaximum = 0;
						pixelMinimum = 0;

						for (int sampleIndex = n; sampleIndex < (n + samplesPerPixel); sampleIndex++) {
							if (currentSample > pixelMaximum) { pixelMaximum = currentSample; }
							if (currentSample < pixelMinimum) { pixelMinimum = currentSample; }
						}

						pixelMaximum = (int)(pixelMaximum * yScale);
						pixelMinimum = (int)(pixelMinimum * yScale);

						graphics.DrawLine(pen, previousPoint.X, previousPoint.Y, xPosition, yOffset + pixelMinimum);
						graphics.DrawLine(pen, xPosition, yOffset + pixelMaximum, xPosition, yOffset + pixelMinimum);
						previousPoint.X = xPosition;
						previousPoint.Y = yOffset + pixelMaximum;

						xPosition += spacePerSample;
					}
				}

				//show seconds
				int second = 0;
				Brush brush = new SolidBrush(Color.Blue);
				Font boldFont = new Font(this.Font, FontStyle.Bold);
				for (int n = 0; n < picWave.Width; n += pixelsPerSecond) {
					graphics.DrawString(second.ToString(), boldFont, brush, n, picWave.Height - 15);
					second++;
				}

				pen.Color = Color.Red;
				graphics.DrawLine(pen, 0, yOffset, bitmap.Width, yOffset);

				graphics.Dispose();
				picWave.Image = bitmap;

				//show statistics
				tsslLength.Text = this.Duration.ToString("n2", CultureInfo.CurrentCulture);
				tsslVolume.Text = maxSampleValue.ToString(CultureInfo.CurrentCulture);

				//re-add existing checkboxes
				foreach (CheckBox chk in checkBoxes) { MarkBeep(new BeepFoundEventArgs((Beep)chk.Tag), chk); }

			} finally {
				topLevelControl.Cursor = Cursors.Default;
			}
		}

		/// <summary>Display a beep and add a new CheckBox</summary>
		/// <param name="eventArgs"></param>
		private void MarkBeep(BeepFoundEventArgs eventArgs)
		{
			MarkBeep(eventArgs, new CheckBox());
		}

		/// <summary>Display a beep</summary>
		/// <param name="eventArgs"></param>
		/// <param name="checkBox"></param>
		private void MarkBeep(BeepFoundEventArgs eventArgs, CheckBox checkBox)
		{
			int samplesPerPixel;
			int spacePerSample;
			int imageWidth = picWave.Image.Width;
			if (imageWidth > waveSound.Count) {
				//mehrere Pixel pro Sample
				samplesPerPixel = 1;
				spacePerSample = imageWidth / waveSound.Count;
			} else {
				//mehrere Samples pro Pixel
				spacePerSample = 1;
				samplesPerPixel = waveSound.Count / imageWidth;
			}

			Graphics graphics = Graphics.FromImage(picWave.Image);
			Pen pen = new Pen(Color.Red);
			Brush brush = new SolidBrush(Color.Red);

			//start index
			int startPixelIndex = spacePerSample * (int)Math.Floor((float)eventArgs.Beep.StartSampleIndex / (float)samplesPerPixel);
			graphics.DrawLine(pen, startPixelIndex, 0, startPixelIndex, picWave.Height);
			//left arrow
			graphics.DrawPolygon(pen, new Point[3] {
				new Point(startPixelIndex, 0),
				new Point(startPixelIndex + 4, 4),
				new Point(startPixelIndex, 8) });

			//end index
			int endPixelIndex = spacePerSample * (int)Math.Floor((float)eventArgs.Beep.EndSampleIndex / (float)samplesPerPixel);
			graphics.DrawLine(pen, endPixelIndex, 0, endPixelIndex, picWave.Height);
			//right arrow
			graphics.DrawPolygon(pen, new Point[3] {
				new Point(endPixelIndex, 0),
				new Point(endPixelIndex - 4, 4),
				new Point(endPixelIndex, 8) });

			graphics.DrawString(
				String.Format(
					CultureInfo.CurrentCulture,
					"{0} - {1}",
					eventArgs.Beep.StartSecond.ToString("n1", CultureInfo.CurrentCulture),
					eventArgs.Beep.EndSecond.ToString("n1", CultureInfo.CurrentCulture)),
				this.Font, brush, startPixelIndex, 10);

			graphics.Dispose();
			picWave.Invalidate();

			if (checkBox.Tag == null) {
				//the checkbox is new
				checkBox.Tag = eventArgs.Beep;
				checkBoxes.Add(checkBox);
				checkBox.Checked = true;
				checkBox.Width = checkBox.Height;
			}
			checkBox.Left = startPixelIndex + ((endPixelIndex - startPixelIndex) / 2);
			checkBox.Top = picWave.Height - checkBox.Height;
			checkBox.BackColor = Color.White;
			panelContainer.Controls.Add(checkBox);
			checkBox.BringToFront();
		}

		/// <summary>Stop playback, before closing the application</summary>
		public void Close()
		{
			PlayerStop();
		}

		/// <summary>Change the zoom factor, when the user leaves the zoom box</summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void tstZoom_Leave(object sender, EventArgs e)
		{
			OnZoomFactorChanged();
		}

		/// <summary>Change the zoom factor, when the user leaves the zoom box</summary>
		private void OnZoomFactorChanged()
		{
			float newZoomPercent;
			if (float.TryParse(tstZoom.Text, out newZoomPercent)) {
				this.ZoomPercent = newZoomPercent;
			}
		}

		/// <summary>Play the wave sound</summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void tsbPlay_Click(object sender, EventArgs e)
		{
			if (waveSound != null) {
				playerStream = waveSound.CreateStream();
				this.player = new WaveOutPlayer(this.WaveSound.Format, playerStream);
			}
		}

		/// <summary>Stop playback</summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void tsbStop_Click(object sender, EventArgs e)
		{
			PlayerStop();
		}

		/// <summary>Stop the player and close its stream</summary>
		private void PlayerStop()
		{
			if (player != null) {
				try {
					player.Dispose();
				} finally {
					player = null;
				}
			}
			if (playerStream != null) {
				playerStream.Close();
			}
		}

		/// <summary>Open a sound from a wave file</summary>
		/// <param name="fileName"></param>
		public void OpenFromFile(String fileName)
		{
			currentFile = fileName;
			WaveUtility waveUtility = new WaveUtility(fileName);

			if (waveUtility.WaveSound.Format.BitsPerSample != 16) {
				waveUtility.ConvertToDefaultFormat(
					Path.GetTempPath(),
					soxPath);
			}

			this.WaveSound = waveUtility.WaveSound;
		}

		/// <summary>Let the user select a wave file, and then open it</summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void tsbOpen_Click(object sender, EventArgs e)
		{
			OpenFileDialog dlg = new OpenFileDialog();
			dlg.Filter = "*.wav|*.wav";
			if (dlg.ShowDialog() == DialogResult.OK) {
				OpenFromFile(dlg.FileName);
			}
		}

		/// <summary>Save the displayed sound to a wave file</summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void tsbSave_Click(object sender, EventArgs e)
		{
			if (waveSound != null) {
				SaveFileDialog dlg = new SaveFileDialog();
				dlg.Filter = "*.wav|*.wav";
				if (dlg.ShowDialog() == DialogResult.OK) {
					waveSound.SaveToFile(dlg.FileName);
				}
			}
		}

	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -