VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

搜索
查看: 210|回复: 1

[原创] 通过directshow+basslib 播放大部分音乐格式源码

[复制链接]
75_avatar_middle
最佳答案
0 
在线会员 发表于 2019-12-9 23:50:34 | 显示全部楼层 |阅读模式
我在开发软件的时候,需要播放音效,渲染氛围。开始用了一些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;
}

评分

参与人数 1驿站币 +2 热心值 +2 收起 理由
58_avatar_small thzzl + 2 + 2 很给力!

查看全部评分





上一篇:软件开发日志—使文本框Edit控件可以接受unix,mac的换行模式
下一篇:今日一贴,发一个让程序增加托盘图标的方法
58_avatar_middle
最佳答案
45 
online_vip 发表于 2019-12-10 00:01:31 | 显示全部楼层
软件是什么样的软件,能发张图看看吗?
您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

×【发帖 友情提示】
1、请回复有意义的内容,请勿恶意灌水;
2、纯数字、字母、表情等无意义的内容系统将自动删除;
3、若正常回复后帖子被自动删除,为系统误删的情况,请重新回复其他正常内容或等待管理员审核通过后会自动发布;
4、感谢您对VC驿站一如既往的支持,谢谢合作!

关闭

站长提醒上一条 /2 下一条

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号 )|网站地图wx_jqr

GMT+8, 2020-11-1 00:30

Powered by CcTry.CoM

© 2009-2020 cctry.com

快速回复 返回顶部 返回列表