echotool.cpp
上传用户:hxb_1234
上传日期:2010-03-30
资源大小:8328k
文件大小:8k
源码类别:

VC书籍

开发平台:

Visual C++

  1. //-----------------------------------------------------------------------------
  2. // 文件名: EchoTool.cpp
  3. //
  4. // 描  述: 实现一个继承自IDirectMusicTool,并提供回音效果的类
  5. //-----------------------------------------------------------------------------
  6. #include <dmusici.h>
  7. #include "EchoTool.h"
  8. //-----------------------------------------------------------------------------
  9. // 函数名: CEchoTool::CEchoTool()
  10. // 描  述: 
  11. //-----------------------------------------------------------------------------
  12. CEchoTool::CEchoTool()
  13. {
  14.     m_cRef = 1;                 // 设置为1,可调用Release()释放
  15.     m_dwEchoNum = 3;            // 设置缺省情况为每个音符三个回音
  16.     m_mtDelay = DMUS_PPQ / 2;   // 设置缺省情况为第八音符回音
  17.     InitializeCriticalSection(&m_CrSec);
  18. }
  19. //-----------------------------------------------------------------------------
  20. // 函数名: CEchoTool::~CEchoTool()
  21. // 描  述: 
  22. //-----------------------------------------------------------------------------
  23. CEchoTool::~CEchoTool()
  24. {
  25.     DeleteCriticalSection(&m_CrSec);
  26. }
  27. //-----------------------------------------------------------------------------
  28. // 函数名: CEchoTool::QueryInterface()
  29. // 描  述: 
  30. //-----------------------------------------------------------------------------
  31. STDMETHODIMP CEchoTool::QueryInterface(const IID &iid, void **ppv)
  32. {
  33.     if (iid == IID_IUnknown || iid == IID_IDirectMusicTool)
  34.     {
  35.         *ppv = static_cast<IDirectMusicTool*>(this);
  36.     } 
  37.     else
  38.     {
  39.         *ppv = NULL;
  40.         return E_NOINTERFACE;
  41.     }
  42.     
  43.     reinterpret_cast<IUnknown*>(this)->AddRef();
  44.     return S_OK;
  45. }
  46. //-----------------------------------------------------------------------------
  47. // 函数名: CEchoTool::AddRef()
  48. // 描  述: 
  49. //-----------------------------------------------------------------------------
  50. STDMETHODIMP_(ULONG) CEchoTool::AddRef()
  51. {
  52.     return InterlockedIncrement(&m_cRef);
  53. }
  54. //-----------------------------------------------------------------------------
  55. // 函数名: CEchoTool::Release()
  56. // 描  述: 
  57. //-----------------------------------------------------------------------------
  58. STDMETHODIMP_(ULONG) CEchoTool::Release()
  59. {
  60.     if( 0 == InterlockedDecrement(&m_cRef) )
  61.     {
  62.         delete this;
  63.         return 0;
  64.     }
  65.     return m_cRef;
  66. }
  67. //-----------------------------------------------------------------------------
  68. // 函数名: CEchoTool::Init()
  69. // 描  述: 
  70. //-----------------------------------------------------------------------------
  71. HRESULT STDMETHODCALLTYPE CEchoTool::Init( IDirectMusicGraph* pGraph )
  72. {
  73.     // 本工具不需要任何初始化
  74.     return E_NOTIMPL;
  75. }
  76. //-----------------------------------------------------------------------------
  77. // 函数名: CEchoTool::GetMsgDeliveryType()
  78. // 描  述: 
  79. //-----------------------------------------------------------------------------
  80. HRESULT STDMETHODCALLTYPE CEchoTool::GetMsgDeliveryType( DWORD* pdwDeliveryType )
  81. {
  82.     // 本工具需要立即消息,这是缺省的,因此返回E_NOTIMPL即可。
  83.     // 另一种方法是设置*pdwDeliveryType传输类型,如DMUS_PMSGF_TOOL_IMMEDIATE,
  84.     // DMUS_PMSGF_TOOL_QUEUE, 或DMUS_PMSGF_TOOL_ATTIME.
  85.     
  86.     *pdwDeliveryType = DMUS_PMSGF_TOOL_IMMEDIATE;
  87.     return S_OK;
  88. }
  89. //-----------------------------------------------------------------------------
  90. // 函数名: CEchoTool::GetMediaTypeArraySize()
  91. // 描  述: 
  92. //-----------------------------------------------------------------------------
  93. HRESULT STDMETHODCALLTYPE CEchoTool::GetMediaTypeArraySize( DWORD* pdwNumElements )
  94. {
  95.     // 这个工具只需要note、patch、sysex和MIDI四种消息, 
  96.     // 所以*pdwNumElements为4.
  97.     
  98.     *pdwNumElements = 4;
  99.     return S_OK;
  100. }
  101. //-----------------------------------------------------------------------------
  102. // 函数名: CEchoTool::GetMediaTypes()
  103. // 描  述: 
  104. //-----------------------------------------------------------------------------
  105. HRESULT STDMETHODCALLTYPE CEchoTool::GetMediaTypes( DWORD** padwMediaTypes, 
  106.                                                     DWORD dwNumElements )
  107. {
  108.     // 用本工具想要处理的消息的类型来填充padwMediaTypes数组。
  109.     // 本例中dwNumElements将为3, 因为该数据是从GetMediaTypeArraySize()返回的。    
  110.     if( dwNumElements == 4 )
  111.     {
  112.         // 设置数组的元素为DMUS_PMSGT_NOTE,
  113.         // DMUS_PMSGT_MIDI, and DMUS_PMSGT_PATCH
  114.         (*padwMediaTypes)[0] = DMUS_PMSGT_NOTE;
  115.         (*padwMediaTypes)[1] = DMUS_PMSGT_MIDI;
  116.         (*padwMediaTypes)[2] = DMUS_PMSGT_PATCH;
  117.         (*padwMediaTypes)[3] = DMUS_PMSGT_SYSEX;
  118.         return S_OK;
  119.     }
  120.     else
  121.     {
  122.         // 这应该不会发生
  123.         return E_FAIL;
  124.     }
  125. }
  126. //-----------------------------------------------------------------------------
  127. // 函数名: CEchoTool::ProcessPMsg()
  128. // 描  述: 
  129. //-----------------------------------------------------------------------------
  130. HRESULT STDMETHODCALLTYPE CEchoTool::ProcessPMsg( IDirectMusicPerformance* pPerf, 
  131.                                                   DMUS_PMSG* pPMsg )
  132. {
  133.     DWORD dwCount;
  134.     DWORD dwEchoNum;
  135.     MUSIC_TIME mtDelay;
  136.     
  137.     // SetEchoNum()和SetDelay()使用这些成员变量,
  138.     // 因此使用关键的段使得线程安全。
  139.     EnterCriticalSection(&m_CrSec);
  140.     dwEchoNum = m_dwEchoNum;
  141.     mtDelay = m_mtDelay;
  142.     LeaveCriticalSection(&m_CrSec);
  143.     
  144.     // 返回S_FREE释放消息. 如果StampPMsg()失败,没有此消息的目的地,因此释放它
  145.     if(( NULL == pPMsg->pGraph ) ||
  146.         FAILED(pPMsg->pGraph->StampPMsg(pPMsg)))
  147.     {
  148.         return DMUS_S_FREE;
  149.     }
  150.   
  151.     IDirectMusicPerformance8 *pPerf8;
  152.     if (SUCCEEDED(pPerf->QueryInterface(IID_IDirectMusicPerformance8,(void **)&pPerf8)))
  153.     {
  154.         for( dwCount = 1; dwCount <= dwEchoNum; dwCount++ )
  155.         {
  156.             DMUS_PMSG *pClone;
  157.             if( SUCCEEDED( pPerf8->ClonePMsg( pPMsg,&pClone)))
  158.             {
  159.                 // 增加回音音符的次数
  160.                 pClone->mtTime += (dwCount * mtDelay);
  161.                 if (pPMsg->dwType == DMUS_PMSGT_NOTE )
  162.                 {
  163.                     DMUS_NOTE_PMSG *pNote = (DMUS_NOTE_PMSG*)pPMsg;
  164.                     DMUS_NOTE_PMSG *pCloneNote = (DMUS_NOTE_PMSG*)pClone;
  165.                     pCloneNote->bVelocity = (BYTE) (pNote->bVelocity - 
  166.                         ((pNote->bVelocity * (dwCount * 15))/100));
  167.                 }
  168.                 // 设置音符,因此仅仅MUSIC_TIME是有效的.
  169.                 // REFERENCE_TIME将在SendPMsg()中重新计算
  170.                 pClone->dwFlags = DMUS_PMSGF_MUSICTIME;
  171.                 pClone->dwPChannel = pPMsg->dwPChannel + 
  172.                     (16*dwCount);
  173.                 // 排队等待回音的PMsg
  174.                 pPerf->SendPMsg(pClone );
  175.             }
  176.         }
  177.         pPerf8->Release();
  178.     }
  179.     //返回DMUS_S_REQUEUE,因此原始消息被重新排列 
  180.     return DMUS_S_REQUEUE;
  181. }
  182. //-----------------------------------------------------------------------------
  183. // 函数名: CEchoTool::Flush()
  184. // 描  述: 
  185. //-----------------------------------------------------------------------------
  186. HRESULT STDMETHODCALLTYPE CEchoTool::Flush( IDirectMusicPerformance* pPerf, 
  187.                                             DMUS_PMSG* pDMUS_PMSG,
  188.                                             REFERENCE_TIME rt)
  189. {
  190.     // 本工具不需要流
  191.     return E_NOTIMPL;
  192. }
  193. //-----------------------------------------------------------------------------
  194. // 函数名: CEchoTool::SetEchoNum()
  195. // 描  述: 
  196. //-----------------------------------------------------------------------------
  197. void CEchoTool::SetEchoNum( DWORD dwEchoNum )
  198. {
  199.     // ProcessPMsg()使用m_dwEchoNum, 
  200.     // 因此使用关键的段使得线程安全。
  201.     if( dwEchoNum <= MAX_ECHOES )
  202.     {
  203.         EnterCriticalSection(&m_CrSec);
  204.         m_dwEchoNum = dwEchoNum;
  205.         LeaveCriticalSection(&m_CrSec);
  206.     }
  207. }
  208. //-----------------------------------------------------------------------------
  209. // 函数名: CEchoTool::SetDelay()
  210. // 描  述: 
  211. //-----------------------------------------------------------------------------
  212. void CEchoTool::SetDelay( MUSIC_TIME mtDelay )
  213. {
  214.     // ProcessPMsg()使用m_mtDelay,     
  215. // 因此使用关键的段使得线程安全。
  216.     EnterCriticalSection(&m_CrSec);
  217.     m_mtDelay = mtDelay;
  218.     LeaveCriticalSection(&m_CrSec);
  219. }