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.

311 lines
9.3 KiB

  1. // Quantize.cpp : Implementation of CQuantizeTool
  2. //
  3. // Copyright (C) 1999 Microsoft Corporation. All Rights Reserved
  4. //
  5. #include "dmusicc.h"
  6. #include "dmusici.h"
  7. #include "debug.h"
  8. #include "quantize.h"
  9. #include "toolhelp.h"
  10. CQuantizeTool::CQuantizeTool()
  11. {
  12. ParamInfo Params[DMUS_QUANTIZE_PARAMCOUNT] =
  13. {
  14. { DMUS_QUANTIZE_STRENGTH, MPT_INT,MP_CAPS_ALL,0,110,80,
  15. L"Percent",L"Strength",NULL }, // Strength - 80% by default
  16. { DMUS_QUANTIZE_TIMEUNIT, MPT_ENUM,MP_CAPS_ALL, DMUS_TIME_UNIT_MTIME,DMUS_TIME_UNIT_1,DMUS_TIME_UNIT_GRID,
  17. L"",L"Resolution Units",L"Music Clicks,Grid,Beat,Bar,64th note triplets,64th notes,32nd note triplets,32nd notes,16th note triplets,16th notes,8th note triplets,8th notes,Quarter note triplets,Quarter notes,Half note triplets,Half notes,Whole note triplets,Whole notes" },
  18. { DMUS_QUANTIZE_RESOLUTION, MPT_INT,MP_CAPS_ALL,1,1000,1,
  19. L"",L"Resolution",NULL}, // Resolution - 1 grid note by default
  20. { DMUS_QUANTIZE_TYPE, MPT_ENUM,MP_CAPS_ALL, DMUS_QUANTIZET_START,DMUS_QUANTIZET_ALL,DMUS_QUANTIZET_START,
  21. L"",L"Type",L"Start Time,Duration,Start and Duration"} // Type - quantize start time by default
  22. };
  23. InitParams(DMUS_QUANTIZE_PARAMCOUNT,Params);
  24. m_fMusicTime = TRUE; // override default setting.
  25. }
  26. STDMETHODIMP_(ULONG) CQuantizeTool::AddRef()
  27. {
  28. return InterlockedIncrement(&m_cRef);
  29. }
  30. STDMETHODIMP_(ULONG) CQuantizeTool::Release()
  31. {
  32. if( 0 == InterlockedDecrement(&m_cRef) )
  33. {
  34. delete this;
  35. return 0;
  36. }
  37. return m_cRef;
  38. }
  39. STDMETHODIMP CQuantizeTool::QueryInterface(const IID &iid, void **ppv)
  40. {
  41. if (iid == IID_IUnknown || iid == IID_IDirectMusicTool || iid == IID_IDirectMusicTool8)
  42. {
  43. *ppv = static_cast<IDirectMusicTool8*>(this);
  44. }
  45. else if(iid == IID_IPersistStream)
  46. {
  47. *ppv = static_cast<IPersistStream*>(this);
  48. }
  49. else if(iid == IID_IDirectMusicQuantizeTool)
  50. {
  51. *ppv = static_cast<IDirectMusicQuantizeTool*>(this);
  52. }
  53. else if(iid == IID_IMediaParams)
  54. {
  55. *ppv = static_cast<IMediaParams*>(this);
  56. }
  57. else if(iid == IID_IMediaParamInfo)
  58. {
  59. *ppv = static_cast<IMediaParamInfo*>(this);
  60. }
  61. else if(iid == IID_ISpecifyPropertyPages)
  62. {
  63. *ppv = static_cast<ISpecifyPropertyPages*>(this);
  64. }
  65. else
  66. {
  67. *ppv = NULL;
  68. return E_NOINTERFACE;
  69. }
  70. AddRef();
  71. return S_OK;
  72. }
  73. //////////////////////////////////////////////////////////////////////
  74. // IPersistStream
  75. STDMETHODIMP CQuantizeTool::GetClassID(CLSID* pClassID)
  76. {
  77. if (pClassID)
  78. {
  79. *pClassID = CLSID_DirectMusicQuantizeTool;
  80. return S_OK;
  81. }
  82. return E_POINTER;
  83. }
  84. //////////////////////////////////////////////////////////////////////
  85. // IPersistStream Methods:
  86. STDMETHODIMP CQuantizeTool::IsDirty()
  87. {
  88. if (m_fDirty) return S_OK;
  89. else return S_FALSE;
  90. }
  91. STDMETHODIMP CQuantizeTool::Load(IStream* pStream)
  92. {
  93. EnterCriticalSection(&m_CrSec);
  94. DWORD dwChunkID;
  95. DWORD dwSize;
  96. HRESULT hr = pStream->Read(&dwChunkID, sizeof(dwChunkID), NULL);
  97. hr = pStream->Read(&dwSize, sizeof(dwSize), NULL);
  98. if(SUCCEEDED(hr) && (dwChunkID == FOURCC_QUANTIZE_CHUNK))
  99. {
  100. DMUS_IO_QUANTIZE_HEADER Header;
  101. memset(&Header,0,sizeof(Header));
  102. hr = pStream->Read(&Header, min(sizeof(Header),dwSize), NULL);
  103. if (SUCCEEDED(hr))
  104. {
  105. SetParam(DMUS_QUANTIZE_STRENGTH,(float) Header.dwStrength);
  106. SetParam(DMUS_QUANTIZE_TIMEUNIT,(float) Header.dwTimeUnit);
  107. SetParam(DMUS_QUANTIZE_RESOLUTION,(float) Header.dwResolution);
  108. SetParam(DMUS_QUANTIZE_TYPE,(float) Header.dwType);
  109. }
  110. }
  111. m_fDirty = FALSE;
  112. LeaveCriticalSection(&m_CrSec);
  113. return hr;
  114. }
  115. STDMETHODIMP CQuantizeTool::Save(IStream* pStream, BOOL fClearDirty)
  116. {
  117. EnterCriticalSection(&m_CrSec);
  118. DWORD dwChunkID = FOURCC_QUANTIZE_CHUNK;
  119. DWORD dwSize = sizeof(DMUS_IO_QUANTIZE_HEADER);
  120. HRESULT hr = pStream->Write(&dwChunkID, sizeof(dwChunkID), NULL);
  121. if (SUCCEEDED(hr))
  122. {
  123. hr = pStream->Write(&dwSize, sizeof(dwSize), NULL);
  124. }
  125. if (SUCCEEDED(hr))
  126. {
  127. DMUS_IO_QUANTIZE_HEADER Header;
  128. GetParamInt(DMUS_QUANTIZE_STRENGTH,MAX_REF_TIME,(long *)&Header.dwStrength);
  129. GetParamInt(DMUS_QUANTIZE_TIMEUNIT,MAX_REF_TIME,(long *) &Header.dwTimeUnit);
  130. GetParamInt(DMUS_QUANTIZE_RESOLUTION,MAX_REF_TIME,(long *) &Header.dwResolution);
  131. GetParamInt(DMUS_QUANTIZE_TYPE,MAX_REF_TIME,(long *) &Header.dwType);
  132. hr = pStream->Write(&Header, sizeof(Header),NULL);
  133. }
  134. if (fClearDirty) m_fDirty = FALSE;
  135. LeaveCriticalSection(&m_CrSec);
  136. return hr;
  137. }
  138. STDMETHODIMP CQuantizeTool::GetSizeMax(ULARGE_INTEGER* pcbSize)
  139. {
  140. if (pcbSize == NULL)
  141. {
  142. return E_POINTER;
  143. }
  144. pcbSize->QuadPart = sizeof(DMUS_IO_QUANTIZE_HEADER) + 8; // Data plus RIFF header.
  145. return S_OK;
  146. }
  147. STDMETHODIMP CQuantizeTool::GetPages(CAUUID * pPages)
  148. {
  149. pPages->cElems = 1;
  150. pPages->pElems = (GUID *) CoTaskMemAlloc(sizeof(GUID));
  151. if (pPages->pElems == NULL)
  152. return E_OUTOFMEMORY;
  153. *(pPages->pElems) = CLSID_QuantizePage;
  154. return NOERROR;
  155. }
  156. /////////////////////////////////////////////////////////////////
  157. // IDirectMusicTool
  158. STDMETHODIMP CQuantizeTool::ProcessPMsg( IDirectMusicPerformance* pPerf,
  159. DMUS_PMSG* pPMsg )
  160. {
  161. // returning S_FREE frees the message. If StampPMsg()
  162. // fails, there is no destination for this message so
  163. // free it.
  164. if(NULL == pPMsg->pGraph )
  165. {
  166. return DMUS_S_FREE;
  167. }
  168. if (FAILED(pPMsg->pGraph->StampPMsg(pPMsg)))
  169. {
  170. return DMUS_S_FREE;
  171. }
  172. // We need to know the time format so we can call GetParamInt() to read control parameters.
  173. REFERENCE_TIME rtTime;
  174. if (m_fMusicTime) rtTime = pPMsg->mtTime;
  175. else rtTime = pPMsg->rtTime;
  176. if( pPMsg->dwType == DMUS_PMSGT_NOTE )
  177. {
  178. DMUS_NOTE_PMSG *pNote = (DMUS_NOTE_PMSG *) pPMsg;
  179. IDirectMusicPerformance8 *pPerf8; // We'll need the DX8 interface to access ClonePMsg.
  180. if (SUCCEEDED(pPerf->QueryInterface(IID_IDirectMusicPerformance8,(void **)&pPerf8)))
  181. {
  182. long lStrength, lResolution, lTimeUnit, lType;
  183. GetParamInt(DMUS_QUANTIZE_STRENGTH,rtTime,&lStrength);
  184. GetParamInt(DMUS_QUANTIZE_RESOLUTION,rtTime,&lResolution);
  185. GetParamInt(DMUS_QUANTIZE_TIMEUNIT,rtTime,&lTimeUnit);
  186. GetParamInt(DMUS_QUANTIZE_TYPE,rtTime,&lType);
  187. DMUS_TIMESIGNATURE TimeSig;
  188. if (SUCCEEDED(pPerf8->GetParamEx(GUID_TimeSignature,pNote->dwVirtualTrackID,pNote->dwGroupID,DMUS_SEG_ANYTRACK,pNote->mtTime - pNote->nOffset,NULL,&TimeSig)))
  189. {
  190. lResolution *= CToolHelper::TimeUnitToTicks(lTimeUnit,&TimeSig);
  191. if (lResolution < 1) lResolution = 1;
  192. if ((lType == DMUS_QUANTIZET_START) || (lType == DMUS_QUANTIZET_ALL))
  193. {
  194. MUSIC_TIME mtTime = -TimeSig.mtTime;
  195. long lIntervals = (mtTime + (lResolution >> 1)) / lResolution;
  196. long lOffset = mtTime - (lIntervals * lResolution);
  197. lOffset *= lStrength;
  198. lOffset /= 100;
  199. pNote->mtTime -= lOffset;
  200. pNote->dwFlags &= ~DMUS_PMSGF_REFTIME;
  201. }
  202. if ((lType == DMUS_QUANTIZET_LENGTH) || (lType == DMUS_QUANTIZET_ALL))
  203. {
  204. long lIntervals = (pNote->mtDuration + (lResolution >> 1)) / lResolution;
  205. if (lIntervals < 1) lIntervals = 1;
  206. long lOffset = pNote->mtDuration - (lIntervals * lResolution);
  207. lOffset *= lStrength;
  208. lOffset /= 100;
  209. pNote->mtDuration -= lOffset;
  210. }
  211. }
  212. pPerf8->Release();
  213. }
  214. }
  215. return DMUS_S_REQUEUE;
  216. }
  217. STDMETHODIMP CQuantizeTool::Clone( IDirectMusicTool ** ppTool)
  218. {
  219. CQuantizeTool *pNew = new CQuantizeTool;
  220. if (pNew)
  221. {
  222. HRESULT hr = pNew->CopyParamsFromSource(this);
  223. if (SUCCEEDED(hr))
  224. {
  225. *ppTool = (IDirectMusicTool *) pNew;
  226. }
  227. else
  228. {
  229. delete pNew;
  230. }
  231. return hr;
  232. }
  233. else
  234. {
  235. return E_OUTOFMEMORY;
  236. }
  237. }
  238. STDMETHODIMP CQuantizeTool::SetStrength(DWORD dwStrength)
  239. {
  240. return SetParam(DMUS_QUANTIZE_STRENGTH,(float) dwStrength);
  241. }
  242. STDMETHODIMP CQuantizeTool::SetTimeUnit(DWORD dwTimeUnit)
  243. {
  244. return SetParam(DMUS_QUANTIZE_TIMEUNIT,(float) dwTimeUnit);
  245. }
  246. STDMETHODIMP CQuantizeTool::SetResolution(DWORD dwResolution)
  247. {
  248. return SetParam(DMUS_QUANTIZE_RESOLUTION,(float) dwResolution);
  249. }
  250. STDMETHODIMP CQuantizeTool::SetType(DWORD dwType)
  251. {
  252. return SetParam(DMUS_QUANTIZE_TYPE,(float) dwType);
  253. }
  254. STDMETHODIMP CQuantizeTool::GetStrength(DWORD * pdwStrength)
  255. {
  256. return GetParamInt(DMUS_QUANTIZE_STRENGTH,MAX_REF_TIME,(long *) pdwStrength);
  257. }
  258. STDMETHODIMP CQuantizeTool::GetTimeUnit(DWORD * pdwTimeUnit)
  259. {
  260. return GetParamInt(DMUS_QUANTIZE_TIMEUNIT,MAX_REF_TIME,(long *) pdwTimeUnit);
  261. }
  262. STDMETHODIMP CQuantizeTool::GetResolution(DWORD * pdwResolution)
  263. {
  264. return GetParamInt(DMUS_QUANTIZE_RESOLUTION,MAX_REF_TIME,(long *) pdwResolution);
  265. }
  266. STDMETHODIMP CQuantizeTool::GetType(DWORD * pdwType)
  267. {
  268. return GetParamInt(DMUS_QUANTIZE_TYPE,MAX_REF_TIME,(long *) pdwType);
  269. }