zoukankan      html  css  js  c++  java
  • 音频播放(小文件循环播放)

    //utility   读取内存可以是用该方法

    static LPSTR loadAudioBlock(char* filename, DWORD* blockSize)
    {
    HANDLE hFile= INVALID_HANDLE_VALUE;
    DWORD size = 0;
    DWORD readBytes = 0;
    void* block = NULL;
    /*
    * open the file
    */
    if((hFile = CreateFile(
    filename,
    GENERIC_READ,
    FILE_SHARE_READ,
    NULL,
    OPEN_EXISTING,
    0,
    NULL
    )) == INVALID_HANDLE_VALUE)
    return NULL;
    /*
    * get it's size, allocate memory and read the file
    * into memory. don't use this on large files!
    */
    do {
    if((size = GetFileSize(hFile, NULL)) == 0)
    break;
    if((block = HeapAlloc(GetProcessHeap(), 0, size)) == NULL)
    break;
    ReadFile(hFile, block, size, &readBytes, NULL);
    } while(0);
    CloseHandle(hFile);
    *blockSize = size;
    return (LPSTR)block;
    }

    //end utility

    #ifndef __WWAVEHELPER_H__
    #define __WWAVEHELPER_H__

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

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

    //#include <mmreg.h>
    class wWaveHelper
    {
    public:
    /************************playback about***************/
    int GetPlaybackIDByName(const chConstString& strDevName);
    chString GetPalybackNameByID(int nID);

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

    class 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);
    BOOL GetMute(int nType);
    BOOL SetMute(int nType, BOOL BMute);
    private:
    int GetVolum(int nType);
    BOOL SetVolum(int nType, int nValue);
    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_wavePlayBlocks;
    WAVEHDR m_blockOne;
    WAVEHDR m_blockTwo;
    public:
    UINT64 m_playStartTimer;
    };

    class wWaveRecord
    {
    public:
    bool waveRecordStart(UINT idDev);
    void waveRecordStop();
    int getCurrentSample();
    public:
    wWaveRecord();
    ~wWaveRecord();
    private:
    HWAVEIN m_hWaveIn;
    WAVEHDR* m_waveRecordBlocks;
    UINT64 m_RecordStartTimer;
    };


    #endif //__WWAVEHELPER_H__

    //implementation

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

    int wWaveHelper::GetPlaybackIDByName(const chConstString& strDevName)
    {
    chASSERT(!strDevName.empty());
    WAVEOUTCAPS outcaps;
    int nCount = ::waveOutGetNumDevs();
    for(int uOutId = 0; uOutId < nCount; uOutId++)
    {
    if (::waveOutGetDevCaps(uOutId, &outcaps, sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR)
    {
    if(ACC::equ(strDevName, outcaps.szPname))
    {
    return uOutId;
    }
    }
    }
    return WAVE_MAPPER;
    }

    chString wWaveHelper::GetPalybackNameByID(int nID)
    {
    chASSERT(nID >= -1);
    WAVEOUTCAPS outcaps;
    if (::waveOutGetDevCaps(nID, &outcaps, sizeof(WAVEOUTCAPS)) != MMSYSERR_NOERROR)
    {
    return NULL;
    }
    return outcaps.szPname;
    }

    int wWaveHelper::GetRecordIDByName(const chConstString& strDevName)
    {
    chASSERT(!strDevName.empty());
    WAVEINCAPS incaps;
    int nCount = ::waveInGetNumDevs();
    for(int uInId = 0; uInId < nCount; uInId++)
    {
    if (::waveInGetDevCaps(uInId, &incaps, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR )
    {
    if(ACC::equ(strDevName, incaps.szPname))
    {
    return uInId;
    }
    }
    }
    return WAVE_MAPPER;
    }

    chString wWaveHelper::GetRecordNameByID(int nID)
    {
    chASSERT(nID >= -1);
    WAVEINCAPS incaps;
    if (::waveInGetDevCaps(nID, &incaps, sizeof(WAVEINCAPS)) != MMSYSERR_NOERROR)
    {
    return NULL;
    }
    return incaps.szPname;
    }

    wWaveHelper::wWaveHelper()
    {

    }

    wWaveHelper::~wWaveHelper()
    {

    }


    static int GetAudioIDByName(const chConstString& strDevName)
    {
    chASSERT(!strDevName.empty());

    MIXERCAPS mixCaps;
    int nNumMixers = ::mixerGetNumDevs();
    for(int uMxId = 0; uMxId < nNumMixers; uMxId++)
    {
    if (::mixerGetDevCaps(uMxId, &mixCaps, sizeof(MIXERCAPS)) == MMSYSERR_NOERROR)
    {
    if(::strcmp(mixCaps.szPname, strDevName.m_pText) == 0)
    {
    return uMxId;
    }
    }
    }
    return WAVE_MAPPER;
    }


    BOOL wMixerCtrl::OpenMixer(int iIndex)
    {
    chASSERT(iIndex >= 0);
    chASSERT(m_hMixer == NULL);
    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)
    {
    return FALSE;
    }
    BOOL wMixerCtrl::SetMute(int nType, BOOL BMute)
    {
    return 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();
    }
    }

    static void CALLBACK waveOutProc(
    HWAVEOUT hWaveOut,
    UINT uMsg,
    DWORD dwInstance,
    DWORD dwParam1,
    DWORD dwParam2
    )
    {
    WAVEHDR*p=(WAVEHDR*)dwParam1;//dwParam1指向WAVEHDR的地址
    if (uMsg == WOM_DONE && waveOutUnprepareHeader(hWaveOut,p,sizeof(WAVEHDR)) == MMSYSERR_NOERROR)
    {
    static int Count = 0;
    waveOutPrepareHeader(hWaveOut, p, sizeof(WAVEHDR));
    waveOutWrite(hWaveOut, p, sizeof(WAVEHDR));
    if ((++Count & 1) != 1)
    {
    wWavePlayer* pWavePlayer = (wWavePlayer*)dwInstance;
    pWavePlayer->m_playStartTimer = etlGetTickCount();
    }
    }
    }

    bool wWavePlayer::wavePlayStart(UINT idDev, const chConstString& strFilePath)
    {
    WAVEFORMATEX wfx; /* look this up in your documentation */
    //DWORD blockSize;/* holds the size of the block */

    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,
    (DWORD_PTR)waveOutProc,
    (DWORD)this,
    CALLBACK_FUNCTION) != MMSYSERR_NOERROR)
    {
    SYZ_TRACE("unable to open WAVE_MAPPER device");
    //ExitProcess(1);
    return false;
    }

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

    m_wavePlayBlocks = etlDumpBinFile(strFilePath);//读取内存可以使用上面 utility中loadAudioBlock方法
    if(m_wavePlayBlocks.size() == 0)
    {
    SYZ_TRACE("Unable to load file");
    //ExitProcess(1);
    wavePlayStop();
    return false;
    }

    LPSTR pPCMHead = (LPSTR)m_wavePlayBlocks.data() + 44;
    int nPCMLen = m_wavePlayBlocks.size() - 44;

    ZeroMemory(&m_blockOne, sizeof(WAVEHDR));
    m_blockOne.lpData = pPCMHead;
    m_blockOne.dwBufferLength = nPCMLen / 2;

    ZeroMemory(&m_blockTwo, sizeof(WAVEHDR));
    m_blockTwo.lpData = pPCMHead + nPCMLen / 2;
    m_blockTwo.dwBufferLength = nPCMLen / 2;

    waveOutPrepareHeader(m_hWaveOut, &m_blockOne, sizeof(WAVEHDR));
    waveOutWrite(m_hWaveOut, &m_blockOne, sizeof(WAVEHDR));
    waveOutPrepareHeader(m_hWaveOut, &m_blockTwo, sizeof(WAVEHDR));
    waveOutWrite(m_hWaveOut, &m_blockTwo, sizeof(WAVEHDR));
    m_playStartTimer = etlGetTickCount();
    return true;
    }

    void wWavePlayer::wavePlayStop()
    {
    if (m_hWaveOut != NULL)
    {
    waveOutReset(m_hWaveOut);
    waveOutClose(m_hWaveOut);
    m_hWaveOut = NULL;
    m_playStartTimer = 0;
    }
    }
    int wWavePlayer::getCurrentSample()
    {
    //chASSERT(m_Playblock.size() != 0);
    //1毫秒偏移16byte ===> 16*1*8000/1000/8 = 16byte
    UINT64 longMillisecondTime = (etlGetTickCount() - m_playStartTimer);
    UINT64 byteCounts = longMillisecondTime * 16;
    chASSERT(m_wavePlayBlocks.size() > byteCounts);
    return m_wavePlayBlocks.at((int)byteCounts);
    }

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

    wWavePlayer::~wWavePlayer()
    {
    if (m_hWaveOut != NULL)
    {
    waveOutClose(m_hWaveOut);
    m_hWaveOut = NULL;
    }
    }

  • 相关阅读:
    .NET core webApi 使用JWT验证签名
    sudo
    Mysql Error Code : 1436 Thread stack overrun
    Parallel World 4 – Parallel Task (1)
    SQLSTATE[HY000] [2002] Can't connect to local MySQL server
    Parallel World 3 – Parallel Task (2)
    Parallel World 5 – Concurrent Collections (1)
    Utime failed: Permission denied in Smarty/sysplugins/smarty_internal_template.php on line xxx
    Add Reference
    Javascript Tips
  • 原文地址:https://www.cnblogs.com/hqu-ye/p/4310202.html
Copyright © 2011-2022 走看看