⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 echotool.cpp

📁 VC++视频开发实例集锦(包括“远程视频监控”"语音识别系统"等13个经典例子)
💻 CPP
字号:
//-----------------------------------------------------------------------------
// 文件名: EchoTool.cpp
//
// 描  述: 实现一个继承自IDirectMusicTool,并提供回音效果的类
//-----------------------------------------------------------------------------
#include <dmusici.h>
#include "EchoTool.h"




//-----------------------------------------------------------------------------
// 函数名: CEchoTool::CEchoTool()
// 描  述: 
//-----------------------------------------------------------------------------
CEchoTool::CEchoTool()
{
    m_cRef = 1;                 // 设置为1,可调用Release()释放
    m_dwEchoNum = 3;            // 设置缺省情况为每个音符三个回音
    m_mtDelay = DMUS_PPQ / 2;   // 设置缺省情况为第八音符回音
    InitializeCriticalSection(&m_CrSec);
}




//-----------------------------------------------------------------------------
// 函数名: CEchoTool::~CEchoTool()
// 描  述: 
//-----------------------------------------------------------------------------
CEchoTool::~CEchoTool()
{
    DeleteCriticalSection(&m_CrSec);
}




//-----------------------------------------------------------------------------
// 函数名: CEchoTool::QueryInterface()
// 描  述: 
//-----------------------------------------------------------------------------
STDMETHODIMP CEchoTool::QueryInterface(const IID &iid, void **ppv)
{
    if (iid == IID_IUnknown || iid == IID_IDirectMusicTool)
    {
        *ppv = static_cast<IDirectMusicTool*>(this);
    } 
    else
    {
        *ppv = NULL;
        return E_NOINTERFACE;
    }
    
    reinterpret_cast<IUnknown*>(this)->AddRef();
    return S_OK;
}




//-----------------------------------------------------------------------------
// 函数名: CEchoTool::AddRef()
// 描  述: 
//-----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CEchoTool::AddRef()
{
    return InterlockedIncrement(&m_cRef);
}




//-----------------------------------------------------------------------------
// 函数名: CEchoTool::Release()
// 描  述: 
//-----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CEchoTool::Release()
{
    if( 0 == InterlockedDecrement(&m_cRef) )
    {
        delete this;
        return 0;
    }

    return m_cRef;
}




//-----------------------------------------------------------------------------
// 函数名: CEchoTool::Init()
// 描  述: 
//-----------------------------------------------------------------------------
HRESULT STDMETHODCALLTYPE CEchoTool::Init( IDirectMusicGraph* pGraph )
{
    // 本工具不需要任何初始化
    return E_NOTIMPL;
}




//-----------------------------------------------------------------------------
// 函数名: CEchoTool::GetMsgDeliveryType()
// 描  述: 
//-----------------------------------------------------------------------------
HRESULT STDMETHODCALLTYPE CEchoTool::GetMsgDeliveryType( DWORD* pdwDeliveryType )
{
    // 本工具需要立即消息,这是缺省的,因此返回E_NOTIMPL即可。
    // 另一种方法是设置*pdwDeliveryType传输类型,如DMUS_PMSGF_TOOL_IMMEDIATE,
    // DMUS_PMSGF_TOOL_QUEUE, 或DMUS_PMSGF_TOOL_ATTIME.
    
    *pdwDeliveryType = DMUS_PMSGF_TOOL_IMMEDIATE;
    return S_OK;
}




//-----------------------------------------------------------------------------
// 函数名: CEchoTool::GetMediaTypeArraySize()
// 描  述: 
//-----------------------------------------------------------------------------
HRESULT STDMETHODCALLTYPE CEchoTool::GetMediaTypeArraySize( DWORD* pdwNumElements )
{
    // 这个工具只需要note、patch、sysex和MIDI四种消息, 
    // 所以*pdwNumElements为4.
    
    *pdwNumElements = 4;
    return S_OK;
}




//-----------------------------------------------------------------------------
// 函数名: CEchoTool::GetMediaTypes()
// 描  述: 
//-----------------------------------------------------------------------------
HRESULT STDMETHODCALLTYPE CEchoTool::GetMediaTypes( DWORD** padwMediaTypes, 
                                                    DWORD dwNumElements )
{
    // 用本工具想要处理的消息的类型来填充padwMediaTypes数组。
    // 本例中dwNumElements将为3, 因为该数据是从GetMediaTypeArraySize()返回的。    
    if( dwNumElements == 4 )
    {
        // 设置数组的元素为DMUS_PMSGT_NOTE,
        // DMUS_PMSGT_MIDI, and DMUS_PMSGT_PATCH
        (*padwMediaTypes)[0] = DMUS_PMSGT_NOTE;
        (*padwMediaTypes)[1] = DMUS_PMSGT_MIDI;
        (*padwMediaTypes)[2] = DMUS_PMSGT_PATCH;
        (*padwMediaTypes)[3] = DMUS_PMSGT_SYSEX;
        return S_OK;
    }
    else
    {
        // 这应该不会发生
        return E_FAIL;
    }
}




//-----------------------------------------------------------------------------
// 函数名: CEchoTool::ProcessPMsg()
// 描  述: 
//-----------------------------------------------------------------------------
HRESULT STDMETHODCALLTYPE CEchoTool::ProcessPMsg( IDirectMusicPerformance* pPerf, 
                                                  DMUS_PMSG* pPMsg )
{
    DWORD dwCount;
    DWORD dwEchoNum;
    MUSIC_TIME mtDelay;
    
    // SetEchoNum()和SetDelay()使用这些成员变量,
    // 因此使用关键的段使得线程安全。
    EnterCriticalSection(&m_CrSec);
    dwEchoNum = m_dwEchoNum;
    mtDelay = m_mtDelay;
    LeaveCriticalSection(&m_CrSec);
    
    // 返回S_FREE释放消息. 如果StampPMsg()失败,没有此消息的目的地,因此释放它
    if(( NULL == pPMsg->pGraph ) ||
        FAILED(pPMsg->pGraph->StampPMsg(pPMsg)))
    {
        return DMUS_S_FREE;
    }

  
    IDirectMusicPerformance8 *pPerf8;
    if (SUCCEEDED(pPerf->QueryInterface(IID_IDirectMusicPerformance8,(void **)&pPerf8)))
    {
        for( dwCount = 1; dwCount <= dwEchoNum; dwCount++ )
        {
            DMUS_PMSG *pClone;
            if( SUCCEEDED( pPerf8->ClonePMsg( pPMsg,&pClone)))
            {
                // 增加回音音符的次数
                pClone->mtTime += (dwCount * mtDelay);
                if (pPMsg->dwType == DMUS_PMSGT_NOTE )
                {
                    DMUS_NOTE_PMSG *pNote = (DMUS_NOTE_PMSG*)pPMsg;
                    DMUS_NOTE_PMSG *pCloneNote = (DMUS_NOTE_PMSG*)pClone;
                    pCloneNote->bVelocity = (BYTE) (pNote->bVelocity - 
                        ((pNote->bVelocity * (dwCount * 15))/100));
                }
                // 设置音符,因此仅仅MUSIC_TIME是有效的.
                // REFERENCE_TIME将在SendPMsg()中重新计算
                pClone->dwFlags = DMUS_PMSGF_MUSICTIME;
                pClone->dwPChannel = pPMsg->dwPChannel + 
                    (16*dwCount);
                // 排队等待回音的PMsg
                pPerf->SendPMsg(pClone );
            }
        }
        pPerf8->Release();
    }


    //返回DMUS_S_REQUEUE,因此原始消息被重新排列 
    return DMUS_S_REQUEUE;
}




//-----------------------------------------------------------------------------
// 函数名: CEchoTool::Flush()
// 描  述: 
//-----------------------------------------------------------------------------
HRESULT STDMETHODCALLTYPE CEchoTool::Flush( IDirectMusicPerformance* pPerf, 
                                            DMUS_PMSG* pDMUS_PMSG,
                                            REFERENCE_TIME rt)
{
    // 本工具不需要流
    return E_NOTIMPL;
}




//-----------------------------------------------------------------------------
// 函数名: CEchoTool::SetEchoNum()
// 描  述: 
//-----------------------------------------------------------------------------
void CEchoTool::SetEchoNum( DWORD dwEchoNum )
{
    // ProcessPMsg()使用m_dwEchoNum, 
    // 因此使用关键的段使得线程安全。
    if( dwEchoNum <= MAX_ECHOES )
    {
        EnterCriticalSection(&m_CrSec);
        m_dwEchoNum = dwEchoNum;
        LeaveCriticalSection(&m_CrSec);
    }
}




//-----------------------------------------------------------------------------
// 函数名: CEchoTool::SetDelay()
// 描  述: 
//-----------------------------------------------------------------------------
void CEchoTool::SetDelay( MUSIC_TIME mtDelay )
{
    // ProcessPMsg()使用m_mtDelay,     
	// 因此使用关键的段使得线程安全。
    EnterCriticalSection(&m_CrSec);
    m_mtDelay = mtDelay;
    LeaveCriticalSection(&m_CrSec);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -