Leaked source code of windows server 2003
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.

390 lines
12 KiB

  1. #include <windows.h>
  2. #include "sverb.h"
  3. #include "sverbp.h"
  4. #include "clone.h"
  5. STD_CREATE(WavesReverb)
  6. //////////////////////////////////////////////////////////////////////////////
  7. //
  8. // CDirectSoundWavesReverbDMO::NDQueryInterface
  9. //
  10. // Subclass can override if it wants to implement more interfaces.
  11. //
  12. STDMETHODIMP CDirectSoundWavesReverbDMO::NDQueryInterface(THIS_ REFIID riid, LPVOID *ppv)
  13. {
  14. IMP_DSDMO_QI(riid,ppv);
  15. if (riid == IID_IPersist)
  16. {
  17. return GetInterface((IPersist*)this, ppv);
  18. }
  19. else if (riid == IID_IMediaObject)
  20. {
  21. return GetInterface((IMediaObject*)this, ppv);
  22. }
  23. else if (riid == IID_IDirectSoundFXWavesReverb)
  24. {
  25. return GetInterface((IDirectSoundFXWavesReverb*)this, ppv);
  26. }
  27. else if (riid == IID_ISpecifyPropertyPages)
  28. {
  29. return GetInterface((ISpecifyPropertyPages*)this, ppv);
  30. }
  31. else if (riid == IID_IMediaParams)
  32. {
  33. return GetInterface((IMediaParams*)this, ppv);
  34. }
  35. else if (riid == IID_IMediaParamInfo)
  36. {
  37. return GetInterface((IMediaParamInfo*)this, ppv);
  38. }
  39. else
  40. return CComBase::NDQueryInterface(riid, ppv);
  41. }
  42. //////////////////////////////////////////////////////////////////////////////
  43. //
  44. // CDirectSoundWavesReverbDMO::Clone
  45. //
  46. STDMETHODIMP CDirectSoundWavesReverbDMO::Clone(IMediaObjectInPlace **pp)
  47. {
  48. return StandardDMOClone<CDirectSoundWavesReverbDMO, DSFXWavesReverb>(this, pp);
  49. }
  50. //////////////////////////////////////////////////////////////////////////////
  51. //
  52. // CDirectSoundWavesReverbDMO::CDirectSoundWavesReverbDMO
  53. //
  54. CDirectSoundWavesReverbDMO::CDirectSoundWavesReverbDMO( IUnknown *pUnk, HRESULT *phr )
  55. : CComBase( pUnk, phr ),
  56. m_fDirty(TRUE),
  57. m_pbCoeffs(NULL),
  58. m_plStates(NULL),
  59. m_fInitCPCMDMO(false),
  60. m_pfnSVerbProcess(NULL),
  61. m_fGain(DSFX_WAVESREVERB_INGAIN_DEFAULT),
  62. m_fMix(DSFX_WAVESREVERB_REVERBMIX_DEFAULT),
  63. m_fTime(DSFX_WAVESREVERB_REVERBTIME_DEFAULT),
  64. m_fRatio(DSFX_WAVESREVERB_HIGHFREQRTRATIO_DEFAULT)
  65. {
  66. }
  67. //////////////////////////////////////////////////////////////////////////////
  68. //
  69. // CDirectSoundWavesReverbDMO::~CDirectSoundWavesReverbDMO
  70. //
  71. CDirectSoundWavesReverbDMO::~CDirectSoundWavesReverbDMO()
  72. {
  73. delete[] m_pbCoeffs;
  74. delete[] m_plStates;
  75. }
  76. const MP_CAPS g_capsAll = MP_CAPS_CURVE_JUMP | MP_CAPS_CURVE_LINEAR | MP_CAPS_CURVE_SQUARE | MP_CAPS_CURVE_INVSQUARE | MP_CAPS_CURVE_SINE;
  77. static ParamInfo g_params[] =
  78. {
  79. // index type caps min, max, neutral, unit text, label, pwchText
  80. SVP_Gain, MPT_FLOAT, g_capsAll, DSFX_WAVESREVERB_INGAIN_MIN, DSFX_WAVESREVERB_INGAIN_MAX, DSFX_WAVESREVERB_INGAIN_DEFAULT, L"dB", L"InGain", L"",
  81. SVP_Mix, MPT_FLOAT, g_capsAll, DSFX_WAVESREVERB_REVERBMIX_MIN, DSFX_WAVESREVERB_REVERBMIX_MAX, DSFX_WAVESREVERB_REVERBMIX_DEFAULT, L"dB", L"ReverbMix", L"",
  82. SVP_ReverbTime, MPT_FLOAT, g_capsAll, DSFX_WAVESREVERB_REVERBTIME_MIN, DSFX_WAVESREVERB_REVERBTIME_MAX, DSFX_WAVESREVERB_REVERBTIME_DEFAULT, L"ms", L"ReverbTime", L"",
  83. SVP_Ratio, MPT_FLOAT, g_capsAll, DSFX_WAVESREVERB_HIGHFREQRTRATIO_MIN, DSFX_WAVESREVERB_HIGHFREQRTRATIO_MAX, DSFX_WAVESREVERB_HIGHFREQRTRATIO_DEFAULT, L"", L"HighFreqRTRatio", L"",
  84. };
  85. HRESULT CDirectSoundWavesReverbDMO::InitOnCreation()
  86. {
  87. HRESULT hr = InitParams(1, &GUID_TIME_REFERENCE, 0, 0, sizeof(g_params)/sizeof(*g_params), g_params);
  88. return hr;
  89. }
  90. HRESULT CDirectSoundWavesReverbDMO::Init()
  91. {
  92. HRESULT hr = S_OK;
  93. DMO_MEDIA_TYPE *pmt = InputType();
  94. if (pmt->majortype != MEDIATYPE_Audio ||
  95. pmt->subtype != MEDIASUBTYPE_PCM ||
  96. pmt->formattype != FORMAT_WaveFormatEx)
  97. {
  98. hr = E_INVALIDARG;
  99. TraceI(1,"ERROR: Invalid Format specified during SetInputType()\n");
  100. }
  101. WAVEFORMATEX *pwfex = (WAVEFORMATEX*)pmt->pbFormat;
  102. if (SUCCEEDED(hr))
  103. {
  104. if (pwfex->wFormatTag != WAVE_FORMAT_PCM ||
  105. pwfex->wBitsPerSample != 16)
  106. {
  107. hr = E_INVALIDARG;
  108. TraceI(1,"ERROR: Invalid Format specified during SetInputType()\n");
  109. }
  110. }
  111. if (SUCCEEDED(hr))
  112. {
  113. switch (pwfex->nChannels)
  114. {
  115. case 1:
  116. m_pfnSVerbProcess = SVerbMonoToMonoShort;
  117. break;
  118. case 2:
  119. m_pfnSVerbProcess = SVerbStereoToStereoShort;
  120. break;
  121. default:
  122. hr = E_FAIL;
  123. TraceI(1,"ERROR: Waves Reverb only supports mono or stereo\n");
  124. }
  125. }
  126. // Formats have been set. Initialize the reverb.
  127. //
  128. m_pbCoeffs = new BYTE[GetCoefsSize()];
  129. m_plStates = new long[(GetStatesSize() + sizeof(long) - 1)/ sizeof(long)];
  130. if (m_pbCoeffs == NULL || m_plStates == NULL)
  131. {
  132. hr = E_OUTOFMEMORY;
  133. TraceI(1,"ERROR: Out of memory\n");
  134. }
  135. if (SUCCEEDED(hr))
  136. {
  137. memset(m_plStates, 0, GetStatesSize());
  138. InitSVerb((float)m_ulSamplingRate, m_pbCoeffs);
  139. InitSVerbStates(m_plStates);
  140. m_fInitCPCMDMO = true;
  141. }
  142. Discontinuity();
  143. return hr;
  144. }
  145. HRESULT CDirectSoundWavesReverbDMO::Discontinuity()
  146. {
  147. HRESULT hr;
  148. DSFXWavesReverb wavesreverb;
  149. if (m_pbCoeffs && m_plStates)
  150. {
  151. memset(m_plStates, 0, GetStatesSize());
  152. InitSVerb((float)m_ulSamplingRate, m_pbCoeffs);
  153. InitSVerbStates(m_plStates);
  154. }
  155. hr = GetAllParameters(&wavesreverb);
  156. if (SUCCEEDED(hr))
  157. {
  158. hr = SetAllParameters(&wavesreverb);
  159. }
  160. if (SUCCEEDED(hr))
  161. {
  162. UpdateCoefficients();
  163. }
  164. return hr;
  165. }
  166. //////////////////////////////////////////////////////////////////////////////
  167. //
  168. // CDirectSoundWavesReverbDMO::FBRProcess
  169. //
  170. HRESULT CDirectSoundWavesReverbDMO::FBRProcess(DWORD cSamples, BYTE *pIn, BYTE *pOut)
  171. {
  172. assert(m_pfnSVerbProcess);
  173. (*m_pfnSVerbProcess)(
  174. cSamples,
  175. (short*)pIn,
  176. (short*)pOut,
  177. m_pbCoeffs,
  178. m_plStates);
  179. return S_OK;
  180. }
  181. //////////////////////////////////////////////////////////////////////////////
  182. //
  183. // CDirectSoundWavesReverbDMO::ProcessInPlace
  184. //
  185. HRESULT CDirectSoundWavesReverbDMO::ProcessInPlace(ULONG ulQuanta, LPBYTE pcbData, REFERENCE_TIME rtStart, DWORD dwFlags)
  186. {
  187. // Update parameter values from any curves that may be in effect.
  188. if (this->GetActiveParamBits())
  189. {
  190. this->UpdateActiveParams(rtStart, *this);
  191. this->UpdateCoefficients();
  192. }
  193. return FBRProcess(ulQuanta, pcbData, pcbData);
  194. }
  195. //////////////////////////////////////////////////////////////////////////////
  196. //
  197. // CDirectSoundWavesReverbDMO::SetParam
  198. //
  199. STDMETHODIMP CDirectSoundWavesReverbDMO::SetParam(DWORD dwParamIndex,MP_DATA value)
  200. {
  201. HRESULT hr = SetParamInternal(dwParamIndex, value, false);
  202. if (SUCCEEDED(hr))
  203. this->UpdateCoefficients();
  204. return hr;
  205. }
  206. //////////////////////////////////////////////////////////////////////////////
  207. //
  208. // CDirectSoundWavesReverbDMO::SetParamInternal
  209. //
  210. HRESULT CDirectSoundWavesReverbDMO::SetParamInternal(DWORD dwParamIndex, MP_DATA value, bool fSkipPasssingToParamManager)
  211. {
  212. switch (dwParamIndex)
  213. {
  214. case SVP_Gain:
  215. CHECK_PARAM(DSFX_WAVESREVERB_INGAIN_MIN, DSFX_WAVESREVERB_INGAIN_MAX);
  216. m_fGain = value;
  217. break;
  218. case SVP_Mix:
  219. CHECK_PARAM(DSFX_WAVESREVERB_REVERBMIX_MIN,DSFX_WAVESREVERB_REVERBMIX_MAX);
  220. m_fMix = value;
  221. break;
  222. case SVP_ReverbTime:
  223. CHECK_PARAM(DSFX_WAVESREVERB_REVERBTIME_MIN,DSFX_WAVESREVERB_REVERBTIME_MAX);
  224. m_fTime = value;
  225. break;
  226. case SVP_Ratio:
  227. CHECK_PARAM(DSFX_WAVESREVERB_HIGHFREQRTRATIO_MIN,DSFX_WAVESREVERB_HIGHFREQRTRATIO_MAX);
  228. m_fRatio = value;
  229. break;
  230. default:
  231. return E_FAIL;
  232. }
  233. // Let base class set this so it can handle all the rest of the param calls
  234. //
  235. HRESULT hr = fSkipPasssingToParamManager ? S_OK : CParamsManager::SetParam(dwParamIndex, value);
  236. return hr;
  237. }
  238. void CDirectSoundWavesReverbDMO::UpdateCoefficients()
  239. {
  240. // Waves Reverb has a single SetSVerb call that updates all parameters simultaneously instead of internal
  241. // state variables that are updated incrementally by changes to individual parameters as the other DMOs do.
  242. if (m_fInitCPCMDMO)
  243. {
  244. SetSVerb(
  245. m_fGain,
  246. m_fMix,
  247. m_fTime,
  248. m_fRatio,
  249. m_pbCoeffs);
  250. }
  251. }
  252. //////////////////////////////////////////////////////////////////////////////
  253. //
  254. // CDirectSoundWavesReverbDMO::SetAllParameters
  255. //
  256. STDMETHODIMP CDirectSoundWavesReverbDMO::SetAllParameters(THIS_ LPCDSFXWavesReverb pwr)
  257. {
  258. HRESULT hr = S_OK;
  259. // Check that the pointer is not NULL
  260. if (pwr == NULL)
  261. {
  262. TraceI(1,"ERROR: pwr is NULL\n");
  263. hr = E_POINTER;
  264. }
  265. // Set the parameters
  266. if (SUCCEEDED(hr)) hr = SetParamInternal(SVP_Gain, pwr->fInGain, false);
  267. if (SUCCEEDED(hr)) hr = SetParamInternal(SVP_Mix, pwr->fReverbMix, false);
  268. if (SUCCEEDED(hr)) hr = SetParamInternal(SVP_ReverbTime, pwr->fReverbTime, false);
  269. if (SUCCEEDED(hr)) hr = SetParamInternal(SVP_Ratio, pwr->fHighFreqRTRatio, false);
  270. this->UpdateCoefficients();
  271. return hr;
  272. }
  273. //////////////////////////////////////////////////////////////////////////////
  274. //
  275. // CDirectSoundWavesReverbDMO::GetAllParameters
  276. //
  277. HRESULT CDirectSoundWavesReverbDMO::GetAllParameters(THIS_ LPDSFXWavesReverb pwr)
  278. {
  279. HRESULT hr = S_OK;
  280. MP_DATA mpd;
  281. if (pwr == NULL) return E_POINTER;
  282. #define GET_PARAM(x,y) \
  283. if (SUCCEEDED(hr)) { \
  284. hr = GetParam(x, &mpd); \
  285. if (SUCCEEDED(hr)) pwr->y = mpd; \
  286. }
  287. #define GET_PARAM_LONG(x,y) \
  288. if (SUCCEEDED(hr)) { \
  289. hr = GetParam(x, &mpd); \
  290. if (SUCCEEDED(hr)) pwr->y = (long)mpd; \
  291. }
  292. GET_PARAM(SVP_Gain, fInGain);
  293. GET_PARAM(SVP_Mix, fReverbMix);
  294. GET_PARAM(SVP_ReverbTime, fReverbTime);
  295. GET_PARAM(SVP_Ratio, fHighFreqRTRatio);
  296. return S_OK;
  297. }
  298. HRESULT CDirectSoundWavesReverbDMO::CheckInputType(const DMO_MEDIA_TYPE *pmt)
  299. {
  300. if (NULL == pmt) {
  301. return E_POINTER;
  302. }
  303. // Verify that this is PCM with a WAVEFORMATEX format specifier
  304. if ((pmt->majortype != MEDIATYPE_Audio) ||
  305. (pmt->subtype != MEDIASUBTYPE_PCM) ||
  306. (pmt->formattype != FORMAT_WaveFormatEx) ||
  307. (pmt->cbFormat < sizeof(WAVEFORMATEX)) ||
  308. (pmt->pbFormat == NULL))
  309. return DMO_E_TYPE_NOT_ACCEPTED;
  310. // Verify the wave format
  311. WAVEFORMATEX *pWave = (WAVEFORMATEX*)pmt->pbFormat;
  312. if (pWave->wFormatTag != WAVE_FORMAT_PCM ||
  313. pWave->wBitsPerSample != 16 ||
  314. pWave->nChannels != 1 && pWave->nChannels != 2)
  315. {
  316. return DMO_E_TYPE_NOT_ACCEPTED;
  317. }
  318. return NOERROR;
  319. }
  320. // GetClassID
  321. //
  322. // Part of the persistent file support. We must supply our class id
  323. // which can be saved in a graph file and used on loading a graph with
  324. // this fx in it to instantiate this filter via CoCreateInstance.
  325. //
  326. HRESULT CDirectSoundWavesReverbDMO::GetClassID(CLSID *pClsid)
  327. {
  328. if (pClsid==NULL) {
  329. return E_POINTER;
  330. }
  331. *pClsid = GUID_DSFX_WAVES_REVERB;
  332. return NOERROR;
  333. } // GetClassID