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

📄 wavein.cs

📁 功能:基于windows mobile 的地图查看器。使用vs2005开发
💻 CS
📖 第 1 页 / 共 2 页
字号:
using System;
using System.Runtime.InteropServices;
using System.IO;
using Microsoft.WindowsCE.Forms;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Diagnostics;

namespace PInvokeLibrary
{
	/// <summary>
	/// Encapsulates Waveform Audio Interface recording functions and provides a simple
	/// interface for recording audio.
	/// </summary>
	public class WaveIn
	{
		/// <summary>
		/// Supplies an inteface for creating, recording to, and saving a .wav file.
		/// </summary>
		protected class WaveFile : IDisposable
		{
			/// <summary>
			/// Hardware interface instance for this wave file.
			/// </summary>
			protected IntPtr m_hwi = IntPtr.Zero;

			/// <summary>
			/// Instance of the WAVEFORMATEX header for this file.
			/// </summary>
			protected Wave.WAVEFORMATEX m_wfmt = null;

			/// <summary>
			/// Buffers used to store recording information.
			/// </summary>
			protected Wave.WAVEHDR[] m_whdr = null;

			/// <summary>
			/// Specifies whether the file is inited or not.
			/// </summary>
			protected bool m_inited = false;

			/// <summary>
			/// Current block, or buffer in m_whdr, being written.
			/// </summary>
			protected int m_curBlock;

			/// <summary>
			/// Maximum number of blocks to be written.
			/// </summary>
			protected int m_numBlocks;

			/// <summary>
			/// Size of each record buffer.
			/// </summary>
			protected uint m_bufferSize;

			/// <summary>
			/// Maximum size of all record buffers.
			/// </summary>
			protected uint m_maxDataLength;

			/// <summary>
			/// Specifies whether or not recording is done.
			/// </summary>
			public bool Done { get { return !m_recording; } }
			protected bool m_recording = false;

			/// <summary>
			/// Preload the buffers and prepare them for recording.
			/// </summary>
			/// <param name="curDevice">Device to use for recording</param>
			/// <param name="hwnd">Handle to a message window that will receive
			/// audio messages.</param>
			/// <param name="maxRecordLength_ms">Maximum length of recording</param>
			/// <param name="bufferSize">Size of buffers to use for recording.  New
			/// buffers are added when needed until the maximum length is reached
			/// or the recording is stopped.</param>
			/// <returns>MMSYSERR.NOERROR if successful</returns>
			public Wave.MMSYSERR Preload(uint curDevice, IntPtr hwnd, int maxRecordLength_ms, int bufferSize)
			{
				// Do not allow recording to be interrupted
				if (m_recording)
					return Wave.MMSYSERR.ERROR;

				// If this file is already initialized then start over
				if (m_inited)
				{
					Stop();
					FreeWaveBuffers();
				}

				// Create an instance of WAVEINCAPS to check if our desired
				// format is supported
				WAVEINCAPS caps = new WAVEINCAPS();
				waveInGetDevCaps(0, caps, caps.Size);
				if ((caps.dwFormats & Wave.WAVE_FORMAT_1S08) == 0)
					return Wave.MMSYSERR.NOTSUPPORTED;

				// Initialize a WAVEFORMATEX structure specifying the desired
				// format
				m_wfmt = new Wave.WAVEFORMATEX();
				m_wfmt.wFormatTag = Wave.WAVEHDR.WAVE_FORMAT_PCM;
				m_wfmt.wBitsPerSample = 8;
				m_wfmt.nChannels = 2;
				m_wfmt.nSamplesPerSec = 11025;
				m_wfmt.nAvgBytesPerSec = (uint)(m_wfmt.nSamplesPerSec * m_wfmt.nChannels * (m_wfmt.wBitsPerSample / 8));
				m_wfmt.nBlockAlign = (ushort)(m_wfmt.wBitsPerSample * m_wfmt.nChannels / 8);

				// Attempt to open the specified device with the desired wave format
				Wave.MMSYSERR result = waveInOpen(ref m_hwi, curDevice, m_wfmt, hwnd, 0, Wave.CALLBACK_WINDOW);
				if (result != Wave.MMSYSERR.NOERROR)
					return result;

				if (bufferSize == 0)
					return Wave.MMSYSERR.ERROR;

				m_bufferSize = (uint)bufferSize;

				// Force the buffers to align to nBlockAlign
				if (m_bufferSize % m_wfmt.nBlockAlign != 0)
					m_bufferSize += m_wfmt.nBlockAlign - (m_bufferSize % m_wfmt.nBlockAlign);

				// Determine the number of buffers needed to record the maximum length
				m_maxDataLength = (uint)(m_wfmt.nAvgBytesPerSec * maxRecordLength_ms / 1000);
				m_numBlocks = (int)(m_maxDataLength / m_bufferSize);
				if (m_numBlocks * m_bufferSize < m_maxDataLength)
					m_numBlocks++;

				// Allocate the list of buffers
				m_whdr = new Wave.WAVEHDR[m_numBlocks + 1];

				// Allocate and initialize two buffers to start with
				m_whdr[0] = new Wave.WAVEHDR();
				m_whdr[1] = new Wave.WAVEHDR();

				result = InitBuffer(0);
				if (result != Wave.MMSYSERR.NOERROR)
					return result;

				result = InitBuffer(1);
				if (result != Wave.MMSYSERR.NOERROR)
					return result;

				m_curBlock = 0;
				m_inited = true;

				return Wave.MMSYSERR.NOERROR;
			}

			/// <summary>
			/// Called when the Windows message specifying that a block has finished
			/// recording is encountered.  It is critical that the application stay
			/// one buffer ahead because at the point this function is called, the system
			/// has already started writing to the next buffer.
			/// </summary>
			public void BlockDone()
			{
				m_curBlock++;

				// If the next block is not the padding buffer at the end of the
				// recording then initialize another buffer, otherwise stop recording
				if (m_curBlock < m_numBlocks)
				{
					InitBuffer(m_curBlock + 1);
				}
				else if (m_curBlock == m_numBlocks)
				{
					Stop();
				}
			}

			/// <summary>
			/// Initialize a buffer for recording by allocating a data buffer,
			/// preparing the header, and adding it to the read queue.
			/// </summary>
			/// <param name="bufIndex">Index of buffer to allocate</param>
			/// <returns>MMSYSERR.NOERROR if successful</returns>
			public Wave.MMSYSERR InitBuffer(int bufIndex)
			{
				// Determine the size of the buffer to create
				uint writeLength = (uint)m_bufferSize;
				if (bufIndex < m_numBlocks)
				{
					uint remainingDataLength = (uint)(m_maxDataLength - bufIndex * m_bufferSize);
					if (m_bufferSize > remainingDataLength)
						writeLength = remainingDataLength;
				}

				// If the header is not already instanced then instance it
				if (m_whdr[bufIndex] == null)
					m_whdr[bufIndex] = new Wave.WAVEHDR();

				// Allocate memory if not already allocated
				Wave.MMSYSERR result = m_whdr[bufIndex].Init(writeLength, false);
				if (result != Wave.MMSYSERR.NOERROR)
					return result;

				// Prepare the header
				result = waveInPrepareHeader(m_hwi, m_whdr[bufIndex], (uint)Marshal.SizeOf(m_whdr[bufIndex]));
				if (result != Wave.MMSYSERR.NOERROR)
					return result;

				// Put the buffer in the queue
				return waveInAddBuffer(m_hwi, m_whdr[bufIndex], (uint)Marshal.SizeOf(m_whdr[bufIndex]));
			}

			/// <summary>
			/// Start recording.
			/// </summary>
			/// <returns>MMSYSERR.NOERROR if successful</returns>
			public Wave.MMSYSERR Start()
			{
				if (!m_inited || m_recording)
					return Wave.MMSYSERR.ERROR;

				Wave.MMSYSERR result = waveInStart(m_hwi);
				if (result != Wave.MMSYSERR.NOERROR)
					return result;

				m_recording = true;

				return Wave.MMSYSERR.NOERROR;
			}

			/// <summary>
			/// Free the buffers allocated for recording.  This is not done when
			/// recording stops because the user needs a chance to save or reject
			/// the recording before trying again.
			/// </summary>
			private void FreeWaveBuffers()
			{
				m_inited = false;

				if (m_whdr != null)
				{
					for(int i = 0; i < m_whdr.Length; i++)
					{
						if (m_whdr[i] != null)
						{
							waveInUnprepareHeader(m_hwi, m_whdr[i], (uint)Marshal.SizeOf(m_whdr[i]));

							m_whdr[i].Dispose();
							m_whdr[i] = null;
						}
					}

					m_whdr = null;
				}

				waveInClose(m_hwi);
				
				m_hwi = IntPtr.Zero;
			}

			/// <summary>
			/// Write individual characters to the BinaryWriter.  This is a helper
			/// function used by Save.  Writing strings does not work because they
			/// write a length before the characters.
			/// </summary>
			/// <param name="wrtr">Destination of write</param>
			/// <param name="text">Characters to be written</param>
			private void WriteChars(BinaryWriter wrtr, string text)
			{
				for (int i = 0; i < text.Length; i++)
				{
					char c = (char)text[i];
					wrtr.Write(c);
				}
			}

			/// <summary>
			/// Save the current record buffers to the specified file.
			/// </summary>
			/// <param name="fileName">Name of file to be saved</param>
			/// <returns>MMSYSERR.NOERROR if successful</returns>
			public Wave.MMSYSERR Save(string fileName)
			{
				if (!m_inited)
					return Wave.MMSYSERR.ERROR;

				if (m_recording)
					Stop();

				FileStream strm = null;
				BinaryWriter wrtr = null;

				try
				{
					if (File.Exists(fileName))
					{
						FileInfo fi = new FileInfo(fileName);
						if ((fi.Attributes & FileAttributes.ReadOnly) != 0)
							fi.Attributes -= FileAttributes.ReadOnly;

						strm = new FileStream(fileName, FileMode.Truncate);
					}
					else
					{
						strm = new FileStream(fileName, FileMode.Create);
					}

					if (strm == null)
						return Wave.MMSYSERR.ERROR;

					wrtr = new BinaryWriter(strm);
					if (wrtr == null)
						return Wave.MMSYSERR.ERROR;

					// Determine the size of the data, as the total number of bytes
					// recorded by each buffer
					uint totalSize = 0;
					for (int i = 0; i < m_numBlocks; i++)
					{
						if (m_whdr[i] != null)
							totalSize += m_whdr[i].dwBytesRecorded;
					}

					int chunkSize = (int)(36 + totalSize);

					// Write out the header information
					WriteChars(wrtr, "RIFF");
					wrtr.Write(chunkSize);
					WriteChars(wrtr, "WAVEfmt ");
					wrtr.Write((int)16);
					m_wfmt.Write(wrtr);
					WriteChars(wrtr, "data");
					wrtr.Write((int)totalSize);

					// Write the data recorded to each buffer
					for (int i = 0; i < m_numBlocks; i++)
					{
						if (m_whdr[i] != null)
						{
							Wave.MMSYSERR result = m_whdr[i].Write(wrtr);
							if (result != Wave.MMSYSERR.NOERROR)
								return result;
						}
					}

					return Wave.MMSYSERR.NOERROR;
				}
				finally
				{
					FreeWaveBuffers();

					if (strm != null)
						strm.Close();

					if (wrtr != null)
						wrtr.Close();
				}
			}

			/// <summary>
			/// Stop recording.  After stopping, the buffers are kept until recording
			/// is restarted or the buffers are saved.
			/// </summary>
			public void Stop()
			{
				waveInReset(m_hwi);

				m_recording = false;
			}

			/// <summary>
			/// Clean up any allocated resources.
			/// </summary>
			public void Dispose()
			{
				Stop();

				FreeWaveBuffers();
			}
		}

		/// <summary>
		/// Defines the MessageWindow used to receive messages from the audio
		/// system.
		/// </summary>
		protected class SoundMessageWindow : MessageWindow
		{
			public const int MM_WIM_OPEN = 0x3BE;
			public const int MM_WIM_CLOSE = 0x3BF;
			public const int MM_WIM_DATA = 0x3C0;

			// Instance of a recording interface
			protected WaveIn m_wi = null;

			public SoundMessageWindow(WaveIn wi)
			{
				m_wi = wi;
			}

			protected override void WndProc(ref Message msg)
			{
				switch(msg.Msg)
				{
					// When this message is encountered, a block is
					// done recording, so notify the WaveIn instance.
					case MM_WIM_DATA:
					{
						if (m_wi != null)
							m_wi.BlockDone();
					}
					break;
				}
				base.WndProc(ref msg);

⌨️ 快捷键说明

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