Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

321 lines
9.0 KiB

  1. // Velocity.cpp : Implementation of CVelocityTool
  2. //
  3. // Copyright (C) 2000 Microsoft Corporation. All Rights Reserved
  4. //
  5. #include "dmusicc.h"
  6. #include "dmusici.h"
  7. #include "debug.h"
  8. #include "velocity.h"
  9. #include "toolhelp.h"
  10. CVelocityTool::CVelocityTool()
  11. {
  12. ParamInfo Params[DMUS_VELOCITY_PARAMCOUNT] =
  13. {
  14. { DMUS_VELOCITY_STRENGTH, MPT_INT,MP_CAPS_ALL,0,100,100,
  15. L"Percent",L"Strength",NULL }, // Strength - 100% by default
  16. { DMUS_VELOCITY_LOWLIMIT, MPT_INT,MP_CAPS_ALL,1,127,1,
  17. L"Velocity",L"Lower Limit",NULL }, // Lower limit - 1 by default
  18. { DMUS_VELOCITY_HIGHLIMIT, MPT_INT,MP_CAPS_ALL,1,127,127,
  19. L"Velocity",L"Upper Limit",NULL }, // Upper limit - 127 by default
  20. { DMUS_VELOCITY_CURVESTART, MPT_INT,MP_CAPS_ALL,1,127,1,
  21. L"Velocity",L"Curve Start",NULL }, // Curve start - 1 by default
  22. { DMUS_VELOCITY_CURVEEND, MPT_INT,MP_CAPS_ALL,1,127,127,
  23. L"Velocity",L"Curve End",NULL }, // Curve End - 127 by default
  24. };
  25. InitParams(DMUS_VELOCITY_PARAMCOUNT,Params);
  26. m_fMusicTime = TRUE; // override default setting.
  27. }
  28. STDMETHODIMP_(ULONG) CVelocityTool::AddRef()
  29. {
  30. return InterlockedIncrement(&m_cRef);
  31. }
  32. STDMETHODIMP_(ULONG) CVelocityTool::Release()
  33. {
  34. if( 0 == InterlockedDecrement(&m_cRef) )
  35. {
  36. delete this;
  37. return 0;
  38. }
  39. return m_cRef;
  40. }
  41. STDMETHODIMP CVelocityTool::QueryInterface(const IID &iid, void **ppv)
  42. {
  43. if (iid == IID_IUnknown || iid == IID_IDirectMusicTool || iid == IID_IDirectMusicTool8)
  44. {
  45. *ppv = static_cast<IDirectMusicTool8*>(this);
  46. }
  47. else if(iid == IID_IPersistStream)
  48. {
  49. *ppv = static_cast<IPersistStream*>(this);
  50. }
  51. else if(iid == IID_IDirectMusicVelocityTool)
  52. {
  53. *ppv = static_cast<IDirectMusicVelocityTool*>(this);
  54. }
  55. else if(iid == IID_IMediaParams)
  56. {
  57. *ppv = static_cast<IMediaParams*>(this);
  58. }
  59. else if(iid == IID_IMediaParamInfo)
  60. {
  61. *ppv = static_cast<IMediaParamInfo*>(this);
  62. }
  63. else if(iid == IID_ISpecifyPropertyPages)
  64. {
  65. *ppv = static_cast<ISpecifyPropertyPages*>(this);
  66. }
  67. else
  68. {
  69. *ppv = NULL;
  70. return E_NOINTERFACE;
  71. }
  72. AddRef();
  73. return S_OK;
  74. }
  75. //////////////////////////////////////////////////////////////////////
  76. // IPersistStream
  77. STDMETHODIMP CVelocityTool::GetClassID(CLSID* pClassID)
  78. {
  79. if (pClassID)
  80. {
  81. *pClassID = CLSID_DirectMusicVelocityTool;
  82. return S_OK;
  83. }
  84. return E_POINTER;
  85. }
  86. //////////////////////////////////////////////////////////////////////
  87. // IPersistStream Methods:
  88. STDMETHODIMP CVelocityTool::IsDirty()
  89. {
  90. if (m_fDirty) return S_OK;
  91. else return S_FALSE;
  92. }
  93. STDMETHODIMP CVelocityTool::Load(IStream* pStream)
  94. {
  95. EnterCriticalSection(&m_CrSec);
  96. DWORD dwChunkID;
  97. DWORD dwSize;
  98. HRESULT hr = pStream->Read(&dwChunkID, sizeof(dwChunkID), NULL);
  99. hr = pStream->Read(&dwSize, sizeof(dwSize), NULL);
  100. if(SUCCEEDED(hr) && (dwChunkID == FOURCC_VELOCITY_CHUNK))
  101. {
  102. DMUS_IO_VELOCITY_HEADER Header;
  103. memset(&Header,0,sizeof(Header));
  104. hr = pStream->Read(&Header, min(sizeof(Header),dwSize), NULL);
  105. if (SUCCEEDED(hr))
  106. {
  107. SetParam(DMUS_VELOCITY_STRENGTH,(float) Header.lStrength);
  108. SetParam(DMUS_VELOCITY_LOWLIMIT,(float) Header.lLowLimit);
  109. SetParam(DMUS_VELOCITY_HIGHLIMIT,(float) Header.lHighLimit);
  110. SetParam(DMUS_VELOCITY_CURVESTART,(float) Header.lCurveStart);
  111. SetParam(DMUS_VELOCITY_CURVEEND,(float) Header.lCurveEnd);
  112. }
  113. }
  114. m_fDirty = FALSE;
  115. LeaveCriticalSection(&m_CrSec);
  116. return hr;
  117. }
  118. STDMETHODIMP CVelocityTool::Save(IStream* pStream, BOOL fClearDirty)
  119. {
  120. EnterCriticalSection(&m_CrSec);
  121. DWORD dwChunkID = FOURCC_VELOCITY_CHUNK;
  122. DWORD dwSize = sizeof(DMUS_IO_VELOCITY_HEADER);
  123. HRESULT hr = pStream->Write(&dwChunkID, sizeof(dwChunkID), NULL);
  124. if (SUCCEEDED(hr))
  125. {
  126. hr = pStream->Write(&dwSize, sizeof(dwSize), NULL);
  127. }
  128. if (SUCCEEDED(hr))
  129. {
  130. DMUS_IO_VELOCITY_HEADER Header;
  131. GetParamInt(DMUS_VELOCITY_STRENGTH,MAX_REF_TIME,&Header.lStrength);
  132. GetParamInt(DMUS_VELOCITY_LOWLIMIT,MAX_REF_TIME,&Header.lLowLimit);
  133. GetParamInt(DMUS_VELOCITY_HIGHLIMIT,MAX_REF_TIME,&Header.lHighLimit);
  134. GetParamInt(DMUS_VELOCITY_CURVESTART,MAX_REF_TIME,&Header.lCurveStart);
  135. GetParamInt(DMUS_VELOCITY_CURVEEND,MAX_REF_TIME,&Header.lCurveEnd);
  136. hr = pStream->Write(&Header, sizeof(Header),NULL);
  137. }
  138. if (fClearDirty) m_fDirty = FALSE;
  139. LeaveCriticalSection(&m_CrSec);
  140. return hr;
  141. }
  142. STDMETHODIMP CVelocityTool::GetSizeMax(ULARGE_INTEGER* pcbSize)
  143. {
  144. if (pcbSize == NULL)
  145. {
  146. return E_POINTER;
  147. }
  148. pcbSize->QuadPart = sizeof(DMUS_IO_VELOCITY_HEADER) + 8; // Data plus RIFF header.
  149. return S_OK;
  150. }
  151. STDMETHODIMP CVelocityTool::GetPages(CAUUID * pPages)
  152. {
  153. pPages->cElems = 1;
  154. pPages->pElems = (GUID *) CoTaskMemAlloc(sizeof(GUID));
  155. if (pPages->pElems == NULL)
  156. return E_OUTOFMEMORY;
  157. *(pPages->pElems) = CLSID_VelocityPage;
  158. return NOERROR;
  159. }
  160. /////////////////////////////////////////////////////////////////
  161. // IDirectMusicTool
  162. STDMETHODIMP CVelocityTool::ProcessPMsg( IDirectMusicPerformance* pPerf,
  163. DMUS_PMSG* pPMsg )
  164. {
  165. // returning S_FREE frees the message. If StampPMsg()
  166. // fails, there is no destination for this message so
  167. // free it.
  168. if(NULL == pPMsg->pGraph )
  169. {
  170. return DMUS_S_FREE;
  171. }
  172. if (FAILED(pPMsg->pGraph->StampPMsg(pPMsg)))
  173. {
  174. return DMUS_S_FREE;
  175. }
  176. // We need to know the time format so we can call GetParamInt() to read control parameters.
  177. REFERENCE_TIME rtTime;
  178. if (m_fMusicTime) rtTime = pPMsg->mtTime;
  179. else rtTime = pPMsg->rtTime;
  180. if( pPMsg->dwType == DMUS_PMSGT_NOTE )
  181. {
  182. DMUS_NOTE_PMSG *pNote = (DMUS_NOTE_PMSG *) pPMsg;
  183. long lStrength;
  184. long lLowLimit, lHighLimit, lCurveStart, lCurveEnd;
  185. GetParamInt(DMUS_VELOCITY_STRENGTH,rtTime,&lStrength);
  186. GetParamInt(DMUS_VELOCITY_LOWLIMIT,rtTime,&lLowLimit);
  187. GetParamInt(DMUS_VELOCITY_HIGHLIMIT,rtTime,&lHighLimit);
  188. GetParamInt(DMUS_VELOCITY_CURVESTART,rtTime,&lCurveStart);
  189. GetParamInt(DMUS_VELOCITY_CURVEEND,rtTime,&lCurveEnd);
  190. if (lCurveStart <= lCurveEnd)
  191. {
  192. long lNewVelocity;
  193. if (pNote->bVelocity <= lCurveStart)
  194. {
  195. lNewVelocity = lLowLimit;
  196. }
  197. else if (pNote->bVelocity >= lCurveEnd)
  198. {
  199. lNewVelocity = lHighLimit;
  200. }
  201. else
  202. {
  203. // For this case, compute the point on the line between (lCurveStart, lLowLimit) and (lCurveEnd, lHighLimit)
  204. lNewVelocity = lLowLimit + ((lHighLimit - lLowLimit) * (pNote->bVelocity - lCurveStart)) / (lCurveEnd - lCurveStart);
  205. }
  206. // Now, calculate the change we want to apply.
  207. lNewVelocity -= pNote->bVelocity;
  208. // Scale it to the amount we'll actually do.
  209. lNewVelocity = (lNewVelocity * lStrength) / 100;
  210. lNewVelocity += pNote->bVelocity;
  211. if (lNewVelocity < 1) lNewVelocity = 1;
  212. if (lNewVelocity > 127) lNewVelocity = 127;
  213. pNote->bVelocity = (BYTE) lNewVelocity;
  214. }
  215. }
  216. return DMUS_S_REQUEUE;
  217. }
  218. STDMETHODIMP CVelocityTool::Clone( IDirectMusicTool ** ppTool)
  219. {
  220. CVelocityTool *pNew = new CVelocityTool;
  221. if (pNew)
  222. {
  223. HRESULT hr = pNew->CopyParamsFromSource(this);
  224. if (SUCCEEDED(hr))
  225. {
  226. *ppTool = (IDirectMusicTool *) pNew;
  227. }
  228. else
  229. {
  230. delete pNew;
  231. }
  232. return hr;
  233. }
  234. else
  235. {
  236. return E_OUTOFMEMORY;
  237. }
  238. }
  239. STDMETHODIMP CVelocityTool::SetStrength(long lStrength)
  240. {
  241. return SetParam(DMUS_VELOCITY_STRENGTH,(float) lStrength);
  242. }
  243. STDMETHODIMP CVelocityTool::SetLowLimit(long lVelocityOut)
  244. {
  245. return SetParam(DMUS_VELOCITY_LOWLIMIT,(float) lVelocityOut);
  246. }
  247. STDMETHODIMP CVelocityTool::SetHighLimit(long lVelocityOut)
  248. {
  249. return SetParam(DMUS_VELOCITY_HIGHLIMIT,(float) lVelocityOut);
  250. }
  251. STDMETHODIMP CVelocityTool::SetCurveStart(long lVelocityIn)
  252. {
  253. return SetParam(DMUS_VELOCITY_CURVESTART,(float) lVelocityIn);
  254. }
  255. STDMETHODIMP CVelocityTool::SetCurveEnd(long lVelocityIn)
  256. {
  257. return SetParam(DMUS_VELOCITY_CURVEEND,(float) lVelocityIn);
  258. }
  259. STDMETHODIMP CVelocityTool::GetStrength(long * plStrength)
  260. {
  261. return GetParamInt(DMUS_VELOCITY_STRENGTH,MAX_REF_TIME,plStrength);
  262. }
  263. STDMETHODIMP CVelocityTool::GetLowLimit(long * plVelocityOut)
  264. {
  265. return GetParamInt(DMUS_VELOCITY_LOWLIMIT,MAX_REF_TIME,plVelocityOut);
  266. }
  267. STDMETHODIMP CVelocityTool::GetHighLimit(long * plVelocityOut)
  268. {
  269. return GetParamInt(DMUS_VELOCITY_HIGHLIMIT,MAX_REF_TIME,plVelocityOut);
  270. }
  271. STDMETHODIMP CVelocityTool::GetCurveStart(long * plVelocityIn)
  272. {
  273. return GetParamInt(DMUS_VELOCITY_CURVESTART,MAX_REF_TIME,plVelocityIn);
  274. }
  275. STDMETHODIMP CVelocityTool::GetCurveEnd(long * plVelocityIn)
  276. {
  277. return GetParamInt(DMUS_VELOCITY_CURVEEND,MAX_REF_TIME,plVelocityIn);
  278. }