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;
    }
    }

  • 相关阅读:
    leetcode 33. Search in Rotated Sorted Array
    leetcode 32. Longest Valid Parentheses
    leetcode 28. Implement strStr()
    leetcode 27. Remove Element
    leetcode 26. Remove Duplicates from Sorted Array
    leetcode 24. Swap Nodes in Pairs
    leetcode 22. Generate Parentheses
    树莓派的频率管理和热控制
    sql执行insert插入一条记录同时获取刚插入的id
    全程直播个人博客重构过程,采用springboot+dubbo+jpa技术栈。
  • 原文地址:https://www.cnblogs.com/hqu-ye/p/4315937.html
Copyright © 2011-2022 走看看