标签:
//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;
	}
}
标签:
原文地址:http://www.cnblogs.com/hqu-ye/p/4310202.html