異世界


2012年11月9日 星期五

C# 音頻程式 -- WinMM.dll 函數匯總

資料參考: 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 list
    private 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 error
 
    public 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 FARPROC 
 
    public const int TIME_MS = 0x0001;  // time in milliseconds 
    public const int TIME_SAMPLES = 0x0002;  // number of wave samples 
    public 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 buffer
        public int dwBufferLength; // length of data buffer
        public int dwBytesRecorded; // used for input only
        public IntPtr dwUser; // for client's use
        public int dwFlags; // assorted flags (see defines)
        public int dwLoops; // loop control counter
        public IntPtr lpNext; // PWaveHdr, reserved for driver
        public 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


向指定的波形輸出設備發送一個數據塊

沒有留言:

張貼留言