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.

272 lines
8.5 KiB

  1. #include <windows.h>
  2. #include "garglep.h"
  3. #include "clone.h"
  4. STD_CREATE(Gargle)
  5. #define DEFAULT_GARGLE_RATE 20
  6. CDirectSoundGargleDMO::CDirectSoundGargleDMO( IUnknown *pUnk, HRESULT *phr )
  7. :CComBase( pUnk, phr ),
  8. m_ulShape(0),
  9. m_ulGargleFreqHz(DEFAULT_GARGLE_RATE),
  10. m_fDirty(true),
  11. m_bInitialized(FALSE)
  12. {
  13. }
  14. HRESULT CDirectSoundGargleDMO::NDQueryInterface(REFIID riid, void **ppv) {
  15. IMP_DSDMO_QI(riid,ppv);
  16. if (riid == IID_IPersist)
  17. {
  18. return GetInterface((IPersist*)this, ppv);
  19. }
  20. else if (riid == IID_IMediaObject)
  21. {
  22. return GetInterface((IMediaObject*)this, ppv);
  23. }
  24. else if (riid == IID_IDirectSoundFXGargle)
  25. {
  26. return GetInterface((IDirectSoundFXGargle*)this, ppv);
  27. }
  28. else if (riid == IID_ISpecifyPropertyPages)
  29. {
  30. return GetInterface((ISpecifyPropertyPages*)this, ppv);
  31. }
  32. else if (riid == IID_IMediaParams)
  33. {
  34. return GetInterface((IMediaParams*)this, ppv);
  35. }
  36. else if (riid == IID_IMediaParamInfo)
  37. {
  38. return GetInterface((IMediaParamInfo*)this, ppv);
  39. }
  40. else
  41. return CComBase::NDQueryInterface(riid, ppv);
  42. }
  43. CDirectSoundGargleDMO::~CDirectSoundGargleDMO()
  44. {
  45. }
  46. 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;
  47. static ParamInfo g_params[] =
  48. {
  49. // index type caps min, max, neutral, unit text, label, pwchText??
  50. GFP_Rate, MPT_INT, g_capsAll, DSFXGARGLE_RATEHZ_MIN, DSFXGARGLE_RATEHZ_MAX, 20, L"Hz", L"Rate", L"",
  51. GFP_Shape, MPT_ENUM, g_capsAll, DSFXCHORUS_WAVE_TRIANGLE, DSFXGARGLE_WAVE_SQUARE, DSFXGARGLE_WAVE_TRIANGLE, L"", L"WaveShape", L"Triangle,Square",
  52. };
  53. HRESULT CDirectSoundGargleDMO::InitOnCreation()
  54. {
  55. HRESULT hr = InitParams(1, &GUID_TIME_REFERENCE, 0, 0, sizeof(g_params)/sizeof(*g_params), g_params);
  56. return hr;
  57. }
  58. HRESULT CDirectSoundGargleDMO::Init()
  59. {
  60. // compute the period
  61. m_ulPeriod = m_ulSamplingRate / m_ulGargleFreqHz;
  62. m_bInitialized = TRUE;
  63. return S_OK;
  64. }
  65. //////////////////////////////////////////////////////////////////////////////
  66. //
  67. // CDirectSoundGargleDMO::Clone
  68. //
  69. STDMETHODIMP CDirectSoundGargleDMO::Clone(IMediaObjectInPlace **pp)
  70. {
  71. return StandardDMOClone<CDirectSoundGargleDMO, DSFXGargle>(this, pp);
  72. }
  73. HRESULT CDirectSoundGargleDMO::Discontinuity() {
  74. m_ulPhase = 0;
  75. return NOERROR;
  76. }
  77. HRESULT CDirectSoundGargleDMO::FBRProcess(DWORD cSamples, BYTE *pIn, BYTE *pOut) {
  78. if (!m_bInitialized)
  79. return DMO_E_TYPE_NOT_SET;
  80. // test code
  81. //memcpy(pOut, pIn, cSamples * m_cChannels * (m_b8bit ? 1 : 2));
  82. //return NOERROR;
  83. DWORD cSample, cChannel;
  84. for (cSample = 0; cSample < cSamples; cSample++) {
  85. // If m_Shape is 0 (triangle) then we multiply by a triangular waveform
  86. // that runs 0..Period/2..0..Period/2..0... else by a square one that
  87. // is either 0 or Period/2 (same maximum as the triangle) or zero.
  88. //
  89. // m_Phase is the number of samples from the start of the period.
  90. // We keep this running from one call to the next,
  91. // but if the period changes so as to make this more
  92. // than Period then we reset to 0 with a bang. This may cause
  93. // an audible click or pop (but, hey! it's only a sample!)
  94. //
  95. ++m_ulPhase;
  96. if (m_ulPhase > m_ulPeriod)
  97. m_ulPhase = 0;
  98. ULONG ulM = m_ulPhase; // m is what we modulate with
  99. if (m_ulShape == 0) { // Triangle
  100. if (ulM > m_ulPeriod / 2)
  101. ulM = m_ulPeriod - ulM; // handle downslope
  102. } else { // Square wave
  103. if (ulM <= m_ulPeriod / 2)
  104. ulM = m_ulPeriod / 2;
  105. else
  106. ulM = 0;
  107. }
  108. for (cChannel = 0; cChannel < m_cChannels; cChannel++) {
  109. if (m_b8bit) {
  110. // sound sample, zero based
  111. int i = pIn[cSample * m_cChannels + cChannel] - 128;
  112. // modulate
  113. i = (i * (signed)ulM * 2) / (signed)m_ulPeriod;
  114. // 8 bit sound uses 0..255 representing -128..127
  115. // Any overflow, even by 1, would sound very bad.
  116. // so we clip paranoically after modulating.
  117. // I think it should never clip by more than 1
  118. //
  119. if (i > 127)
  120. i = 127;
  121. if (i < -128)
  122. i = -128;
  123. // reset zero offset to 128
  124. pOut[cSample * m_cChannels + cChannel] = (unsigned char)(i + 128);
  125. } else {
  126. // 16 bit sound uses 16 bits properly (0 means 0)
  127. // We still clip paranoically
  128. //
  129. int i = ((short*)pIn)[cSample * m_cChannels + cChannel];
  130. // modulate
  131. i = (i * (signed)ulM * 2) / (signed)m_ulPeriod;
  132. // clip
  133. if (i > 32767)
  134. i = 32767;
  135. if (i < -32768)
  136. i = -32768;
  137. ((short*)pOut)[cSample * m_cChannels + cChannel] = (short)i;
  138. }
  139. }
  140. }
  141. return NOERROR;
  142. }
  143. // GetClassID
  144. //
  145. // Part of the persistent file support. We must supply our class id
  146. // which can be saved in a graph file and used on loading a graph with
  147. // a gargle in it to instantiate this filter via CoCreateInstance.
  148. //
  149. HRESULT CDirectSoundGargleDMO::GetClassID(CLSID *pClsid)
  150. {
  151. if (pClsid==NULL) {
  152. return E_POINTER;
  153. }
  154. *pClsid = GUID_DSFX_STANDARD_GARGLE;
  155. return NOERROR;
  156. } // GetClassID
  157. //////////////////////////////////////////////////////////////////////////////
  158. //
  159. // CDirectSoundGargleDMO::SetAllParameters
  160. //
  161. STDMETHODIMP CDirectSoundGargleDMO::SetAllParameters(THIS_ LPCDSFXGargle pParm)
  162. {
  163. HRESULT hr = S_OK;
  164. // Check that the pointer is not NULL
  165. if (pParm == NULL)
  166. {
  167. Trace(1,"ERROR: pParm is NULL\n");
  168. hr = E_POINTER;
  169. }
  170. // Set the parameters
  171. if (SUCCEEDED(hr)) hr = SetParam(GFP_Rate, static_cast<MP_DATA>(pParm->dwRateHz));
  172. if (SUCCEEDED(hr)) hr = SetParam(GFP_Shape, static_cast<MP_DATA>(pParm->dwWaveShape));
  173. m_fDirty = true;
  174. return hr;
  175. }
  176. //////////////////////////////////////////////////////////////////////////////
  177. //
  178. // CDirectSoundGargleDMO::GetAllParameters
  179. //
  180. STDMETHODIMP CDirectSoundGargleDMO::GetAllParameters(THIS_ LPDSFXGargle pParm)
  181. {
  182. HRESULT hr = S_OK;
  183. MP_DATA var;
  184. if (pParm == NULL)
  185. {
  186. return E_POINTER;
  187. }
  188. #define GET_PARAM_DWORD(x,y) \
  189. if (SUCCEEDED(hr)) { \
  190. hr = GetParam(x, &var); \
  191. if (SUCCEEDED(hr)) pParm->y = (DWORD)var; \
  192. }
  193. GET_PARAM_DWORD(GFP_Rate, dwRateHz);
  194. GET_PARAM_DWORD(GFP_Shape, dwWaveShape);
  195. return hr;
  196. }
  197. //////////////////////////////////////////////////////////////////////////////
  198. //
  199. // CDirectSoundGargleDMO::SetParam
  200. //
  201. HRESULT CDirectSoundGargleDMO::SetParamInternal(DWORD dwParamIndex, MP_DATA value, bool fSkipPasssingToParamManager)
  202. {
  203. switch (dwParamIndex)
  204. {
  205. case GFP_Rate:
  206. CHECK_PARAM(DSFXGARGLE_RATEHZ_MIN,DSFXGARGLE_RATEHZ_MAX);
  207. m_ulGargleFreqHz = (unsigned)value;
  208. if (m_ulGargleFreqHz < 1) m_ulGargleFreqHz = 1;
  209. if (m_ulGargleFreqHz > 1000) m_ulGargleFreqHz = 1000;
  210. Init(); // FIXME - temp hack (sets m_bInitialized flag)
  211. break;
  212. case GFP_Shape:
  213. CHECK_PARAM(DSFXGARGLE_WAVE_TRIANGLE,DSFXGARGLE_WAVE_SQUARE);
  214. m_ulShape = (unsigned)value;
  215. break;
  216. }
  217. // Let base class set this so it can handle all the rest of the param calls.
  218. // Skip the base class if fSkipPasssingToParamManager. This indicates that we're calling the function
  219. // internally using valuds that came from the base class -- thus there's no need to tell it values it
  220. // already knows.
  221. return fSkipPasssingToParamManager ? S_OK : CParamsManager::SetParam(dwParamIndex, value);
  222. }
  223. //////////////////////////////////////////////////////////////////////////////
  224. //
  225. // CDirectSoundGargleDMO::ProcessInPlace
  226. //
  227. HRESULT CDirectSoundGargleDMO::ProcessInPlace(ULONG ulQuanta, LPBYTE pcbData, REFERENCE_TIME rtStart, DWORD dwFlags)
  228. {
  229. // Update parameter values from any curves that may be in effect.
  230. this->UpdateActiveParams(rtStart, *this);
  231. return FBRProcess(ulQuanta, pcbData, pcbData);
  232. }