1
0

MediaParams.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. // MediaParams.cpp: implementation of the CMediaParams class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "AudioPlugIn.h"
  6. #include "MediaParams.h"
  7. #include "ParamEnvelope.h"
  8. #include "CakeMedParam_i.c"
  9. #define DEFINE_PARAM_INFO
  10. #include "Parameters.h"
  11. //////////////////////////////////////////////////////////////////////
  12. // Ctors
  13. CMediaParams::CMediaParams( IUnknown* pUnkOuter ) : m_pUnkOuter(pUnkOuter)
  14. {
  15. m_pCallback = NULL;
  16. m_cRef = 0;
  17. m_aEnv = NULL;
  18. m_dDecimationInterval = 20.0 / 1000.0; // 20 msec
  19. m_lFs = 44100;
  20. }
  21. CMediaParams::~CMediaParams()
  22. {
  23. ASSERT( 0 == m_cRef );
  24. if (m_pCallback)
  25. m_pCallback->Release();
  26. m_pCallback = NULL;
  27. m_pUnkOuter = NULL;
  28. delete [] m_aEnv;
  29. m_aEnv = NULL;
  30. }
  31. //////////////////////////////////////////////////////////////////////
  32. // Factory-style construction
  33. HRESULT CMediaParams::Create( CMediaParams** ppObj, IUnknown* pUnkOuter )
  34. {
  35. if (NULL == ppObj)
  36. return E_POINTER;
  37. if (NULL == pUnkOuter)
  38. return E_POINTER;
  39. // Construct the CMediaParams object
  40. CMediaParams* pNew = new CMediaParams( pUnkOuter );
  41. if (NULL == pNew)
  42. return E_OUTOFMEMORY;
  43. // Construct and initialize its parameters
  44. pNew->m_aEnv = new CParamEnvelope [ NUM_PARAMS ];
  45. if (NULL == pNew->m_aEnv)
  46. return E_OUTOFMEMORY;
  47. for (ULONG ix = 0; ix < NUM_PARAMS; ++ix)
  48. pNew->m_aEnv[ ix ].SetParamInfo( m_aParamInfo[ ix ] );
  49. pNew->AddRef();
  50. *ppObj = pNew;
  51. return S_OK;
  52. }
  53. ////////////////////////////////////////////////////////////////////////////////
  54. // Given a sample range, fills pTimes with sample positions where we need
  55. // to recompute one or more automated parameter values. Positions are always
  56. // added periodically at the decimation interval; positions are also added
  57. // for every segment boundary among all of the parameters.
  58. HRESULT CMediaParams::GetDecimationTimes( LONGLONG llSampStart,
  59. LONGLONG llSampEnd,
  60. std::vector<LONGLONG>* pTimes )
  61. {
  62. LONGLONG const llInterval = static_cast<LONGLONG>( GetDecimationInterval() * GetSampleRate() );
  63. double const dSamplesPerRefTime = static_cast<double>( GetSampleRate() ) / UNITS;
  64. REFERENCE_TIME const rtStart = REFERENCE_TIME( llSampStart / dSamplesPerRefTime + 0.5 );
  65. // Make an worst-case guess at how many decimation points we'll need
  66. ULONG uPoints = 0;
  67. for (DWORD dwParam = 0; dwParam < NUM_AUTOMATED_PARAMS; dwParam++)
  68. {
  69. const CParamEnvelope& env = m_aEnv[ dwParam ];
  70. uPoints += env.GetCount() * 2;
  71. }
  72. // If there is no automation, then there is no need to decimate
  73. if (0 == uPoints)
  74. return S_OK;
  75. // Account for points that are added due to periodic decimation
  76. uPoints += ULONG( ((llSampEnd - llSampStart) / llInterval) + 1 );
  77. // Reserve some memory for landmark points
  78. pTimes->reserve( uPoints );
  79. // Add periodic landmarks at the decimation interval
  80. LONGLONG llSamp = (llSampStart / llInterval) * llInterval;
  81. if (llSamp < llSampStart)
  82. llSamp += llInterval;
  83. while (llSamp < llSampEnd)
  84. {
  85. pTimes->push_back( llSamp );
  86. llSamp += llInterval;
  87. }
  88. // Add landmarks for each shape boundary
  89. for (dwParam = 0; dwParam < NUM_AUTOMATED_PARAMS; dwParam++)
  90. {
  91. const CParamEnvelope& env = m_aEnv[ dwParam ];
  92. unsigned const nCount = env.GetCount();
  93. // Add each shape endpoint that falls in our time range
  94. for (unsigned ix = 0; ix < nCount; ix++)
  95. {
  96. const MP_ENVELOPE_SEGMENT& seg = env.GetAt( ix );
  97. LONGLONG const llEnvStart = static_cast<LONGLONG>( seg.rtStart * dSamplesPerRefTime + 0.5 );
  98. LONGLONG const llEnvEnd = static_cast<LONGLONG>( seg.rtEnd * dSamplesPerRefTime + 0.5 );
  99. if (llSampStart <= llEnvStart && llEnvStart < llSampEnd)
  100. pTimes->push_back( llEnvStart );
  101. if (llSampStart <= llEnvEnd && llEnvEnd < llSampEnd)
  102. pTimes->push_back( llEnvEnd );
  103. }
  104. }
  105. // Sort result
  106. std::sort( pTimes->begin(), pTimes->end() );
  107. return S_OK;
  108. }
  109. ////////////////////////////////////////////////////////////////////////////////
  110. // Set the current position among all parameters, updating current envelope
  111. // value and deltas. This method is called repeatedly by the streaming code,
  112. // to update parameter values as they evolve along the duration of the envelope.
  113. HRESULT CMediaParams::UpdateValuesForSample( LONGLONG llSamp )
  114. {
  115. double const dSamplesPerRefTime = static_cast<double>( GetSampleRate() ) / UNITS;
  116. REFERENCE_TIME const rt = REFERENCE_TIME( llSamp / dSamplesPerRefTime + 0.5 );
  117. HRESULT hr = S_OK;
  118. for (DWORD dwParam = 0; dwParam < NUM_AUTOMATED_PARAMS; dwParam++)
  119. {
  120. hr = m_aEnv[ dwParam ].UpdateValuesForRefTime( rt, GetSampleRate() );
  121. if (FAILED( hr ))
  122. break;
  123. }
  124. return hr;
  125. }
  126. ////////////////////////////////////////////////////////////////////////////////
  127. // IUnknown
  128. HRESULT CMediaParams::QueryInterface( REFIID riid, void** ppv )
  129. {
  130. if (NULL == ppv)
  131. return E_POINTER;
  132. if (riid == IID_IUnknown)
  133. {
  134. *ppv = static_cast<IUnknown*>( static_cast<IMediaParams*>( this ) );
  135. m_pUnkOuter->AddRef();
  136. return S_OK;
  137. }
  138. else
  139. {
  140. return m_pUnkOuter->QueryInterface( riid, ppv );
  141. }
  142. }
  143. ULONG CMediaParams::AddRef()
  144. {
  145. return InterlockedIncrement( &m_cRef );
  146. }
  147. ULONG CMediaParams::Release()
  148. {
  149. ASSERT( m_cRef > 0 );
  150. ULONG ul = InterlockedDecrement( &m_cRef );
  151. if (0 == ul)
  152. {
  153. delete this;
  154. return 0;
  155. }
  156. else
  157. return ul;
  158. }
  159. ////////////////////////////////////////////////////////////////////////////////
  160. // IMediaParams
  161. HRESULT CMediaParams::GetParam(ULONG dwParamIndex, FLOAT* pValue)
  162. {
  163. if (dwParamIndex >= NUM_PARAMS)
  164. return E_INVALIDARG;
  165. if (NULL == pValue)
  166. return E_POINTER;
  167. return m_aEnv[ dwParamIndex ].GetParam( pValue );
  168. }
  169. ////////////////////////////////////////////////////////////////////////////////
  170. HRESULT CMediaParams::SetParam(ULONG dwParamIndex, FLOAT value)
  171. {
  172. if (dwParamIndex >= NUM_PARAMS)
  173. return E_INVALIDARG;
  174. return m_aEnv[ dwParamIndex ].SetParam( value );
  175. }
  176. ////////////////////////////////////////////////////////////////////////////////
  177. HRESULT CMediaParams::AddEnvelope(ULONG dwParamIndex, ULONG cSegments, MP_ENVELOPE_SEGMENT* pmpes)
  178. {
  179. if (dwParamIndex >= NUM_AUTOMATED_PARAMS && dwParamIndex != DWORD_ALLPARAMS)
  180. return E_INVALIDARG;
  181. if (0 == cSegments)
  182. return S_OK;
  183. if (IsBadReadPtr( pmpes, cSegments * sizeof(MP_ENVELOPE_SEGMENT) ))
  184. return E_POINTER;
  185. double const dSamplesPerRefTime = static_cast<double>( GetSampleRate() ) / UNITS;
  186. if (dwParamIndex == DWORD_ALLPARAMS)
  187. {
  188. for (ULONG ix = 0; ix < NUM_AUTOMATED_PARAMS; ix++)
  189. {
  190. HRESULT hr = m_aEnv[ ix ].AddEnvelope( cSegments, pmpes, dSamplesPerRefTime );
  191. if (FAILED( hr ))
  192. return hr;
  193. }
  194. return S_OK;
  195. }
  196. else
  197. {
  198. return m_aEnv[ dwParamIndex ].AddEnvelope( cSegments, pmpes, dSamplesPerRefTime );
  199. }
  200. }
  201. ////////////////////////////////////////////////////////////////////////////////
  202. HRESULT CMediaParams::FlushEnvelope(ULONG dwParamIndex, REFERENCE_TIME rtStart, REFERENCE_TIME rtEnd)
  203. {
  204. if (dwParamIndex >= NUM_AUTOMATED_PARAMS && dwParamIndex != DWORD_ALLPARAMS)
  205. return E_INVALIDARG;
  206. if (rtStart > rtEnd)
  207. return E_INVALIDARG;
  208. double const dSamplesPerRefTime = static_cast<double>( GetSampleRate() ) / UNITS;
  209. if (dwParamIndex == DWORD_ALLPARAMS)
  210. {
  211. for (ULONG ix = 0; ix < NUM_AUTOMATED_PARAMS; ix++)
  212. {
  213. HRESULT hr = m_aEnv[ ix ].FlushEnvelope( rtStart, rtEnd, dSamplesPerRefTime );
  214. if (FAILED( hr ))
  215. return hr;
  216. }
  217. return S_OK;
  218. }
  219. else
  220. {
  221. HRESULT hr = m_aEnv[ dwParamIndex ].FlushEnvelope( rtStart, rtEnd, dSamplesPerRefTime );
  222. if (FAILED( hr ))
  223. return hr;
  224. }
  225. return S_OK;
  226. }
  227. ////////////////////////////////////////////////////////////////////////////////
  228. HRESULT CMediaParams::SetTimeFormat(GUID guidTimeFormat, ULONG mpTimeData)
  229. {
  230. if (guidTimeFormat != GUID_TIME_REFERENCE)
  231. return E_INVALIDARG;
  232. return S_OK;
  233. }
  234. ////////////////////////////////////////////////////////////////////////////////
  235. // IMediaParamInfo
  236. HRESULT CMediaParams::GetParamCount(ULONG* pdwParams)
  237. {
  238. if (NULL == pdwParams)
  239. return E_POINTER;
  240. *pdwParams = NUM_AUTOMATED_PARAMS;
  241. return S_OK;
  242. }
  243. ////////////////////////////////////////////////////////////////////////////////
  244. HRESULT CMediaParams::GetParamInfo(ULONG dwParamIndex, MP_PARAMINFO* pInfo)
  245. {
  246. if (dwParamIndex >= NUM_AUTOMATED_PARAMS)
  247. return E_INVALIDARG;
  248. if (IsBadWritePtr( pInfo, sizeof(MP_PARAMINFO) ))
  249. return E_POINTER;
  250. *pInfo = m_aParamInfo[ dwParamIndex ].mppi;
  251. return S_OK;
  252. }
  253. ////////////////////////////////////////////////////////////////////////////////
  254. HRESULT CMediaParams::GetParamText(ULONG dwParamIndex, WCHAR** ppwchText)
  255. {
  256. if (dwParamIndex >= NUM_AUTOMATED_PARAMS)
  257. return E_INVALIDARG;
  258. if (NULL == ppwchText)
  259. return E_POINTER;
  260. const ParamInfo& info = m_aParamInfo[ dwParamIndex ];
  261. const MP_PARAMINFO& mppi = info.mppi;
  262. // Count up lengths of label and unit strings, plus null terminators
  263. int cch = wcslen(mppi.szLabel) + wcslen(mppi.szUnitText) + 3;
  264. // Add in length of the enum. text if any was supplied
  265. if (NULL != info.pwszEnumText)
  266. cch += wcslen(info.pwszEnumText) + 1;
  267. // Allocate memory for the returned string
  268. *ppwchText = (WCHAR*)CoTaskMemAlloc( sizeof(WCHAR) * cch );
  269. if (NULL == *ppwchText)
  270. return E_OUTOFMEMORY;
  271. // Text format is "Name\0Units\0Enum1\0Enum2\0...EnumN\0\0"
  272. WCHAR* pwsz = *ppwchText;
  273. // [1] Copy in the name
  274. wcscpy( pwsz, mppi.szLabel );
  275. pwsz += wcslen(mppi.szLabel) + 1;
  276. // [2] Copy in the units
  277. wcscpy( pwsz, mppi.szUnitText );
  278. pwsz += wcslen(mppi.szUnitText) + 1;
  279. // [3] Copy in the enum. text, if any was supplied
  280. if (NULL != info.pwszEnumText)
  281. {
  282. wcscpy( pwsz, info.pwszEnumText );
  283. // Replace commas with nulls, to conform to DX8 string format spec
  284. while (*pwsz)
  285. {
  286. if (*pwsz == L',')
  287. *pwsz = 0;
  288. pwsz++;
  289. }
  290. }
  291. return S_OK;
  292. }
  293. ////////////////////////////////////////////////////////////////////////////////
  294. HRESULT CMediaParams::GetNumTimeFormats(ULONG* pdwNumTimeFormats)
  295. {
  296. if (NULL == pdwNumTimeFormats)
  297. return E_POINTER;
  298. *pdwNumTimeFormats = 1;
  299. return S_OK;
  300. }
  301. ////////////////////////////////////////////////////////////////////////////////
  302. HRESULT CMediaParams::GetSupportedTimeFormat(ULONG dwFormatIndex, GUID* pguidTimeFormat)
  303. {
  304. if (NULL == pguidTimeFormat)
  305. return E_POINTER;
  306. if (0 != dwFormatIndex)
  307. return E_INVALIDARG;
  308. *pguidTimeFormat = GUID_TIME_REFERENCE;
  309. return S_OK;
  310. }
  311. ////////////////////////////////////////////////////////////////////////////////
  312. HRESULT CMediaParams::GetCurrentTimeFormat(GUID* pguidTimeFormat, ULONG*)
  313. {
  314. if (NULL == pguidTimeFormat)
  315. return E_POINTER;
  316. *pguidTimeFormat = GUID_TIME_REFERENCE;
  317. return S_OK;
  318. }
  319. ////////////////////////////////////////////////////////////////////////////////
  320. // IMediaParamsSetUICallback
  321. HRESULT CMediaParams::SetUICallback(IMediaParamsUICallback* pICallback)
  322. {
  323. if (pICallback)
  324. pICallback->AddRef();
  325. if (m_pCallback)
  326. m_pCallback->Release();
  327. m_pCallback = pICallback;
  328. return S_OK;
  329. }
  330. ////////////////////////////////////////////////////////////////////////////////
  331. // IMediaParamsUICallback
  332. HRESULT CMediaParams::ParamsBeginCapture(DWORD *aIndex, DWORD cPoints)
  333. {
  334. HRESULT hr = S_OK;
  335. // Inform each parameter that capture has begun
  336. for (DWORD ix = 0; ix < cPoints; ix++)
  337. m_aEnv[ aIndex[ ix ] ].BeginCapture();
  338. if (m_pCallback)
  339. hr = m_pCallback->ParamsBeginCapture( aIndex, cPoints );
  340. return hr;
  341. }
  342. HRESULT CMediaParams::ParamsChanged(DWORD *aIndex, DWORD cPoints, MP_DATA *paData)
  343. {
  344. HRESULT hr = S_OK;
  345. // Send the parameter change to each parameter
  346. for (DWORD ix = 0; ix < cPoints; ix++)
  347. {
  348. hr = SetParam( aIndex[ ix ], paData[ ix ] );
  349. if (FAILED( hr ))
  350. return hr;
  351. }
  352. // Send the parameter change to our callback
  353. if (m_pCallback)
  354. hr = m_pCallback->ParamsChanged( aIndex, cPoints, paData );
  355. return hr;
  356. }
  357. HRESULT CMediaParams::ParamsEndCapture(DWORD *aIndex, DWORD cPoints)
  358. {
  359. HRESULT hr = S_OK;
  360. // Inform each parameter that capture has ended
  361. for (DWORD ix = 0; ix < cPoints; ix++)
  362. m_aEnv[ aIndex[ ix ] ].EndCapture();
  363. if (m_pCallback)
  364. hr = m_pCallback->ParamsEndCapture( aIndex, cPoints );
  365. return hr;
  366. }
  367. ////////////////////////////////////////////////////////////////////////////////