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

 

posted on 2015-03-03 09:39  叶城宇  阅读(236)  评论(0编辑  收藏  举报