資料參考: http://stackoverflow.com/questions/7105806/c-sharp-audio-recording-using-winmm-dll-native-code
資料參考: http://msdn.microsoft.com/en-us/library/windows/desktop/dd370817(v=vs.85).aspx
Play:
using System;
using System.Runtime.InteropServices;
class PInvokeTest
{[DllImport("winmm.dll")]
public static extern bool PlaySound(string pszSound, UIntPtr hmod, uint fdwSound);public static void Main(){bool result;
result = PlaySound("C:\\WINDOWS\\Media\\Chimes.wav", UIntPtr.Zero, 0x0001 | 0x00020000);
Console.WriteLine(result);}}
Record:
[WaveIn.CS]
using System;
using System.Threading;
using System.Runtime.InteropServices;
namespace SoundViewer
{internal class WaveInHelper{public static void Try(int err){if (err != WaveNative.MMSYSERR_NOERROR)
throw new Exception(err.ToString());}}public delegate void BufferDoneEventHandler(IntPtr data, int size);internal class WaveInBuffer : IDisposable{public WaveInBuffer NextBuffer;
private AutoResetEvent m_RecordEvent = new AutoResetEvent(false);private IntPtr m_WaveIn;
private WaveNative.WaveHdr m_Header;
private byte[] m_HeaderData;private GCHandle m_HeaderHandle;
private GCHandle m_HeaderDataHandle;
private bool m_Recording;internal static void WaveInProc(IntPtr hdrvr, int uMsg, int dwUser, ref WaveNative.WaveHdr wavhdr, int dwParam2){if (uMsg == WaveNative.MM_WIM_DATA)
{try
{GCHandle h = (GCHandle)wavhdr.dwUser;WaveInBuffer buf = (WaveInBuffer)h.Target;buf.OnCompleted();}catch
{}}}public WaveInBuffer(IntPtr waveInHandle, int size){m_WaveIn = waveInHandle;m_HeaderHandle = GCHandle.Alloc(m_Header, GCHandleType.Pinned);m_Header.dwUser = (IntPtr)GCHandle.Alloc(this);
m_HeaderData = new byte[size];m_HeaderDataHandle = GCHandle.Alloc(m_HeaderData, GCHandleType.Pinned);m_Header.lpData = m_HeaderDataHandle.AddrOfPinnedObject();m_Header.dwBufferLength = size;WaveInHelper.Try(WaveNative.waveInPrepareHeader(m_WaveIn, ref m_Header, Marshal.SizeOf(m_Header)));
}~WaveInBuffer(){Dispose();}public void Dispose(){if (m_Header.lpData != IntPtr.Zero)
{WaveNative.waveInUnprepareHeader(m_WaveIn, ref m_Header, Marshal.SizeOf(m_Header));
m_HeaderHandle.Free();m_Header.lpData = IntPtr.Zero;}m_RecordEvent.Close();if (m_HeaderDataHandle.IsAllocated)
m_HeaderDataHandle.Free();GC.SuppressFinalize(this);
}public int Size{get { return m_Header.dwBufferLength; }
}public IntPtr Data
{get { return m_Header.lpData; }
}public bool Record(){lock(this){m_RecordEvent.Reset();m_Recording = WaveNative.waveInAddBuffer(m_WaveIn, ref m_Header, Marshal.SizeOf(m_Header)) == WaveNative.MMSYSERR_NOERROR;
System.Diagnostics.Debug.Write(string.Format("\n m_WaveIn: {0}, m_Header.dwBytesRecorded: {1}", m_WaveIn, m_Header.dwBytesRecorded));//m_WaveIn.ToPointer();
return m_Recording;
}}public void WaitFor(){if (m_Recording)
m_Recording = m_RecordEvent.WaitOne();else
Thread.Sleep(0);}private void OnCompleted(){m_RecordEvent.Set();m_Recording = false;
}}public class WaveInRecorder : IDisposable{private IntPtr m_WaveIn;
private WaveInBuffer m_Buffers; // linked listprivate WaveInBuffer m_CurrentBuffer;
private Thread m_Thread;
private BufferDoneEventHandler m_DoneProc;
private bool m_Finished;private WaveNative.WaveDelegate m_BufferProc = new WaveNative.WaveDelegate(WaveInBuffer.WaveInProc);public static int DeviceCount{get { return WaveNative.waveInGetNumDevs(); }
}public WaveInRecorder(int device, WaveFormat format, int bufferSize, int bufferCount, BufferDoneEventHandler doneProc){m_DoneProc = doneProc;WaveInHelper.Try(WaveNative.waveInOpen(out m_WaveIn, device, format, m_BufferProc, 0, WaveNative.CALLBACK_FUNCTION));
AllocateBuffers(bufferSize, bufferCount);for (int i = 0; i < bufferCount; i++){SelectNextBuffer();m_CurrentBuffer.Record();}WaveInHelper.Try(WaveNative.waveInStart(m_WaveIn));m_Thread = new Thread(new ThreadStart(ThreadProc));m_Thread.Start();}public void Recording(){//int rawsize = Marshal.SizeOf(m_WaveIn);
//byte[] rawdata = new byte[256 * 1024];
////Marshal.Copy(m_WaveIn, rawdata, 0, rawsize);
////System.IO.File.WriteAllBytes(string.Format("C:\\TempImage\\audio_{0}.wav", Guid.NewGuid()), rawdata );
//Marshal.Copy(rawdata, 0, m_WaveIn, rawdata.Length);
////System.IO.File.WriteAllBytes(string.Format("C:\\TempImage\\audio_{0}.wav", Guid.NewGuid()), rawdata);
////Marshal.FreeHGlobal(m_WaveIn);
//System.IO.MemoryStream ms = new System.IO.MemoryStream(
//int elementSize = Marshal.SizeOf(typeof(IntPtr));
//System.Diagnostics.Debug.Print("Reading unmanaged memory:");
//// Print the 10 elements of the C-style unmanagedArray
//for (int i = 0; i < 10; i++)
//{
// System.Diagnostics.Debug.Print(Marshal.ReadIntPtr(m_WaveIn, i * elementSize));
//}
}~WaveInRecorder(){Dispose();}public void Dispose(){if (m_Thread != null)try
{m_Finished = true;
if (m_WaveIn != IntPtr.Zero)
WaveNative.waveInReset(m_WaveIn);WaitForAllBuffers();m_Thread.Join();m_DoneProc = null;
FreeBuffers();if (m_WaveIn != IntPtr.Zero)
WaveNative.waveInClose(m_WaveIn);}finally
{m_Thread = null;
m_WaveIn = IntPtr.Zero;}GC.SuppressFinalize(this);
}private void ThreadProc(){while (!m_Finished)
{Advance();if (m_DoneProc != null && !m_Finished)m_DoneProc(m_CurrentBuffer.Data, m_CurrentBuffer.Size);m_CurrentBuffer.Record();}}private void AllocateBuffers(int bufferSize, int bufferCount){FreeBuffers();if (bufferCount > 0)
{m_Buffers = new WaveInBuffer(m_WaveIn, bufferSize);
WaveInBuffer Prev = m_Buffers;try
{for (int i = 1; i < bufferCount; i++){WaveInBuffer Buf = new WaveInBuffer(m_WaveIn, bufferSize);
Prev.NextBuffer = Buf;Prev = Buf;}}finally
{Prev.NextBuffer = m_Buffers;}}}private void FreeBuffers(){m_CurrentBuffer = null;
if (m_Buffers != null){WaveInBuffer First = m_Buffers;m_Buffers = null;
WaveInBuffer Current = First;do
{WaveInBuffer Next = Current.NextBuffer;Current.Dispose();Current = Next;} while(Current != First);
}}private void Advance(){SelectNextBuffer();m_CurrentBuffer.WaitFor();}private void SelectNextBuffer(){m_CurrentBuffer = m_CurrentBuffer == null ? m_Buffers : m_CurrentBuffer.NextBuffer;
}private void WaitForAllBuffers(){WaveInBuffer Buf = m_Buffers;while (Buf.NextBuffer != m_Buffers)
{Buf.WaitFor();Buf = Buf.NextBuffer;}}}[WaveNative.cs]
internal class WaveNative{// consts
public const int MMSYSERR_NOERROR = 0; // no errorpublic const int MM_WOM_OPEN = 0x3BB;public const int MM_WOM_CLOSE = 0x3BC;public const int MM_WOM_DONE = 0x3BD;public const int MM_WIM_OPEN = 0x3BE;public const int MM_WIM_CLOSE = 0x3BF;public const int MM_WIM_DATA = 0x3C0;public const int CALLBACK_FUNCTION = 0x00030000; // dwCallback is a FARPROCpublic const int TIME_MS = 0x0001; // time in millisecondspublic const int TIME_SAMPLES = 0x0002; // number of wave samplespublic const int TIME_BYTES = 0x0004; // current byte offset// callbacks
public delegate void WaveDelegate(IntPtr hdrvr, int uMsg, int dwUser, ref WaveHdr wavhdr, int dwParam2);// structs
[StructLayout(LayoutKind.Sequential)] public struct WaveHdr{public IntPtr lpData; // pointer to locked data bufferpublic int dwBufferLength; // length of data bufferpublic int dwBytesRecorded; // used for input onlypublic IntPtr dwUser; // for client's usepublic int dwFlags; // assorted flags (see defines)public int dwLoops; // loop control counterpublic IntPtr lpNext; // PWaveHdr, reserved for driverpublic int reserved; // reserved for driver}private const string mmdll = "winmm.dll";// WaveOut calls
[DllImport(mmdll)]public static extern int waveOutGetNumDevs();[DllImport(mmdll)]public static extern int waveOutPrepareHeader(IntPtr hWaveOut, ref WaveHdr lpWaveOutHdr, int uSize);[DllImport(mmdll)]public static extern int waveOutUnprepareHeader(IntPtr hWaveOut, ref WaveHdr lpWaveOutHdr, int uSize);[DllImport(mmdll)]public static extern int waveOutWrite(IntPtr hWaveOut, ref WaveHdr lpWaveOutHdr, int uSize);[DllImport(mmdll)]public static extern int waveOutOpen(out IntPtr hWaveOut, int uDeviceID, WaveFormat lpFormat, WaveDelegate dwCallback, int dwInstance, int dwFlags);[DllImport(mmdll)]public static extern int waveOutReset(IntPtr hWaveOut);[DllImport(mmdll)]public static extern int waveOutClose(IntPtr hWaveOut);[DllImport(mmdll)]public static extern int waveOutPause(IntPtr hWaveOut);[DllImport(mmdll)]public static extern int waveOutRestart(IntPtr hWaveOut);[DllImport(mmdll)]public static extern int waveOutGetPosition(IntPtr hWaveOut, out int lpInfo, int uSize);[DllImport(mmdll)]public static extern int waveOutSetVolume(IntPtr hWaveOut, int dwVolume);[DllImport(mmdll)]public static extern int waveOutGetVolume(IntPtr hWaveOut, out int dwVolume);// WaveIn calls
[DllImport(mmdll)]public static extern int waveInGetNumDevs();[DllImport(mmdll)]public static extern int waveInAddBuffer(IntPtr hwi, ref WaveHdr pwh, int cbwh);[DllImport(mmdll)]public static extern int waveInClose(IntPtr hwi);[DllImport(mmdll)]public static extern int waveInOpen(out IntPtr phwi, int uDeviceID, WaveFormat lpFormat, WaveDelegate dwCallback, int dwInstance, int dwFlags);[DllImport(mmdll)]public static extern int waveInPrepareHeader(IntPtr hWaveIn, ref WaveHdr lpWaveInHdr, int uSize);[DllImport(mmdll)]public static extern int waveInUnprepareHeader(IntPtr hWaveIn, ref WaveHdr lpWaveInHdr, int uSize);[DllImport(mmdll)]public static extern int waveInReset(IntPtr hwi);[DllImport(mmdll)]public static extern int waveInStart(IntPtr hwi);[DllImport(mmdll)]public static extern int waveInStop(IntPtr hwi);}函式說明:
auxGetDevCaps
查詢指定的輔助輸出設備以確定其性能
auxGetNumDevs
檢取系統中存在的輔助輸出設備的數量
auxGetVolume
返回指定的輔助輸出設備的當前卷設備
auxOutMessage
向指定的輔助輸出設備發送一條消息
auxSetVolume
在指定的輔助輸出設備中設置卷
CloseDirver
關閉指定的可安裝驅動器
DefDriverProc
為任何不由可安裝驅動器處理的消息提供的缺省處理
Drivercallback
調用一個回調函數,發送一條消息給窗口或將一個線程的阻塞解除
DrvGetModuleHandle
返回包含指定可安裝驅動器模塊的實例句柄
DrvsendMessage
把指定的消息發送給可安裝驅動器
GetDriverModuleHandle
返回包含指定可安裝驅動器模塊的實例句柄
joyGetDevCaps
查詢指定的遊戲桿設備以確定其性能
joyGetNumDevs
返回系統支持的遊戲桿設備的數量
joyGetPos
查詢指定的遊戲桿設備的位置和活動性
joyGetPosEx
查詢一個遊戲桿設備的位置和它的按扭狀態
joyGetThreshold
查詢指定的遊戲桿設備的當前移動閾值
joyReleaseCapture
釋放由JoySetCapture函數設置的在指定遊戲桿設備上的捕獲
joySetCapture
發送一個遊戲桿消息到指定的窗口
joySetThreshold
設置指定的遊戲桿設備的移動閾值
mciGetCreatorTask
為指定的MCI設備檢取其創建的任務
mciGetDeviceID
返回和打開設備名相匹配的設備標識符
mciGetErrorString
檢取描述指定媒介控制接口錯誤代碼的字符串
mciGetYieldProc
返回和媒介控制接口的WAIT標誌相關的回調函數的地址
mciSendCommand
向指定的媒介控制接口設備發送一條命令
mciSendString
向指定的媒介控制接口設備發送一個字符串
mciSetYieldProc
設置一個過程地址,在MCI設備因指定了WAIT標誌而等待一個命令完成時,該過程被周期性調用
midiConnect
將指定的MIDI輸入設備連接到輸出設備
midiDisconnect
斷開MIDI輸入設備和輸出設備的連接
midiInAddBuffer
向指定的音樂儀器數字接口的輸入設備增加一個緩衝區
midiInClose
關閉指定的音樂儀器數字接口的輸入設備
midiInGetDveCaps
查詢指定的音樂儀器數字接口的輸入設備,以確定其性能
midiInGetErrorText
檢取有關音樂儀器數字接口的輸入設備指定錯誤的文本說明
midiInGetID
獲得一個音樂一起數字接口的輸入設備的標識符
midiInGetNumDevs
檢取系統中音樂儀器數字接口的輸入設備的數量
midiInMessage
向指定的音樂儀器數字接口的輸入設備驅動器發送一條消息
midiInOpen
打開指定的音樂儀器數字接口的輸入設備
midiInPrepareHeader
為音樂儀器數字接口的輸入設備準備一個緩衝區
midiInReset
在給定的MIDI輸入設備上輸入,並將所有掛起的輸入緩衝區標記為已執行的
midiInStart
啟動在指定的音樂儀器數字接口的輸入設備上的輸入
midiInStop
停止在給定的音樂儀器數字接口的輸入設備上的輸入
midiInUnprepareHeader
消除由midiInPrepareHeader函數完成的準備
midiOutCacheDrumPatches
請求內部的一個MIDI合成設備預裝指定的基於鍵的擊打音色集
midiOutCachePatches
請求內部的音樂儀器數字接口的合成設備預裝指定的音色集
midiOutClose
關閉指定的音樂儀器數字接口的輸出設備
midiOutGetDevCaps
查詢指定的音樂儀器數字接口的輸出設備,以確定其性能
midiOutGetErrorText
檢取有關MIDI輸出設備指定採取的文本說明
midiOutGetID
檢取指定的MIDI輸出設備的標識符
midiOutGetNumDevs
檢取系統中存在的MIDI輸出設備的數量
midiOutGetVolume
返回一個MIDI輸出設備的當前卷設置
midiOutLongMsg
向指定的MIDI輸出設備發送一條系統專用的MIDI消息
midiOutMessage
向一MIDI輸出設備驅動器發送一條消息
midiOutOpen
打開指定的MIDI輸出設備進行回放
midiOutPrepareHeader
為MIDI輸出設備準備一個緩衝區
midiOutReset
為指定的MIDI輸出設備關閉所有MIDI通道上的所有標誌
midiOutSetVolume
設置一個MIDI輸出設備的捲
midiOutShortMsg
向指定的MIDI輸出設備發送一條短MIDI消息
midiOutUnprepareHeader
清除由midiOutPrepareHeader函數完成的準備
midiStreamClose
關閉一個打開的MIDI流
midiStreamOpen
為輸出,打開一個MIDI流
midiStreamOut
在MIDI輸出設備上播放或排隊一個MIDI數據流
midiStreamPause
暫停一個MIDI流的播放
midiStreamPosition
在一個MIDI流中檢取當前位置
midiStreamProperty
設置或檢取與MIDI輸出設備相關MIDI數據流的特性
midiStreamRestart
重新啟動一個暫停的MIDI流
midiStreamStop
關掉指定MIDI輸出設備的所有MIDI通道
mixerClose
關閉指定的混頻器
mixerGetControlDetails
檢取和一個聲頻指線路相關的單一控件的細節
mixerGetDevCaps
查詢指定的混頻器以確定其性能
mixerGetID
獲取指定混頻器的標識符
mixerGetLineContrils
檢取和一個聲頻線路相關的一個或多個控件
mixerGetLineInfo
檢取混頻器有關特有線路的信息
mixerGetNumDevs
返回系統中存在的混頻器的數量
mixerMessage
把一個定制混頻器驅動器消息直接發送給混頻器驅動器
mixerOpen
打開指定的混頻器,在應用程序關閉該句柄前保證該設備不被移走
mixerSetControlDetails
設置和一個聲頻指線路相關的單一控件的細節
mmioAsvance
填充一個文件的IO緩衝區
mmioAscend
取出一個RIFF文件塊
mmioClose
關閉有mmioOpen打開的文件
mmioCreateChunk
創建由mmioOpen函數打開的RIFF文件中的一個塊
mmioDescend
進入由mmioOpen函數打開的RIFF文件的塊中,並查找一個塊
mmioFlush
把文件緩衝區的數據寫入磁盤中
mmioGetInfo
檢取有關由mmioOpen函數創建的RIFF文件的信息
mmioInstallIOProcA
裝入或刪除一個自定義的IO過程
mmioOpen
為輸入輸出打開一個文件
mmioRead
從由mmioOpen函數打開的文件中讀取指定字節數的數據
mmioRename
重新命名指定的文件
mmioSeek
改變由mmioOpen函數打開的文件中的當前指針位置
mmioSendMessage
向與指定文件相聯繫的IO過程發送一條消息
mmioSetBuffer
允許或禁止文件緩衝區的IO,或改變這個緩衝區,或改變這個緩衝區的大小
mmioSetInfo
更新從被打開文件中檢取的信息
mmioStringToFOURCC
把一個以NULL結束的字符串轉換成一個4字符代碼
mmioWrite
向由mmioOpen函數打開的文件中寫入指定字節數的數據
mmsystemGetVersion
返回多媒體擴展系統軟件的當前版本號
OpenDriver
打開一個可安裝驅動器實例,並用缺省設置或指定值初始化該實例
PlaySound
播放一個波形聲音
SendDriveMessage
向指定的可安裝驅動器發送一條消息
SndPlaySound
播放一個由文件名 或由登記的[sound]段的入口指定的波形聲音
timeBeginPeriod
設置應用程序或驅動程序使用的最小定時器分辨率
timeEndPeriod
清除應用程序或驅動程序使用的最小定時器分辨率
timeGetDevCaps
查詢定時器設備以確定其性能
timeGetSystemTime
檢取從WINDOWS開始已逝去的毫秒數
timeGetTime
檢取從WINDOWS開始已逝去的毫秒數,此函數比上一條函數開銷小
timeKillEvent
毀掉指定的定時器回調事件
timeSetEvent
設置一個定時器回調事件
waveInAddBuffer
向波形輸入設備添加一個輸入緩衝區
WaveInClose
關閉指定的波形輸入設置
waveInGetDevCaps
查詢指定的波形輸入設備以確定其性能
waveInGetErrorText
檢取由指定的錯誤代碼標識的文本說明
waveInGetID
獲取指定的波形輸入設備的標識符
waveInGetNumDevs
返回系統中存在的波形輸入設備的數量
waveInGetPosition
檢取指定波形輸入設備的當前位置
waveInMessage
發送一條消息給波形輸入設備的驅動器
waveInOpen
為錄音而打開一個波形輸入設備
waveInPrepareHeader
為波形輸入準備一個輸入緩衝區
waveInReset
停止給定的波形輸入設備的輸入,且將當前位置清零
waveInStart
啟動在指定的波形輸入設備的輸入
waveInStop
停止在指定的波形輸入設備上的輸入
waveInUnprepareHeader
清除由waveInPrepareHeader函數實現的準備
waveOutBreakLoop
中斷給定的波形輸出設備上一個循環,並允許播放驅動器列表中的下一個塊
waveOutClose
關閉指定的波形輸出設備
waveOutGetDevCaps
查詢一個指定的波形輸出設備以確定其性能
waveOutGetErrorText
檢取由指定的錯誤代碼標識的文本說明
waveOutGetID
檢取指定的波形輸出設備的標識符
waveOutGetNumDevs
檢取系統中存在的波形輸出設備的數量
waveOutGetPitch
查詢一個波形輸出設備的當前音調設置
waveOutGetPlaybackRate
查詢一個波形輸出設備當前播放的速度
waveOutGetPosition
檢取指定波形輸出設備的當前播放位置
waveOutGetVolume
查詢指定波形輸出設備的當前音量設置
waveOutMessage
發送一條消息給一個波形輸出設備的驅動器
waveOutOpen
為播放打開一個波形輸出設備
waveOutPause
暫停指定波形輸出設備上的播放
waveOutPrepareHeader
為播放準備一個波形緩衝區
waveOutRestart
重新啟動一個被暫停的波形輸出設備
waveOutSetPitch
設置一個波形輸出設備的音調
waveOutSetPlaybackRate
設置指定波形輸出設備的速度
waveOutSetVolume
設置指定的波形輸出設備的音量
waveOutUnprepareHeader
清除由waveOutPrepareHeader函數實現的準備
waveOutWrite
向指定的波形輸出設備發送一個數據塊
異世界
2012年11月9日 星期五
C# 音頻程式 -- WinMM.dll 函數匯總
訂閱:
張貼留言 (Atom)
沒有留言:
張貼留言