📄 wavein.cs
字号:
}
}
/// <summary>
/// Maintain an instance of a MessageWindow that handles audio messages.
/// </summary>
protected SoundMessageWindow m_msgWindow = null;
/// <summary>
/// An instance of WaveFile used as the destination for recording audio.
/// </summary>
protected WaveFile m_file = null;
/// <summary>
/// Create an instance of WaveIn.
/// </summary>
public WaveIn()
{
m_msgWindow = new SoundMessageWindow(this);
m_file = new WaveFile();
}
/// <summary>
/// Determine the number of available recording devices.
/// </summary>
/// <returns>Number of input devices</returns>
public uint NumDevices()
{
return (uint)waveInGetNumDevs();
}
/// <summary>
/// Get the name of the specified recording device.
/// </summary>
/// <param name="deviceId">ID of the device</param>
/// <param name="prodName">Destination string assigned the name</param>
/// <returns>MMSYSERR.NOERROR if successful</returns>
public Wave.MMSYSERR GetDeviceName(uint deviceId, ref string prodName)
{
WAVEINCAPS caps = new WAVEINCAPS();
Wave.MMSYSERR result = waveInGetDevCaps(deviceId, caps, caps.Size);
if (result != Wave.MMSYSERR.NOERROR)
return result;
prodName = caps.szPname;
return Wave.MMSYSERR.NOERROR;
}
/// <summary>
/// A block has finished so notify the WaveFile. In a more complicated example,
/// this class might maintain an array of WaveFile instances. In such a case, the
/// wParam of the message could be passed from the MM_WIM_DATA message. This
/// value represents the m_hwi member of the file that caused the message.
/// The code might look something like:
/// foreach (WaveFile f in m_files)
/// {
/// if (f.m_hwi.ToInt32() == wParam.ToInt32())
/// {
/// f.BlockDone();
/// break;
/// }
/// }
/// </summary>
public void BlockDone()
{
m_file.BlockDone();
}
/// <summary>
/// Preload the buffers of the record file.
/// </summary>
/// <param name="maxRecordLength_ms">Maximum record length in milliseconds</param>
/// <param name="bufferSize">Size of individual buffers, in bytes</param>
/// <returns>MMSYSERR.NOERROR if successful</returns>
public Wave.MMSYSERR Preload(int maxRecordLength_ms, int bufferSize)
{
if (m_file != null)
return m_file.Preload(0, m_msgWindow.Hwnd, maxRecordLength_ms, bufferSize);
return Wave.MMSYSERR.NOERROR;
}
/// <summary>
/// Stop recording.
/// </summary>
public void Stop()
{
if (m_file != null)
m_file.Stop();
}
/// <summary>
/// Start recording.
/// </summary>
/// <returns>MMSYSERR.NOERROR if successful</returns>
public Wave.MMSYSERR Start()
{
if (m_file != null)
return m_file.Start();
return Wave.MMSYSERR.NOERROR;
}
/// <summary>
/// Checks if the recording time is expired.
/// </summary>
/// <returns>true if not currently recording</returns>
public bool Done()
{
return m_file.Done;
}
/// <summary>
/// Save the WaveFile buffers to the specified file.
/// </summary>
/// <param name="fileName">Name of destination file</param>
/// <returns>MMSYSERR.NOERROR if successful</returns>
public Wave.MMSYSERR Save(string fileName)
{
if (m_file != null)
return m_file.Save(fileName);
return Wave.MMSYSERR.NOERROR;
}
/// <summary>
/// Clean up any resources allocated by the class.
/// </summary>
public void Dispose()
{
m_msgWindow.Dispose();
if (m_file != null)
m_file.Dispose();
}
/// <summary>
/// This function retrieves the number of waveform input devices present in the system.
/// </summary>
/// <returns>The number of devices indicates success. Zero indicates that no devices are present or that an error occurred.</returns>
[DllImport ("coredll.dll")]
protected static extern int waveInGetNumDevs();
/// <summary>
/// This function opens a specified waveform input device for recording.
/// </summary>
/// <param name="phwi">Address filled with a handle identifying the open
/// waveform-audio input device. Use this handle to identify the device when
/// calling other waveform-audio input functions. This parameter can be NULL
/// if WAVE_FORMAT_QUERY is specified for fdwOpen.</param>
/// <param name="uDeviceID">Identifier of the waveform-audio input device to open.
/// It can be either a device identifier or a Handle to an open waveform-audio
/// input device. Can also be WAVE_MAPPER.</param>
/// <param name="pwfx">Pointer to a WAVEFORMATEX structure that identifies the
/// desired format for recording waveform-audio data. You can free this structure
/// immediately after waveInOpen returns.</param>
/// <param name="dwCallback">Specifies the address of a fixed callback function,
/// an event handle, a handle to a window, or the identifier of a thread to be
/// called during waveform-audio recording to process messages related to the
/// progress of recording. If no callback function is required, this value can be
/// zero.</param>
/// <param name="dwInstance">Specifies user-instance data passed to the callback
/// mechanism. This parameter is not used with the window callback mechanism.</param>
/// <param name="fdwOpen">Flags for opening the device.</param>
/// <returns>MMSYSERR</returns>
[DllImport ("coredll.dll")]
private static extern Wave.MMSYSERR waveInOpen(ref IntPtr phwi, uint uDeviceID, Wave.WAVEFORMATEX pwfx, IntPtr dwCallback, uint dwInstance, uint fdwOpen);
/// <summary>
/// This function prepares a buffer for waveform input.
/// </summary>
/// <param name="hwi">Handle to the waveform-audio input device.</param>
/// <param name="pwh">Pointer to a WAVEHDR structure that identifies the buffer
/// to be prepared. The buffer's base address must be aligned with the respect
/// to the sample size.</param>
/// <param name="cbwh">Size, in bytes, of the WAVEHDR structure.</param>
/// <returns></returns>
[DllImport ("coredll.dll")]
private static extern Wave.MMSYSERR waveInPrepareHeader(IntPtr hwi, Wave.WAVEHDR pwh, uint cbwh);
/// <summary>
/// This function cleans up the preparation performed by waveInPrepareHeader.
/// The function must be called after the device driver fills a data buffer
/// and returns it to the application. You must call this function before
/// freeing the data buffer.
/// </summary>
/// <param name="hwi">Handle to the waveform-audio input device.</param>
/// <param name="pwh">Pointer to a WAVEHDR structure identifying the buffer to
/// be cleaned up.</param>
/// <param name="cbwh">Size, in bytes, of the WAVEHDR structure.</param>
/// <returns></returns>
[DllImport ("coredll.dll")]
private static extern Wave.MMSYSERR waveInUnprepareHeader(IntPtr hwi, Wave.WAVEHDR pwh, uint cbwh);
/// <summary>
/// This function closes the specified waveform-audio input device.
/// </summary>
/// <param name="hwi">Handle to the waveform-audio input device. If the
/// function succeeds, the handle is no longer valid after this call.</param>
/// <returns>MMSYSERR</returns>
[DllImport ("coredll.dll")]
protected static extern Wave.MMSYSERR waveInClose(IntPtr hwi);
/// <summary>
/// This function stops input on a specified waveform input device and resets
/// the current position to 0. All pending buffers are marked as done and
/// returned to the application.
/// </summary>
/// <param name="hwi">Handle to the waveform-audio input device.</param>
/// <returns>MMSYSERR</returns>
[DllImport ("coredll.dll")]
protected static extern Wave.MMSYSERR waveInReset(IntPtr hwi);
/// <summary>
/// This function starts input on the specified waveform input device.
/// </summary>
/// <param name="hwi">Handle to the waveform-audio input device.</param>
/// <returns>MMSYSERR</returns>
[DllImport ("coredll.dll")]
protected static extern Wave.MMSYSERR waveInStart(IntPtr hwi);
/// <summary>
/// This function stops waveform input.
/// </summary>
/// <param name="hwi">Handle to the waveform-audio input device.</param>
/// <returns>MMSYSERR</returns>
[DllImport ("coredll.dll")]
protected static extern Wave.MMSYSERR waveInStop(IntPtr hwi);
/// <summary>
/// This function sends an input buffer to the specified waveform-audio input
/// device. When the buffer is filled, the application is notified.
/// </summary>
/// <param name="hwi">Handle to the waveform-audio input device.</param>
/// <param name="pwh">Pointer to a WAVEHDR structure that identifies
/// the buffer.</param>
/// <param name="cbwh">Size, in bytes, of the WAVEHDR structure.</param>
/// <returns>MMSYSERR</returns>
[DllImport ("coredll.dll")]
private static extern Wave.MMSYSERR waveInAddBuffer(IntPtr hwi, Wave.WAVEHDR pwh, uint cbwh);
/// <summary>
/// This structure describes the capabilities of a waveform-audio input device.
/// typedef struct
/// {
/// WORD wMid;
/// WORD wPid;
/// MMVERSION vDriverVersion;
/// TCHAR szPname[MAXPNAMELEN];
/// DWORD dwFormats;
/// WORD wChannels;
/// WORD wReserved1;}
/// WAVEINCAPS;
/// This structure has an embedded TCHAR array so the managed implementation is
/// a byte array with accessors.
/// </summary>
protected class WAVEINCAPS
{
const uint WAVEINCAPS_SIZE = 80;
private byte[] m_data = null;
public uint Size { get { return (uint)WAVEINCAPS_SIZE; } }
/// <summary>
/// Manufacturer identifier for the device driver for the waveform-audio
/// input device.
/// </summary>
public ushort wMid { get { return BitConverter.ToUInt16(m_data, 0); } }
/// <summary>
/// Product identifier for the waveform-audio input device. Product
/// identifiers are defined in Manufacturer and Product Identifiers.
/// </summary>
public ushort wPid { get { return BitConverter.ToUInt16(m_data, 2); } }
/// <summary>
/// Version number of the device driver for the waveform-audio input device.
/// The high-order byte is the major version number, and the low-order byte
/// is the minor version number.
/// </summary>
public uint vDriverVersion { get { return BitConverter.ToUInt32(m_data, 4); } }
/// <summary>
/// Specifies the standard formats that are supported. It is one or
/// a combination of the following flags.
/// </summary>
public uint dwFormats { get { return BitConverter.ToUInt32(m_data, 72); } }
/// <summary>
/// Number that specifies whether the device supports mono (1) or stereo (2)
/// input.
/// </summary>
public ushort wChannels { get { return BitConverter.ToUInt16(m_data, 76); } }
/// <summary>
/// Padding.
/// </summary>
public ushort wReserved1 { get { return BitConverter.ToUInt16(m_data, 78); } }
/// <summary>
/// Null-terminated string that contains the product name.
/// </summary>
public string szPname
{
get
{
char[] bytes = new char[32];
for (int i = 0; i < 32; i++)
{
bytes[i] = (char)BitConverter.ToUInt16(m_data, i * 2 + 8);
}
return new string(bytes);
}
}
public WAVEINCAPS()
{
m_data = new byte[WAVEINCAPS_SIZE];
}
public static implicit operator byte[](WAVEINCAPS caps)
{
return caps.m_data;
}
}
/// <summary>
/// This function retrieves the capabilities of a specified waveform-audio
/// input device.
/// </summary>
/// <param name="uDeviceID">Identifier of the waveform-audio output device. It
/// can be either a device identifier or a Handle to an open waveform-audio
/// input device.</param>
/// <param name="pwic">Pointer to a WAVEINCAPS structure to be filled with
/// information about the capabilities of the device.</param>
/// <param name="cbwic">Size, in bytes, of the WAVEINCAPS structure.</param>
/// <returns>MMSYSERR</returns>
[DllImport ("coredll.dll")]
protected static extern Wave.MMSYSERR waveInGetDevCaps(uint uDeviceID, byte[] pwic, uint cbwic);
/// <summary>
/// Run a test of the WaveIn class.
/// </summary>
/// <param name="showLine">Delegate called to show debug information</param>
public static void TestProc(MainTest.DisplayLineDelegate showLine)
{
WaveIn wi = null;
try
{
wi = new WaveIn();
uint numDevices = wi.NumDevices();
if (numDevices < 1)
{
showLine("FAILURE: No valid sound drivers detected");
return;
}
showLine(string.Format("{0} device{1} detected:", numDevices, numDevices != 1 ? "s" : ""));
for (uint i = 0; i < numDevices; i++)
{
string prodName = "";
if (Wave.MMSYSERR.NOERROR != wi.GetDeviceName(i, ref prodName))
{
showLine(string.Format(" {0}: Failed to get name", i));
}
else
{
showLine(string.Format(" {0}: {1}", i, prodName));
}
}
showLine("Setting max time to 3 seconds");
showLine("Using 256KB buffers");
if (Wave.MMSYSERR.NOERROR != wi.Preload(3000, 256*1024))
{
showLine("FAILURE: Failed to preload buffers");
}
showLine("Starting recording...");
if (Wave.MMSYSERR.NOERROR != wi.Start())
{
showLine("FAILURE: Failed to start recording");
}
showLine("Waiting for 2 seconds...");
Thread.Sleep(2000);
showLine("Stopping recording early");
wi.Stop();
String fileName = System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase;
fileName = Path.GetDirectoryName(fileName);
fileName = Path.Combine(fileName, "test.wav");
showLine("Saving file test.wav");
if (Wave.MMSYSERR.NOERROR != wi.Save(fileName))
{
showLine("FAILURE: Failed to save file");
}
}
finally
{
if (wi != null)
wi.Dispose();
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -