zoukankan      html  css  js  c++  java
  • 音频播放和录制检测

    #ifndef __WWAVEHELPER_H__
    #define __WWAVEHELPER_H__

    #if !WINDOWS_SYSTEM
    #error only windows system supported
    #endif

    #include <mmsystem.h>
    #pragma comment(lib, "winmm.lib")

    #include "uiHelper.h"

    class UIHELPER_EXPORT wWaveHelper
    {
    public:
    /************************playback about***************/
    static int GetPlaybackDevicesCounts();
    static int GetPlaybackIDByName(const chConstString& strDevName);
    static chStringA GetPalybackNameByID(int nID);

    /************************Record About*****************/
    static int GetRecordDevicesCounts();
    static int GetRecordIDByName(const chConstString& strDevName);
    static chStringA GetRecordNameByID(int nID);
    public:
    wWaveHelper();
    ~wWaveHelper();
    };

    class UIHELPER_EXPORT wMixerCtrl
    {
    public:
    BOOL OpenMixer(int iIndex);
    BOOL OpenMixer(const chConstString& strAudioName);
    void CloseMixer();
    //volum just can get special metrics of an audio line
    int GetPlaybackVolum();
    int GetCaptureVolum();
    BOOL SetPlaybackVolum(int nValue);
    BOOL SetCaptureVolum(int nValue);
    //mute
    bool GetMasterVolumeMute();
    bool SetMasterVolumeMute(bool bMute);
    bool GetWaveVolumeMute();
    bool SetWaveVolumeMute(bool bMute);
    private:
    int GetVolum(int nType);
    BOOL SetVolum(int nType, int nValue);

    BOOL GetMute(int nType);
    BOOL SetMute(int nType, BOOL bMute);
    public:
    wMixerCtrl();
    wMixerCtrl(int iIndex);
    wMixerCtrl(const chConstString& strAudioName);
    ~wMixerCtrl();
    public:
    HMIXER m_hMixer;
    };

    class UIHELPER_EXPORT wWavePlayer
    {
    public:
    bool wavePlayStart(UINT idDev, const chConstString& strFilePath);
    void wavePlayStop();
    int getCurrentSample();
    public:
    wWavePlayer();
    ~wWavePlayer();
    private:
    HWAVEOUT m_hWaveOut;
    chByteArray m_dataWaveFile;
    WAVEHDR m_hdrWaveData;
    public:
    UINT64 m_tickStart;
    };

    class CWaveIn;
    class UIHELPER_EXPORT wWaveRecord :public chCriticalSection
    {
    public:
    bool waveRecordStart(UINT idDev);
    void waveRecordStop();
    int getCurrentSample();
    public:
    wWaveRecord();
    ~wWaveRecord();
    public:
    bool m_bRecording;//停止标志,因为这里在WIM_DATA 是不断AddBuff,要靠其它变量去控制,停止
    HWAVEIN m_hWaveIn;
    private:
    WAVEHDR m_hdrWaveData[2];
    chByteArray m_dataWaveIn;
    UINT64 m_tickStart;
    CWaveIn* m_pWaveInThread;
    };


    #endif //__WWAVEHELPER_H__

    #include "ETLLib/ETLLib.hpp"
    #include "wWaveHelper.h"
    #define THIS_MODULE "wWaveHelper"

    int wWaveHelper::GetPlaybackDevicesCounts()
    {
    return ::waveOutGetNumDevs();
    }

    int wWaveHelper::GetPlaybackIDByName(const chConstString& strDevName)
    {
    chASSERT(!strDevName.empty());
    chStringW strDevNameW = chUTF82W(strDevName);
    WAVEOUTCAPSW outcaps;
    int nCount = ::waveOutGetNumDevs();
    for(int uOutId = 0; uOutId < nCount; uOutId++)
    {
    if (::waveOutGetDevCapsW(uOutId, &outcaps, sizeof(outcaps)) == MMSYSERR_NOERROR)
    {
    if(strDevNameW == outcaps.szPname)
    {
    return uOutId;
    }
    }
    }
    return WAVE_MAPPER;
    }

    chStringA wWaveHelper::GetPalybackNameByID(int nID)
    {
    chASSERT(nID >= -1);
    WAVEOUTCAPSW outcaps;
    if (::waveOutGetDevCapsW(nID, &outcaps, sizeof(WAVEOUTCAPSW)) != MMSYSERR_NOERROR)
    {
    return NULL;
    }
    return chW2UTF8(outcaps.szPname);
    }

    int wWaveHelper::GetRecordDevicesCounts()
    {
    return ::waveInGetNumDevs();
    }

    int wWaveHelper::GetRecordIDByName(const chConstString& strDevName)
    {
    chASSERT(!strDevName.empty());
    chStringW strDevNameW = chUTF82W(strDevName);
    WAVEINCAPSW incaps;
    int nCount = ::waveInGetNumDevs();
    for(int uInId = 0; uInId < nCount; uInId++)
    {
    if (::waveInGetDevCapsW(uInId, &incaps, sizeof(incaps)) == MMSYSERR_NOERROR )
    {
    if(strDevNameW == incaps.szPname)
    {
    return uInId;
    }
    }
    }
    return WAVE_MAPPER;
    }

    chStringA wWaveHelper::GetRecordNameByID(int nID)
    {
    chASSERT(nID >= -1);
    WAVEINCAPSW incaps;
    if (::waveInGetDevCapsW(nID, &incaps, sizeof(incaps)) != MMSYSERR_NOERROR)
    {
    return NULL;
    }
    return chW2UTF8(incaps.szPname);
    }

    wWaveHelper::wWaveHelper()
    {

    }

    wWaveHelper::~wWaveHelper()
    {

    }


    static int GetAudioIDByName(const chConstString& strDevName)
    {
    chASSERT(!strDevName.empty());
    chStringW strDevNameW = chUTF82W(strDevName);
    MIXERCAPSW mixCaps;
    int nNumMixers = ::mixerGetNumDevs();
    for(int uMxId = 0; uMxId < nNumMixers; uMxId++)
    {
    if (::mixerGetDevCapsW(uMxId, &mixCaps, sizeof(mixCaps)) == MMSYSERR_NOERROR)
    {
    if(strDevNameW == mixCaps.szPname)
    {
    return uMxId;
    }
    }
    }
    return WAVE_MAPPER;
    }


    BOOL wMixerCtrl::OpenMixer(int iIndex)
    {
    chASSERT(iIndex >= 0);
    chASSERT(m_hMixer == NULL);
    if (::mixerGetNumDevs() == 0)
    {
    return FALSE;
    }
    mixerOpen(&m_hMixer, iIndex, 0, 0, CALLBACK_NULL);
    chASSERT(m_hMixer != NULL);
    //SYZ_TRACE("OpenMixer : %d - %X", iIndex, m_hMixer);
    return TRUE;
    }

    BOOL wMixerCtrl::OpenMixer(const chConstString& strAudioName)
    {
    int iIndex = GetAudioIDByName(strAudioName);
    return OpenMixer(iIndex);
    }

    void wMixerCtrl::CloseMixer()
    {
    if(m_hMixer != NULL)
    {
    mixerClose(m_hMixer);
    m_hMixer = NULL;
    }
    }

    int wMixerCtrl::GetVolum(int nType)
    {
    chASSERT(m_hMixer != NULL);
    // Get the line info for the wave in destination line
    MIXERLINE mxl;
    mxl.cbStruct = sizeof(mxl);
    mxl.dwComponentType = nType;
    mixerGetLineInfo((HMIXEROBJ)m_hMixer, &mxl, MIXER_GETLINEINFOF_COMPONENTTYPE);

    // Find a volume control, if any, of the microphone line
    MIXERCONTROL mxctrl = {0};
    MIXERLINECONTROLS mxlctrl =
    {
    sizeof mxlctrl, mxl.dwLineID, MIXERCONTROL_CONTROLTYPE_VOLUME,
    1, sizeof MIXERCONTROL, &mxctrl
    };

    int uVal = 0;
    if(mixerGetLineControls((HMIXEROBJ) m_hMixer, &mxlctrl, MIXER_GETLINECONTROLSF_ONEBYTYPE) == MMSYSERR_NOERROR)
    {
    // Found!
    int cChannels = mxl.cChannels;
    if (MIXERCONTROL_CONTROLF_UNIFORM & mxctrl.fdwControl)
    cChannels = 1;
    chASSERT(cChannels > 0);
    chSimpleArray<MIXERCONTROLDETAILS_UNSIGNED> valArray(cChannels);

    MIXERCONTROLDETAILS mxcd = {sizeof(mxcd), mxctrl.dwControlID,
    cChannels, (HWND)0,
    sizeof MIXERCONTROLDETAILS_UNSIGNED, (MIXERCONTROLDETAILS_UNSIGNED*)valArray};

    mixerGetControlDetails((HMIXEROBJ)m_hMixer, &mxcd, MIXER_GETCONTROLDETAILSF_VALUE);
    double dVolTotal = 0;
    for(int i = 0; i < cChannels; i++)
    dVolTotal += valArray[i].dwValue;
    uVal = (int)(dVolTotal / cChannels);
    }
    //SYZ_TRACE("GetVolume : %d-%X", nType, uVal);
    return uVal;
    }


    int wMixerCtrl::GetPlaybackVolum()
    {
    return GetVolum(MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT);
    }

    int wMixerCtrl::GetCaptureVolum()
    {
    return GetVolum(MIXERLINE_COMPONENTTYPE_DST_SPEAKERS);
    }

    BOOL wMixerCtrl::SetVolum(int nType, int nValue)
    {
    chASSERT(m_hMixer != NULL);
    // Get the line info for the wave in destination line
    MIXERLINE mxl;
    mxl.cbStruct = sizeof(mxl);
    mxl.dwComponentType = nType;
    mixerGetLineInfo((HMIXEROBJ)m_hMixer, &mxl, MIXER_GETLINEINFOF_COMPONENTTYPE);

    // Find a volume control, if any, of the microphone line
    MIXERCONTROL mxctrl = {0};
    MIXERLINECONTROLS mxlctrl =
    {
    sizeof mxlctrl, mxl.dwLineID, MIXERCONTROL_CONTROLTYPE_VOLUME,
    1, sizeof MIXERCONTROL, &mxctrl
    };

    if(mixerGetLineControls((HMIXEROBJ) m_hMixer, &mxlctrl, MIXER_GETLINECONTROLSF_ONEBYTYPE) == MMSYSERR_NOERROR)
    {
    // Found!
    int cChannels = mxl.cChannels;
    if (MIXERCONTROL_CONTROLF_UNIFORM & mxctrl.fdwControl)
    cChannels = 1;
    chASSERT(cChannels > 0);

    chSimpleArray<MIXERCONTROLDETAILS_UNSIGNED> valArray(cChannels);
    for(int i = 0; i < cChannels; i++)
    {
    valArray[i].dwValue = nValue;
    }

    MIXERCONTROLDETAILS mxcd = {sizeof(mxcd), mxctrl.dwControlID,
    cChannels, (HWND)0,
    sizeof MIXERCONTROLDETAILS_UNSIGNED, (MIXERCONTROLDETAILS_UNSIGNED*)valArray};

    mixerSetControlDetails((HMIXEROBJ)m_hMixer, &mxcd, MIXER_SETCONTROLDETAILSF_VALUE);
    }
    //SYZ_TRACE("SetVolume : %d-%X", nType, uVal);
    return TRUE;
    }

    BOOL wMixerCtrl::SetPlaybackVolum(int nValue)
    {
    return GetVolum(MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT);
    }

    BOOL wMixerCtrl::SetCaptureVolum(int nValue)
    {
    return GetVolum(MIXERLINE_COMPONENTTYPE_DST_SPEAKERS);
    }

    BOOL wMixerCtrl::GetMute(int nType)
    {
    chASSERT(m_hMixer != NULL);
    MIXERLINE mxl;
    mxl.cbStruct = sizeof(MIXERLINE);
    mxl.dwComponentType = nType;
    if (mixerGetLineInfo((HMIXEROBJ)m_hMixer, &mxl, MIXER_GETLINEINFOF_COMPONENTTYPE) != MMSYSERR_NOERROR)
    {
    WARNING_TRACE("GetMute-mixerGetLineInfo Failed!");
    return FALSE;
    }

    // Find a volume control, if any, of the microphone line
    MIXERCONTROL mxctrl = {0};
    MIXERLINECONTROLS mxlctrl =
    {
    sizeof mxlctrl, mxl.dwLineID, MIXERCONTROL_CONTROLTYPE_MUTE,
    1, sizeof MIXERCONTROL, &mxctrl
    };

    if(mixerGetLineControls((HMIXEROBJ) m_hMixer, &mxlctrl, MIXER_GETLINECONTROLSF_ONEBYTYPE) == MMSYSERR_NOERROR)
    {
    MIXERCONTROLDETAILS mxcd;
    MIXERCONTROLDETAILS_BOOLEAN mxcdMute;
    mxcd.hwndOwner = 0;
    mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
    mxcd.dwControlID = mxctrl.dwControlID;
    mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN);
    mxcd.paDetails = &mxcdMute;
    mxcd.cChannels = MIXERCONTROL_CONTROLF_UNIFORM;
    mxcd.cMultipleItems = 0;
    if (mixerGetControlDetails((HMIXEROBJ)m_hMixer, &mxcd, MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE) == MMSYSERR_NOERROR)
    {
    return mxcdMute.fValue;
    }
    WARNING_TRACE("GetMute-mixerGetControlDetails Failed!");
    }
    WARNING_TRACE("GetMute-mixerGetLineControls Failed!");
    return FALSE;
    }

    bool wMixerCtrl::GetMasterVolumeMute()
    {
    return GetMute(MIXERLINE_COMPONENTTYPE_DST_SPEAKERS) != FALSE;
    }

    bool wMixerCtrl::GetWaveVolumeMute()
    {
    return GetMute(MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT) != FALSE;
    }

    BOOL wMixerCtrl::SetMute(int nType, BOOL bMute)
    {
    chASSERT(m_hMixer != NULL);
    MIXERLINE mxl;
    mxl.cbStruct = sizeof(MIXERLINE);
    mxl.dwComponentType = nType;
    if (mixerGetLineInfo((HMIXEROBJ)m_hMixer, &mxl, MIXER_GETLINEINFOF_COMPONENTTYPE) != MMSYSERR_NOERROR)
    {
    WARNING_TRACE("SetMute-mixerGetLineInfo Failed!");
    return FALSE;
    }

    MIXERCONTROL mxctrl = {0};
    MIXERLINECONTROLS mxlctrl =
    {
    sizeof mxlctrl, mxl.dwLineID, MIXERCONTROL_CONTROLTYPE_MUTE,
    1, sizeof MIXERCONTROL, &mxctrl
    };

    if(mixerGetLineControls((HMIXEROBJ) m_hMixer, &mxlctrl, MIXER_GETLINECONTROLSF_ONEBYTYPE) == MMSYSERR_NOERROR)
    {
    MIXERCONTROLDETAILS mxcd;
    MIXERCONTROLDETAILS_BOOLEAN mxcdMute;
    mxcdMute.fValue = bMute;
    mxcd.hwndOwner = 0;
    mxcd.dwControlID = mxctrl.dwControlID;
    mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
    mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN);
    mxcd.paDetails = &mxcdMute;
    mxcd.cChannels = MIXERCONTROL_CONTROLF_UNIFORM ;
    mxcd.cMultipleItems = 0;

    if (mixerSetControlDetails((HMIXEROBJ)m_hMixer, &mxcd, MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE) == MMSYSERR_NOERROR)
    {
    return TRUE;
    }
    WARNING_TRACE("SetMute-mixerSetControlDetails Failed!");
    }
    WARNING_TRACE("SetMute-mixerGetLineControls Failed!");
    return FALSE;
    }

    bool wMixerCtrl::SetMasterVolumeMute(bool bMute)
    {
    return SetMute(MIXERLINE_COMPONENTTYPE_DST_SPEAKERS, bMute) != FALSE;
    }

    bool wMixerCtrl::SetWaveVolumeMute(bool bMute)
    {
    return SetMute(MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT, bMute) != FALSE;
    }

    wMixerCtrl::wMixerCtrl()
    {
    m_hMixer = NULL;
    }
    wMixerCtrl::wMixerCtrl(int iIndex)
    {
    m_hMixer = NULL;
    OpenMixer(iIndex);
    }
    wMixerCtrl::wMixerCtrl(const chConstString& strAudioName)
    {
    m_hMixer = NULL;
    OpenMixer(strAudioName);
    }

    wMixerCtrl::~wMixerCtrl()
    {
    if (m_hMixer != NULL)
    {
    CloseMixer();
    }
    }

    struct WAVEHEAD{
    char riffTag[4];
    char dataLen[4];
    char waveTag[4];
    char fmtTag[4];
    char resvr[4];
    char dataType[2];
    char channelTag[2];
    char SamplesPerSecTag[4];
    char DataTransferRatePerSec[4];
    char BitsPerSample[2];
    char PCM[2];
    char fact[4];
    char filesize[4];
    public:
    bool operator == (const WAVEHEAD& head) const
    {
    return (memcmp(head.riffTag, riffTag, 4) == 0
    && memcmp(head.waveTag, waveTag, 4) == 0
    && memcmp(head.fmtTag, fmtTag, 4) == 0
    && memcmp(head.channelTag, channelTag, 2) == 0
    && memcmp(head.SamplesPerSecTag, SamplesPerSecTag, 4) == 0
    && memcmp(head.BitsPerSample, BitsPerSample, 2) == 0);
    }
    };


    static bool is8k16bitWaveData(const chByteArray& data)
    {
    static WAVEHEAD wave8K16bit = {
    {'R', 'I', 'F', 'F'},
    {},
    {'W', 'A', 'V', 'E'},
    {'f', 'm', 't', ' '},
    {},
    {},
    {0x1, 0x0},
    {0x40, 0x1f, 0x0, 0x0},
    {},
    {0x2, 0x0}
    };
    WAVEHEAD* pFileFmt = (WAVEHEAD*)data.data();
    return data.size() >= sizeof(WAVEHEAD) && wave8K16bit == *pFileFmt;
    }

    bool wWavePlayer::wavePlayStart(UINT idDev, const chConstString& strFilePath)
    {
    m_dataWaveFile = etlDumpBinFile(strFilePath);
    if(m_dataWaveFile.empty())
    {
    INFO_TRACE("Unable to load file");
    return false;
    }

    chASSERT(is8k16bitWaveData(m_dataWaveFile));

    WAVEFORMATEX wfx; /* look this up in your documentation */
    wfx.nSamplesPerSec = 8000; /* sample rate */
    wfx.wBitsPerSample = 16; /* sample size */
    wfx.nChannels = 1; /* channels*/
    wfx.cbSize = 0; /* size of _extra_ info */
    wfx.wFormatTag = WAVE_FORMAT_PCM;
    wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels;
    wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;

    if(waveOutOpen(&m_hWaveOut,
    idDev,
    &wfx,
    0,
    0,
    CALLBACK_NULL) != MMSYSERR_NOERROR)
    {
    INFO_TRACE("unable to open WAVE_MAPPER device");
    return false;
    }

    INFO_TRACE("The Wave Mapper device was opened successfully!");

    ZeroMemory(&m_hdrWaveData, sizeof(WAVEHDR));
    m_hdrWaveData.lpData = (LPSTR)m_dataWaveFile.data() + sizeof(WAVEHEAD);
    m_hdrWaveData.dwBufferLength = m_dataWaveFile.size() - sizeof(WAVEHEAD) ;
    m_hdrWaveData.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
    m_hdrWaveData.dwLoops = -1;

    waveOutPrepareHeader(m_hWaveOut, &m_hdrWaveData, sizeof(WAVEHDR));
    waveOutWrite(m_hWaveOut, &m_hdrWaveData, sizeof(WAVEHDR));
    m_tickStart = etlGetTickCount();
    return true;
    }

    void wWavePlayer::wavePlayStop()
    {
    if (m_hWaveOut != NULL)
    {
    waveOutReset(m_hWaveOut);
    waveOutUnprepareHeader(m_hWaveOut, &m_hdrWaveData, sizeof(WAVEHDR));
    waveOutClose(m_hWaveOut);
    m_hWaveOut = NULL;
    m_tickStart = 0;
    }
    }
    int wWavePlayer::getCurrentSample()
    {
    //chASSERT(m_Playblock.size() != 0);
    //1毫秒偏移16byte ===> 16*1*8000/1000/8 = 16byte
    UINT64 nByteOffset = (etlGetTickCount() - m_tickStart) * 16;
    int iByteOffset = (int)(nByteOffset % (m_dataWaveFile.size() - sizeof(WAVEHEAD)));
    LPBYTE pWaveData = m_dataWaveFile.data() + sizeof(WAVEHEAD);
    return chMAKEWORD(pWaveData[iByteOffset + 1], pWaveData[iByteOffset]);
    }

    wWavePlayer::wWavePlayer()
    {
    m_hWaveOut = NULL;
    m_tickStart = 0;
    }

    wWavePlayer::~wWavePlayer()
    {
    wavePlayStop();
    }


    #define MAX_BUFF_SOUNDSIZE 3200

    //////////////////////////////////////////////////////////////////////////
    //use thread process msg
    DWORD WINAPI AudioInThreadProc(LPVOID lpParameter)
    {
    SYZ_TRACE("AudioInThreadProc start. ");
    MSG msg;
    while(GetMessage(&msg,0,0,0))
    {
    switch(msg.message )
    {
    case MM_WIM_OPEN:
    SYZ_TRACE("MM_WIM_OPEN ");
    break;
    case MM_WIM_CLOSE:
    SYZ_TRACE("MM_WIM_CLOSE ");
    break;
    case MM_WIM_DATA:
    WAVEHDR* pWaveHdr = (WAVEHDR*)msg.lParam;//dwParam1指向WAVEHDR的地址
    //waveInUnprepareHeader((HWAVEIN)msg.wParam, pWaveHdr, sizeof(WAVEHDR));
    if(pWaveHdr->dwBytesRecorded != MAX_BUFF_SOUNDSIZE)
    {
    //clear dirty data
    memset(pWaveHdr->lpData, 0, MAX_BUFF_SOUNDSIZE);
    break;
    }
    pWaveHdr->dwBytesRecorded = 0;
    pWaveHdr->dwFlags = 0;
    waveInPrepareHeader((HWAVEIN)msg.wParam, pWaveHdr, sizeof(WAVEHDR));
    waveInAddBuffer((HWAVEIN)msg.wParam, pWaveHdr, sizeof(WAVEHDR));
    break;
    }
    }
    SYZ_TRACE("AudioInThreadProc exit. ");
    return msg.wParam;
    }
    class CWaveIn
    {
    public:
    BOOL StartThread()
    {
    m_hAudioIn = CreateThread(0, 0, AudioInThreadProc, this, 0, &m_dwAudioInId);
    if(m_hAudioIn == NULL)
    {
    SYZ_TRACE("CWaveIn::StartThread: Strat wave in thread fail. ");
    return FALSE;
    }
    return TRUE;
    }
    CWaveIn()
    {
    m_dwAudioInId = 0;
    if (!StartThread())
    {
    m_dwAudioInId = 0;
    }
    }
    ~CWaveIn()
    {
    if (m_dwAudioInId != NULL)
    {
    TerminateThread(m_hAudioIn, 0);
    }
    }
    public:
    DWORD m_dwAudioInId;
    private:
    HANDLE m_hAudioIn;
    };
    //////////////////////////////////////////////////////////////////////////
    DWORD CALLBACK waveInProc(HWAVEIN hWaveIn, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
    {
    SYZ_TRACE("waveInProc:: hWaveIn: point[%p] uMsg==[%d]", hWaveIn, uMsg);
    if (uMsg == WIM_DATA)
    {
    WAVEHDR* pWaveHdr = (WAVEHDR*)dwParam1;//dwParam1指向WAVEHDR的地址
    wWaveRecord* pWaveRecord = (wWaveRecord*)dwInstance;
    SYZ_TRACE("WAVEHDR stuct data:
    lpData[%p], dwBufferLength[%d], dwBytesRecorded[%d], dwUser[%p], dwFlags[%d], dwLoops[%d], lpNext[%p], reserved[%p]",
    pWaveHdr->lpData, pWaveHdr->dwBufferLength, pWaveHdr->dwBytesRecorded, pWaveHdr->dwUser, pWaveHdr->dwFlags, pWaveHdr->dwLoops, pWaveHdr->lpNext, pWaveHdr->reserved);
    pWaveRecord->Lock();
    if (pWaveRecord->m_bRecording && pWaveHdr->dwBytesRecorded == MAX_BUFF_SOUNDSIZE)
    {
    //waveInUnprepareHeader(hWaveIn, pWaveHdr, sizeof(WAVEHDR));
    pWaveHdr->dwBytesRecorded = 0;
    pWaveHdr->dwFlags = 0;
    SYZ_TRACE("befor call waveInPrepareHeader");
    MMRESULT hr = waveInPrepareHeader(hWaveIn, pWaveHdr, sizeof(WAVEHDR));
    SYZ_TRACE("waveInPrepareHeader result [%d]", (hr == MMSYSERR_NOERROR));
    hr = waveInAddBuffer(hWaveIn, pWaveHdr, sizeof(WAVEHDR));
    SYZ_TRACE("waveInAddBuffer result [%d]", (hr == MMSYSERR_NOERROR));
    }
    else
    {
    //clear dirty data
    memset(pWaveHdr->lpData, 0, MAX_BUFF_SOUNDSIZE);
    }
    pWaveRecord->Unlock();
    }
    else
    {
    //SYZ_TRACE("waveInProc:: hWaveIn: point[%p] uMsg==[%d]", &hWaveIn, uMsg);
    }
    return 0;
    }

    bool wWaveRecord::waveRecordStart(UINT idDev)
    {
    WAVEFORMATEX wfx;
    memset(&wfx, 0, sizeof(wfx));
    wfx.wFormatTag = WAVE_FORMAT_PCM;
    wfx.nChannels = 1;
    wfx.nSamplesPerSec = 8000 ;
    wfx.wBitsPerSample = 16;
    wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels;;
    wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
    wfx.cbSize = 0;

    if (m_pWaveInThread == NULL)
    {
    INFO_TRACE("waveIn callBack_Thread creater failed");
    }
    //CALLBACK_THREAD
    /*if(waveInOpen(&m_hWaveIn,
    idDev,
    &wfx,
    (DWORD_PTR)(m_pWaveInThread->m_dwAudioInId),
    (DWORD)this,
    CALLBACK_THREAD) != MMSYSERR_NOERROR)
    {
    INFO_TRACE("unable to open waveIn device");
    return false;
    };*/
    //CALLBACK_FUNCTION
    if(waveInOpen(&m_hWaveIn,
    idDev,
    &wfx,
    (DWORD_PTR)(waveInProc),
    (DWORD)this,
    CALLBACK_FUNCTION) != MMSYSERR_NOERROR)
    {
    INFO_TRACE("unable to open waveIn device");
    return false;
    };
    m_dataWaveIn.resize(MAX_BUFF_SOUNDSIZE * chLENOF(m_hdrWaveData));
    for (int i = 0; i < chLENOF(m_hdrWaveData); ++i)
    {
    m_hdrWaveData[i].lpData = (LPSTR)m_dataWaveIn.data() + MAX_BUFF_SOUNDSIZE * i;
    m_hdrWaveData[i].dwBufferLength = MAX_BUFF_SOUNDSIZE;
    m_hdrWaveData[i].dwBytesRecorded = 0;
    m_hdrWaveData[i].dwFlags = 0;
    waveInPrepareHeader(m_hWaveIn, &m_hdrWaveData[i], sizeof(WAVEHDR));
    waveInAddBuffer(m_hWaveIn, &m_hdrWaveData[i], sizeof(WAVEHDR));
    }
    Lock();
    m_bRecording = true;
    Unlock();
    waveInStart(m_hWaveIn);
    return true;
    }

    void wWaveRecord::waveRecordStop()
    {
    if (m_hWaveIn != NULL)
    {
    Lock();
    m_bRecording = false;
    Unlock();
    waveInStop(m_hWaveIn);
    waveInReset(m_hWaveIn);
    for (int i = 0; i < chLENOF(m_hdrWaveData); ++i)
    {
    waveInUnprepareHeader(m_hWaveIn, &m_hdrWaveData[i], sizeof(WAVEHDR));
    }
    waveInClose(m_hWaveIn);
    m_hWaveIn = NULL;
    m_tickStart = 0;
    }
    }

    int wWaveRecord::getCurrentSample()
    {
    UINT64 nByteOffset = (etlGetTickCount() - m_tickStart) * 16;
    int iByteOffset = (int)(nByteOffset % m_dataWaveIn.size());
    LPBYTE pWaveData = m_dataWaveIn.data();
    return chMAKEWORD(pWaveData[iByteOffset + 1], pWaveData[iByteOffset]);
    }

    wWaveRecord::wWaveRecord()
    {
    m_bRecording = false;
    m_hWaveIn = NULL;
    m_tickStart = 0;
    m_pWaveInThread = new CWaveIn();
    }

    wWaveRecord::~wWaveRecord()
    {
    waveRecordStop();
    if (m_pWaveInThread != NULL)
    {
    delete m_pWaveInThread;
    }
    }

  • 相关阅读:
    Disruptor-NET和内存栅栏
    SSDB:高性能数据库服务器
    PostgreSQL配置优化
    ADO.NET的弹性连接控制[ADO.NET idle connection resiliency]
    2013年度IT博客大赛跻身10强
    MongoDB 聚合管道(Aggregation Pipeline)
    验证码类库CaptchaMvc
    AngularJS SPA Template For Visual Studio
    .NET 4.0 版本号
    利用SSH Filesystem实现远程文件系统
  • 原文地址:https://www.cnblogs.com/hqu-ye/p/4315937.html
Copyright © 2011-2022 走看看