echotool.cpp
上传用户:tuheem
上传日期:2007-05-01
资源大小:21889k
文件大小:8k
- //-----------------------------------------------------------------------------
- // 文件名: 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);
- }