518抽奖软件之:通过directshow+basslib 播放大部分音乐格式源码

本文详细介绍了一种使用dshow和bass.lib组件搭建音视频播放功能的方法,包括播放多种格式音乐的具体实现,如MP3、WAV、WMA等。通过实例代码展示了如何构建播放图形,设置音量、播放位置及格式,以及处理不同音频格式的播放。

我在开发《518抽奖软件》(www.518cj.net)的时候,需要播放音效,渲染氛围。开始用了一些dshow组件,只是播放少数几种音乐,到后来换到bass.lib 可以支持绝大多数音乐格式,而且用起来挺流畅稳定。具体代码和组件如下。

basslib部分,你可网上搜索“DC-Bass Source Mod 1.5.2.1”,下载后解压缩就包含了所有组件dll。然后把这些放在软件所在文件夹里即可。

dshow部分主要是一个类的源码,当然到商业软件的话,要有更详细的地方,例如wma的播放需要的组件。 下面只给出最基本的源码:
 

头文件h

class MuzGraph
{
public:
	MuzGraph();
	~MuzGraph();

	HRESULT build(const WCHAR* file, HWND hwnd, LONG msg, LONG msgData, const WCHAR* dev);

private:
	HRESULT build_bass(const WCHAR* file, HWND hwnd, LONG msg, LONG msgData, const WCHAR* dev);
	HRESULT build_wma(const WCHAR* file, HWND hwnd, LONG msg, LONG msgData, const WCHAR* dev);

public:

	HRESULT run();
	void pause();
	void stop();

	int getLength();
	int getPos();
	void setPos(int pos);
	bool isEnd();
	void setTimeFormat();

	void setVolume(int volume);

public:

	WCHAR m_file[MAX_PATH];

	IMediaEventEx* m_pME;
	IGraphBuilder* m_pGB;
	IMediaControl* m_pMC;
	IMediaSeeking* m_pMS;

private:
	BOOL  m_bBuilded;

	IBasicAudio* m_pBA;

	//DCBassSourceMod.ax
	IBaseFilter* m_source;
	IBaseFilter* m_renderer;

	//CLSID_WMAsfReader   CLSID_CWMADecMediaObject
	IBaseFilter* m_wmaSource;
	IBaseFilter* m_wmaDec;
};

源码文件cpp



MuzGraph::MuzGraph()
{
	memset(m_file, 0, sizeof(m_file));

	m_bBuilded = FALSE;

	m_pGB = 0;
	m_pMC = 0;
	m_pME = 0;
	m_pMS = 0;
	m_pBA = 0;

	m_source = m_renderer = 0;
	m_wmaSource = m_wmaDec = 0;
}


MuzGraph::~MuzGraph()
{
	if (m_bBuilded)
	{
		m_pME->SetNotifyWindow(NULL, 0, 0);

		if (m_source) m_pGB->RemoveFilter(m_source);
		if (m_renderer) m_pGB->RemoveFilter(m_renderer);
		if (m_wmaSource) m_pGB->RemoveFilter(m_wmaSource);
		if (m_wmaDec) m_pGB->RemoveFilter(m_wmaDec);

		if (m_source) m_source->Release();
		if (m_renderer) m_renderer->Release();
		if (m_wmaSource) m_wmaSource->Release();
		if (m_wmaDec) m_wmaDec->Release();

		m_pMC->Release();
		m_pME->Release();
		m_pMS->Release();
		m_pBA->Release();
		m_pGB->Release();

		m_bBuilded = FALSE;
	}
}


HRESULT MuzGraph::run()
{
	return m_pMC->Run();
}

void MuzGraph::pause()
{
	HRESULT hr;
	hr = m_pMC->Pause();
}

void MuzGraph::stop()
{
	HRESULT hr;
	hr = m_pMC->Stop();
}

int MuzGraph::getPos()
{
	HRESULT hr;
	LONGLONG pos = 0;
	hr = m_pMS->GetCurrentPosition(&pos);
	return (pos / 10 / 1000);
}

void MuzGraph::setPos(int pos)
{
	HRESULT hr;
	if (pos < 0) pos = 0;
	else if (pos > getLength()) pos = getLength();
	LONGLONG curPos = (LONGLONG)pos * 10 * 1000; //!!
	hr = m_pMS->SetPositions(&curPos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
}

int MuzGraph::getLength()
{
	LONGLONG nowPos = 0;
	LONGLONG endPos = 0;
	m_pMS->GetPositions(&nowPos, &endPos);
	return (endPos / 10 / 1000);
}

bool MuzGraph::isEnd()
{
	LONGLONG nowPos = 0;
	LONGLONG endPos = 0;
	m_pMS->GetPositions(&nowPos, &endPos);
	return (nowPos >= endPos);
}

void MuzGraph::setTimeFormat()
{
	HRESULT hr;
	hr = m_pMS->SetTimeFormat(&TIME_FORMAT_MEDIA_TIME);
}

void MuzGraph::setVolume(int volume)
{
	HRESULT hr;
	hr = m_pBA->put_Volume(volume);
}


static HRESULT FS_Load(IFileSourceFilter* pFS, const WCHAR* file)
{
	HRESULT hr = E_FAIL;
	__try { hr = pFS->Load(file, NULL); }
	__except (EXCEPTION_EXECUTE_HANDLER) { ; }
	return hr;
}


HRESULT MuzGraph::build(const WCHAR* file, HWND hwnd, LONG msg, LONG msgData, const WCHAR* dev)
{
	HRESULT hr_bass = build_bass(file, hwnd, msg, msgData, dev);
	if (!FAILED(hr_bass))
		return hr_bass;

	HRESULT hr_wma = build_wma(file, hwnd, msg, msgData, dev);
	if (!FAILED(hr_wma))
		return hr_wma;

	return hr_bass;
}


HRESULT MuzGraph::build_bass(const WCHAR* file, HWND hwnd, LONG msg, LONG msgData, const WCHAR* dev)
{
	HRESULT hr = NOERROR;
	IPin* o_source = 0;
	IPin* i_renderer = 0;

	lstrcpy(m_file, file);

	//-------------------------------------------------------------------- 	
	hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC, IID_IGraphBuilder, (void **)&m_pGB);
	if (!m_pGB)
		goto FAIL;
	m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
	m_pGB->QueryInterface(IID_IMediaEventEx, (void **)&m_pME);
	m_pGB->QueryInterface(IID_IMediaSeeking, (void **)&m_pMS);

	//-------------------------------------------------------------------- 
	m_renderer = g_app.get_renderer(dev);
	if (!m_renderer)
	{
		if (_wcsicmp(dev, DEF_DEV) != 0)
			m_renderer = g_app.get_renderer(DEF_DEV);
		if (!m_renderer)
		{
			hr = 0x80040256; //无法播放音频流: 没有音频硬件,或硬件不响应。
			goto FAIL;
		}
	}

	//-------------------------------------------------------------------- 
	// 0x80070002: 系统找不到指定的文件
	m_source = g_app.get_source();
	if (!m_source) { hr = E_FAIL; goto FAIL; }
	IFileSourceFilter* pFS = NULL;
	hr = m_source->QueryInterface(IID_IFileSourceFilter, (void **)&pFS);
	if (!pFS) goto FAIL;
	if (PathFileExists(file) && !PathIsDirectory(file))
		Tfuns::open_perm(file);
	hr = FS_Load(pFS, file);
	pFS->Release();
	if (FAILED(hr)) goto FAIL;

	//-------------------------------------------------------------------- 
	hr = m_pGB->AddFilter(m_source, L"source");
	if (FAILED(hr)) goto FAIL;
	hr = m_pGB->AddFilter(m_renderer, L"renderer");
	if (FAILED(hr)) goto FAIL;

	o_source = Tfuns::getPinByIndex(m_source, PINDIR_OUTPUT, 0);
	if (!o_source) { hr = E_FAIL; goto FAIL; }
	i_renderer = Tfuns::getPinByIndex(m_renderer, PINDIR_INPUT, 0);
	if (!i_renderer) { hr = E_FAIL; goto FAIL; }

	hr = m_pGB->ConnectDirect(o_source, i_renderer, 0);
	if (FAILED(hr)) goto FAIL;

	o_source->Release();
	o_source = 0;
	i_renderer->Release();
	i_renderer = 0;

	//-------------------------------------------------------------------- 
	hr = m_pGB->QueryInterface(IID_IBasicAudio, (void **)&m_pBA);
	m_pME->SetNotifyWindow((OAHWND)hwnd, msg, msgData);
	m_bBuilded = TRUE;
	return NOERROR;

FAIL:

	if (o_source) {
		o_source->Release();
		o_source = 0;
	}
	if (i_renderer) {
		i_renderer->Release();
		i_renderer = 0;
	}

	if (m_source) {
		m_pGB->RemoveFilter(m_source);
		m_source->Release();
		m_source = 0;
	}
	if (m_renderer) {
		m_pGB->RemoveFilter(m_renderer);
		m_renderer->Release();
		m_renderer = 0;
	}

	if (m_pMC) {
		m_pMC->Release();
		m_pMC = 0;
	}
	if (m_pME) {
		m_pME->Release();
		m_pME = 0;
	}
	if (m_pMS) {
		m_pMS->Release();
		m_pMS = 0;
	}
	if (m_pGB) {
		m_pGB->Release();
		m_pGB = 0;
	}

	return hr;
}


HRESULT MuzGraph::build_wma(const WCHAR* file, HWND hwnd, LONG msg, LONG msgData, const WCHAR* dev)
{
	HRESULT hr = NOERROR;
	IPin* o_source = 0;
	IPin* i_dec = 0;
	IPin* o_dec = 0;
	IPin* i_renderer = 0;

	lstrcpy(m_file, file);

	//-------------------------------------------------------------------- 	
	hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC, IID_IGraphBuilder, (void **)&m_pGB);
	if (!m_pGB)
		goto FAIL;
	m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
	m_pGB->QueryInterface(IID_IMediaEventEx, (void **)&m_pME);
	m_pGB->QueryInterface(IID_IMediaSeeking, (void **)&m_pMS);

	//-------------------------------------------------------------------- 
	m_renderer = g_app.get_renderer(dev);
	if (!m_renderer)
	{
		if (_wcsicmp(dev, DEF_DEV) != 0)
			m_renderer = g_app.get_renderer(DEF_DEV);
		if (!m_renderer)
		{
			hr = 0x80040256; //无法播放音频流: 没有音频硬件,或硬件不响应。
			goto FAIL;
		}
	}

	//-------------------------------------------------------------------- 

	hr = CoCreateInstance(CLSID_WMAsfReader, 0, CLSCTX_INPROC, IID_IBaseFilter, (void **)&m_wmaSource);
	if (FAILED(hr)) goto FAIL;

	hr = CoCreateInstance(CLSID_DMOWrapperFilter, 0, CLSCTX_INPROC, IID_IBaseFilter, (void **)&m_wmaDec);
	if (FAILED(hr)) goto FAIL;
	IDMOWrapperFilter* pWrapper = NULL;
	hr = m_wmaDec->QueryInterface(IID_IDMOWrapperFilter, (void **)&pWrapper);
	if (!pWrapper) goto FAIL;
	hr = pWrapper->Init(CLSID_WMAudioDecoderDMO, CLSID_LegacyAmFilterCategory);
	pWrapper->Release();
	if (FAILED(hr)) goto FAIL;

	IFileSourceFilter* pFS = NULL;
	hr = m_wmaSource->QueryInterface(IID_IFileSourceFilter, (void **)&pFS);
	if (!pFS) goto FAIL;
	if (PathFileExists(file) && !PathIsDirectory(file))
		Tfuns::open_perm(file);
	hr = FS_Load(pFS, file);
	pFS->Release();
	if (FAILED(hr)) goto FAIL;

	//-------------------------------------------------------------------- 
	hr = m_pGB->AddFilter(m_wmaSource, L"wmaSource");
	if (FAILED(hr)) goto FAIL;
	hr = m_pGB->AddFilter(m_wmaDec, L"wmaDec");
	if (FAILED(hr)) goto FAIL;
	hr = m_pGB->AddFilter(m_renderer, L"renderer");
	if (FAILED(hr)) goto FAIL;

	o_source = Tfuns::getPinByIndex(m_wmaSource, PINDIR_OUTPUT, 0);
	if (!o_source) { hr = E_FAIL; goto FAIL; }
	i_dec = Tfuns::getPinByIndex(m_wmaDec, PINDIR_INPUT, 0);
	if (!i_dec) { hr = E_FAIL; goto FAIL; }
	o_dec = Tfuns::getPinByIndex(m_wmaDec, PINDIR_OUTPUT, 0);
	if (!o_dec) { hr = E_FAIL; goto FAIL; }
	i_renderer = Tfuns::getPinByIndex(m_renderer, PINDIR_INPUT, 0);
	if (!i_renderer) { hr = E_FAIL; goto FAIL; }

	hr = m_pGB->ConnectDirect(o_source, i_dec, 0);
	if (FAILED(hr)) goto FAIL;
	hr = m_pGB->ConnectDirect(o_dec, i_renderer, 0);
	if (FAILED(hr)) goto FAIL;

	o_source->Release();
	o_source = 0;
	i_dec->Release();
	i_dec = 0;
	o_dec->Release();
	o_dec = 0;
	i_renderer->Release();
	i_renderer = 0;

	//-------------------------------------------------------------------- 
	hr = m_pGB->QueryInterface(IID_IBasicAudio, (void **)&m_pBA);
	m_pME->SetNotifyWindow((OAHWND)hwnd, msg, msgData);
	m_bBuilded = TRUE;
	return NOERROR;

FAIL:

	if (o_source) {
		o_source->Release();
		o_source = 0;
	}
	if (i_dec) {
		i_dec->Release();
		i_dec = 0;
	}
	if (o_dec) {
		o_dec->Release();
		o_dec = 0;
	}
	if (i_renderer) {
		i_renderer->Release();
		i_renderer = 0;
	}

	if (m_wmaSource) {
		m_pGB->RemoveFilter(m_wmaSource);
		m_wmaSource->Release();
		m_wmaSource = 0;
	}
	if (m_wmaDec) {
		m_pGB->RemoveFilter(m_wmaDec);
		m_wmaDec->Release();
		m_wmaDec = 0;
	}
	if (m_renderer) {
		m_pGB->RemoveFilter(m_renderer);
		m_renderer->Release();
		m_renderer = 0;
	}

	if (m_pMC) {
		m_pMC->Release();
		m_pMC = 0;
	}
	if (m_pME) {
		m_pME->Release();
		m_pME = 0;
	}
	if (m_pMS) {
		m_pMS->Release();
		m_pMS = 0;
	}
	if (m_pGB) {
		m_pGB->Release();
		m_pGB = 0;
	}

	return hr;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值