?? echotool.cpp
字號(hào):
//-----------------------------------------------------------------------------
// 文件名: EchoTool.cpp
//
// 描 述: 實(shí)現(xiàn)一個(gè)繼承自IDirectMusicTool,并提供回音效果的類(lèi)
//-----------------------------------------------------------------------------
#include <dmusici.h>
#include "EchoTool.h"
//-----------------------------------------------------------------------------
// 函數(shù)名: CEchoTool::CEchoTool()
// 描 述:
//-----------------------------------------------------------------------------
CEchoTool::CEchoTool()
{
m_cRef = 1; // 設(shè)置為1,可調(diào)用Release()釋放
m_dwEchoNum = 3; // 設(shè)置缺省情況為每個(gè)音符三個(gè)回音
m_mtDelay = DMUS_PPQ / 2; // 設(shè)置缺省情況為第八音符回音
InitializeCriticalSection(&m_CrSec);
}
//-----------------------------------------------------------------------------
// 函數(shù)名: CEchoTool::~CEchoTool()
// 描 述:
//-----------------------------------------------------------------------------
CEchoTool::~CEchoTool()
{
DeleteCriticalSection(&m_CrSec);
}
//-----------------------------------------------------------------------------
// 函數(shù)名: 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;
}
//-----------------------------------------------------------------------------
// 函數(shù)名: CEchoTool::AddRef()
// 描 述:
//-----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CEchoTool::AddRef()
{
return InterlockedIncrement(&m_cRef);
}
//-----------------------------------------------------------------------------
// 函數(shù)名: CEchoTool::Release()
// 描 述:
//-----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CEchoTool::Release()
{
if( 0 == InterlockedDecrement(&m_cRef) )
{
delete this;
return 0;
}
return m_cRef;
}
//-----------------------------------------------------------------------------
// 函數(shù)名: CEchoTool::Init()
// 描 述:
//-----------------------------------------------------------------------------
HRESULT STDMETHODCALLTYPE CEchoTool::Init( IDirectMusicGraph* pGraph )
{
// 本工具不需要任何初始化
return E_NOTIMPL;
}
//-----------------------------------------------------------------------------
// 函數(shù)名: CEchoTool::GetMsgDeliveryType()
// 描 述:
//-----------------------------------------------------------------------------
HRESULT STDMETHODCALLTYPE CEchoTool::GetMsgDeliveryType( DWORD* pdwDeliveryType )
{
// 本工具需要立即消息,這是缺省的,因此返回E_NOTIMPL即可。
// 另一種方法是設(shè)置*pdwDeliveryType傳輸類(lèi)型,如DMUS_PMSGF_TOOL_IMMEDIATE,
// DMUS_PMSGF_TOOL_QUEUE, 或DMUS_PMSGF_TOOL_ATTIME.
*pdwDeliveryType = DMUS_PMSGF_TOOL_IMMEDIATE;
return S_OK;
}
//-----------------------------------------------------------------------------
// 函數(shù)名: CEchoTool::GetMediaTypeArraySize()
// 描 述:
//-----------------------------------------------------------------------------
HRESULT STDMETHODCALLTYPE CEchoTool::GetMediaTypeArraySize( DWORD* pdwNumElements )
{
// 這個(gè)工具只需要note、patch、sysex和MIDI四種消息,
// 所以*pdwNumElements為4.
*pdwNumElements = 4;
return S_OK;
}
//-----------------------------------------------------------------------------
// 函數(shù)名: CEchoTool::GetMediaTypes()
// 描 述:
//-----------------------------------------------------------------------------
HRESULT STDMETHODCALLTYPE CEchoTool::GetMediaTypes( DWORD** padwMediaTypes,
DWORD dwNumElements )
{
// 用本工具想要處理的消息的類(lèi)型來(lái)填充padwMediaTypes數(shù)組。
// 本例中dwNumElements將為3, 因?yàn)樵摂?shù)據(jù)是從GetMediaTypeArraySize()返回的。
if( dwNumElements == 4 )
{
// 設(shè)置數(shù)組的元素為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
{
// 這應(yīng)該不會(huì)發(fā)生
return E_FAIL;
}
}
//-----------------------------------------------------------------------------
// 函數(shù)名: CEchoTool::ProcessPMsg()
// 描 述:
//-----------------------------------------------------------------------------
HRESULT STDMETHODCALLTYPE CEchoTool::ProcessPMsg( IDirectMusicPerformance* pPerf,
DMUS_PMSG* pPMsg )
{
DWORD dwCount;
DWORD dwEchoNum;
MUSIC_TIME mtDelay;
// SetEchoNum()和SetDelay()使用這些成員變量,
// 因此使用關(guān)鍵的段使得線程安全。
EnterCriticalSection(&m_CrSec);
dwEchoNum = m_dwEchoNum;
mtDelay = m_mtDelay;
LeaveCriticalSection(&m_CrSec);
// 返回S_FREE釋放消息. 如果StampPMsg()失敗,沒(méi)有此消息的目的地,因此釋放它
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)))
{
// 增加回音音符的次數(shù)
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));
}
// 設(shè)置音符,因此僅僅MUSIC_TIME是有效的.
// REFERENCE_TIME將在SendPMsg()中重新計(jì)算
pClone->dwFlags = DMUS_PMSGF_MUSICTIME;
pClone->dwPChannel = pPMsg->dwPChannel +
(16*dwCount);
// 排隊(duì)等待回音的PMsg
pPerf->SendPMsg(pClone );
}
}
pPerf8->Release();
}
//返回DMUS_S_REQUEUE,因此原始消息被重新排列
return DMUS_S_REQUEUE;
}
//-----------------------------------------------------------------------------
// 函數(shù)名: CEchoTool::Flush()
// 描 述:
//-----------------------------------------------------------------------------
HRESULT STDMETHODCALLTYPE CEchoTool::Flush( IDirectMusicPerformance* pPerf,
DMUS_PMSG* pDMUS_PMSG,
REFERENCE_TIME rt)
{
// 本工具不需要流
return E_NOTIMPL;
}
//-----------------------------------------------------------------------------
// 函數(shù)名: CEchoTool::SetEchoNum()
// 描 述:
//-----------------------------------------------------------------------------
void CEchoTool::SetEchoNum( DWORD dwEchoNum )
{
// ProcessPMsg()使用m_dwEchoNum,
// 因此使用關(guān)鍵的段使得線程安全。
if( dwEchoNum <= MAX_ECHOES )
{
EnterCriticalSection(&m_CrSec);
m_dwEchoNum = dwEchoNum;
LeaveCriticalSection(&m_CrSec);
}
}
//-----------------------------------------------------------------------------
// 函數(shù)名: CEchoTool::SetDelay()
// 描 述:
//-----------------------------------------------------------------------------
void CEchoTool::SetDelay( MUSIC_TIME mtDelay )
{
// ProcessPMsg()使用m_mtDelay,
// 因此使用關(guān)鍵的段使得線程安全。
EnterCriticalSection(&m_CrSec);
m_mtDelay = mtDelay;
LeaveCriticalSection(&m_CrSec);
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -