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.

562 lines
15 KiB

  1. #include <windows.h>
  2. #include "distortp.h"
  3. #include "debug.h"
  4. #include "clone.h"
  5. STD_CREATE(Distortion)
  6. //////////////////////////////////////////////////////////////////////////////
  7. //
  8. // CDirectSoundDistortDMO::NDQueryInterface
  9. //
  10. // Subclass can override if it wants to implement more interfaces.
  11. //
  12. STDMETHODIMP CDirectSoundDistortionDMO::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_IDirectSoundFXDistortion)
  24. {
  25. return GetInterface((IDirectSoundFXDistortion*)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. // CDirectSoundDistortionDMO::CDirectSoundDistortionDMO
  45. //
  46. CDirectSoundDistortionDMO::CDirectSoundDistortionDMO( IUnknown *pUnk, HRESULT *phr )
  47. : CComBase( pUnk, phr ),
  48. m_fDirty(false)
  49. // { EAX: put init data here if any (otherwise use Discontinuity).
  50. // } EAX
  51. {
  52. m_EaxSamplesPerSec = 44010;
  53. }
  54. //////////////////////////////////////////////////////////////////////////////
  55. //
  56. // CDirectSoundDistortionDMO::Init()
  57. //
  58. HRESULT CDirectSoundDistortionDMO::Init()
  59. {
  60. DSFXDistortion distort;
  61. // Force recalc of all internal parameters
  62. //
  63. GetAllParameters(&distort);
  64. SetAllParameters(&distort);
  65. return Discontinuity();
  66. }
  67. 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;
  68. static ParamInfo g_params[] =
  69. {
  70. // index type caps min, max, neutral, unit text, label, pwchText
  71. DFP_Gain, MPT_FLOAT, g_capsAll, DSFXDISTORTION_GAIN_MIN, DSFXDISTORTION_GAIN_MAX, -18, L"", L"Gain", L"",
  72. DFP_Edge, MPT_FLOAT, g_capsAll, DSFXDISTORTION_EDGE_MIN, DSFXDISTORTION_EDGE_MAX, 15, L"", L"Edge", L"",
  73. DFP_LpCutoff, MPT_FLOAT, g_capsAll, DSFXDISTORTION_PRELOWPASSCUTOFF_MIN, DSFXDISTORTION_PRELOWPASSCUTOFF_MAX, 8000, L"", L"PreLowpassCutoff", L"",
  74. DFP_EqCenter, MPT_FLOAT, g_capsAll, DSFXDISTORTION_POSTEQCENTERFREQUENCY_MIN, DSFXDISTORTION_POSTEQCENTERFREQUENCY_MAX, 2400, L"", L"PostEQCenterFrequency", L"",
  75. DFP_EqWidth, MPT_FLOAT, g_capsAll, DSFXDISTORTION_POSTEQBANDWIDTH_MIN, DSFXDISTORTION_POSTEQBANDWIDTH_MAX, 2400, L"", L"PostEQBandwidth", L"",
  76. };
  77. HRESULT CDirectSoundDistortionDMO::InitOnCreation()
  78. {
  79. HRESULT hr = InitParams(1, &GUID_TIME_REFERENCE, 0, 0, sizeof(g_params)/sizeof(*g_params), g_params);
  80. return hr;
  81. }
  82. //////////////////////////////////////////////////////////////////////////////
  83. //
  84. // CDirectSoundDistortionDMO::~CDirectSoundDistortionDMO
  85. //
  86. CDirectSoundDistortionDMO::~CDirectSoundDistortionDMO()
  87. {
  88. }
  89. //////////////////////////////////////////////////////////////////////////////
  90. //
  91. // CDirectSoundDistortionDMO::Clone
  92. //
  93. STDMETHODIMP CDirectSoundDistortionDMO::Clone(IMediaObjectInPlace **pp)
  94. {
  95. return StandardDMOClone<CDirectSoundDistortionDMO, DSFXDistortion>(this, pp);
  96. }
  97. //
  98. // Bump - bump the delay pointers.
  99. //
  100. void CDirectSoundDistortionDMO::Bump(void)
  101. {
  102. // EAX {
  103. // }
  104. }
  105. HRESULT CDirectSoundDistortionDMO::Discontinuity()
  106. {
  107. // { EAX
  108. m_delayL1 = m_delayL2 = m_delayR1 = m_delayR2 = 0;
  109. m_ls0 = m_rs0 = 0.0;
  110. // } EAX
  111. return S_OK;
  112. }
  113. //////////////////////////////////////////////////////////////////////////////
  114. __forceinline void CDirectSoundDistortionDMO::DoOneSampleMono(int *l)
  115. {
  116. float inPortL = (float)*l;
  117. float outPortL, tempvar;
  118. // One-pole lowpass filter
  119. outPortL = inPortL * m_EaxLpff;
  120. m_ls0 = outPortL + m_ls0 * m_EaxLpfb;
  121. ////////////////////////////////////////
  122. ////////////////////////////////////////
  123. // Non-linear gain
  124. #define LOG(x,y) mylog(x,y)
  125. outPortL = (float)LOG(m_ls0 * 0x8000, m_EaxExp_range);
  126. outPortL /= 0x8000;
  127. ////////////////////////////////////////
  128. ////////////////////////////////////////
  129. // Bandpass
  130. outPortL = outPortL * m_EaxInScale;
  131. tempvar = outPortL - m_delayL1 * m_EaxK2;
  132. tempvar = tempvar - m_delayL2 * m_EaxK1;
  133. m_delayL1 = m_delayL2 + tempvar * m_EaxK1;
  134. m_delayL2 = tempvar;
  135. outPortL = tempvar;
  136. ////////////////////////////////////////
  137. #ifdef GOOD_CODE_GEN
  138. *l = Saturate(outPortL);
  139. #else
  140. int i;
  141. #ifdef i386
  142. _asm {
  143. fld outPortL
  144. fistp i
  145. }
  146. #else
  147. i = (int)outPortL;
  148. #endif
  149. if (i > 32767)
  150. i = 32767;
  151. else if ( i < -32768)
  152. i = -32768;
  153. *l = i;
  154. #endif
  155. // Bump();
  156. }
  157. //////////////////////////////////////////////////////////////////////////////
  158. __forceinline void CDirectSoundDistortionDMO::DoOneSample(int *l, int *r)
  159. {
  160. float inPortL = (float)*l;
  161. float inPortR = (float)*r;
  162. float outPortL, outPortR, tempvar;
  163. // One-pole lowpass filter
  164. outPortL = inPortL * m_EaxLpff;
  165. outPortR = inPortR * m_EaxLpff;
  166. m_ls0 = outPortL + m_ls0 * m_EaxLpfb;
  167. m_rs0 = outPortR + m_rs0 * m_EaxLpfb;
  168. ////////////////////////////////////////
  169. ////////////////////////////////////////
  170. // Non-linear gain
  171. #define LOG(x,y) mylog(x,y)
  172. outPortL = (float)LOG(m_ls0 * 0x8000, m_EaxExp_range);
  173. outPortR = (float)LOG(m_rs0 * 0x8000, m_EaxExp_range);
  174. outPortL /= 0x8000;
  175. outPortR /= 0x8000;
  176. ////////////////////////////////////////
  177. ////////////////////////////////////////
  178. // Bandpass
  179. outPortL = outPortL * m_EaxInScale;
  180. tempvar = outPortL - m_delayL1 * m_EaxK2;
  181. tempvar = tempvar - m_delayL2 * m_EaxK1;
  182. m_delayL1 = m_delayL2 + tempvar * m_EaxK1;
  183. m_delayL2 = tempvar;
  184. outPortL = tempvar;
  185. outPortR = outPortR * m_EaxInScale;
  186. tempvar = outPortR - m_delayR1 * m_EaxK2;
  187. tempvar = tempvar - m_delayR2 * m_EaxK1;
  188. m_delayR1 = m_delayR2 + tempvar * m_EaxK1;
  189. m_delayR2 = tempvar;
  190. outPortR = tempvar;
  191. ////////////////////////////////////////
  192. *l = Saturate(outPortL);
  193. *r = Saturate(outPortR);
  194. // Bump();
  195. }
  196. //////////////////////////////////////////////////////////////////////////////
  197. //
  198. // CDirectSoundDistortionDMO::FBRProcess
  199. //
  200. HRESULT CDirectSoundDistortionDMO::FBRProcess(DWORD cSamples, BYTE *pIn, BYTE *pOut)
  201. {
  202. // { EAX
  203. #define cb cSamples
  204. #define pin pIn
  205. #define pout pOut
  206. if (m_cChannels == 1) {
  207. if (m_b8bit) {
  208. for (;cb > 0; --cb) {
  209. int i, j;
  210. i = *(pin+0)-128;
  211. i *=256;
  212. // j = i;
  213. DoOneSampleMono(&i);
  214. // i += j;
  215. // i /= 2;
  216. i /= 256;
  217. *(pout+0) = (unsigned char)(i + 128);
  218. pin += sizeof(unsigned char);
  219. pout += sizeof(unsigned char);
  220. }
  221. }
  222. else if (!m_b8bit) {
  223. for (;cb > 0; --cb) { // for (;cb > 0; cb -= sizeof(short)) {
  224. short int *psi = (short int *)pin;
  225. short int *pso = (short int *)pout;
  226. int i, j;
  227. i = *psi;
  228. // j = i;
  229. DoOneSampleMono(&i);
  230. // i += j;
  231. // i /= 2;
  232. *pso = (short)i;
  233. pin += sizeof(short);
  234. pout += sizeof(short);
  235. }
  236. }
  237. }
  238. else if (m_cChannels == 2) {
  239. if (m_b8bit) {
  240. for (;cb > 0; --cb) { // for (;cb > 0; cb -= 2 * sizeof(unsigned char)) {
  241. int i, j;
  242. i = *(pin+0)-128;
  243. j = *(pin+1)-128;
  244. i *=256; j *=256;
  245. DoOneSample(&i, &j);
  246. i /= 256; j /= 256;
  247. *(pout+0) = (unsigned char)(i + 128);
  248. *(pout+1) = (unsigned char)(j + 128);
  249. pin += 2 * sizeof(unsigned char);
  250. pout += 2 * sizeof(unsigned char);
  251. }
  252. }
  253. else if (!m_b8bit) {
  254. for (;cb > 0; --cb) { // for (;cb > 0; cb -= 2 * sizeof(short)) {
  255. short int *psi = (short int *)pin;
  256. short int *pso = (short int *)pout;
  257. int i, j;
  258. i = *(psi+0);
  259. j = *(psi+1);
  260. DoOneSample(&i, &j);
  261. *(pso+0) = (short)i;
  262. *(pso+1) = (short)j;
  263. pin += 2 * sizeof(short);
  264. pout += 2 * sizeof(short);
  265. }
  266. }
  267. }
  268. // } EAX
  269. return S_OK;
  270. }
  271. //////////////////////////////////////////////////////////////////////////////
  272. //
  273. // CDirectSoundDistortionDMO::ProcessInPlace
  274. //
  275. HRESULT CDirectSoundDistortionDMO::ProcessInPlace(ULONG ulQuanta, LPBYTE pcbData, REFERENCE_TIME rtStart, DWORD dwFlags)
  276. {
  277. // Update parameter values from any curves that may be in effect.
  278. this->UpdateActiveParams(rtStart, *this);
  279. return FBRProcess(ulQuanta, pcbData, pcbData);
  280. }
  281. //////////////////////////////////////////////////////////////////////////////
  282. //
  283. // CDirectSoundDistortionDMO::SetParam
  284. //
  285. // { EAX
  286. // }
  287. HRESULT CDirectSoundDistortionDMO::SetParamInternal(DWORD dwParamIndex, MP_DATA value, bool fSkipPasssingToParamManager)
  288. {
  289. HRESULT hr = S_OK;
  290. HRESULT hr2 = S_OK;
  291. //if (!m_EaxSamplesPerSec) return DMO_E_TYPE_NOT_ACCEPTED; // NO TYPE!
  292. switch (dwParamIndex)
  293. {
  294. // { EAX
  295. case DFP_Gain : {
  296. CHECK_PARAM(DSFXDISTORTION_GAIN_MIN, DSFXDISTORTION_GAIN_MAX);
  297. PUT_EAX_VALUE(Gain, value);
  298. m_EaxGain = (float)pow(10, m_EaxGain/20);
  299. INTERPOLATE(InScale, TOFRACTION(m_EaxScale*m_EaxGain));
  300. break;
  301. case DFP_Edge:
  302. CHECK_PARAM(DSFXDISTORTION_EDGE_MIN, DSFXDISTORTION_EDGE_MAX);
  303. PUT_EAX_VALUE(Edge, value);
  304. m_EaxEdge = (m_EaxEdge/100 * 29) + 2;
  305. PUT_EAX_VALUE(Exp_range, (DWORD) m_EaxEdge);
  306. SetParamInternal(DFP_EqCenter, m_EaxCenter, true);
  307. SetParamInternal(DFP_EqWidth, m_EaxBandwidth, true);
  308. break;
  309. case DFP_LpCutoff:
  310. CHECK_PARAM(DSFXDISTORTION_PRELOWPASSCUTOFF_MIN, DSFXDISTORTION_PRELOWPASSCUTOFF_MAX);
  311. //Clamp at Fs/3;
  312. if (value > (MP_DATA)(m_EaxSamplesPerSec / 3))
  313. {
  314. value = (MP_DATA)(m_EaxSamplesPerSec / 3);
  315. hr = S_FALSE;
  316. }
  317. m_EaxLpfb = (float)sqrt((2*cos(2*PI*value/m_EaxSamplesPerSec)+3)/5);
  318. m_EaxLpff = (float)sqrt(1-m_EaxLpfb*m_EaxLpfb);
  319. break;
  320. case DFP_EqCenter: {
  321. CHECK_PARAM(DSFXDISTORTION_POSTEQCENTERFREQUENCY_MIN, DSFXDISTORTION_POSTEQCENTERFREQUENCY_MAX);
  322. //Clamp at Fs/3;
  323. if (value > (MP_DATA)(m_EaxSamplesPerSec / 3))
  324. {
  325. value = (MP_DATA)(m_EaxSamplesPerSec / 3);
  326. hr = S_FALSE;
  327. }
  328. PUT_EAX_VALUE(Center, value);
  329. double _k1, _k2, _omega;
  330. _omega = 2*PI*m_EaxBandwidth/m_EaxSamplesPerSec;
  331. _k1 = -cos(2*PI*value/m_EaxSamplesPerSec);
  332. _k2 = (1 - tan(_omega/2)) / (1 + tan(_omega/2));
  333. m_EaxScale = (float)(sqrt(1 - _k1*_k1) * sqrt(1 - _k2*_k2));
  334. m_EaxScale = (float)(m_EaxScale * LogNorm[(int)m_EaxEdge]);
  335. INTERPOLATE(K1, TOFRACTION(_k1));
  336. INTERPOLATE(InScale, TOFRACTION(m_EaxScale*m_EaxGain));
  337. break;
  338. }
  339. case DFP_EqWidth: {
  340. CHECK_PARAM(DSFXDISTORTION_POSTEQBANDWIDTH_MIN, DSFXDISTORTION_POSTEQBANDWIDTH_MAX);
  341. //Clamp at Fs/3;
  342. if (value > (MP_DATA)(m_EaxSamplesPerSec / 3))
  343. {
  344. value = (MP_DATA)(m_EaxSamplesPerSec / 3);
  345. hr = S_FALSE;
  346. }
  347. PUT_EAX_VALUE(Bandwidth, value);
  348. double _k1, _k2, _omega;
  349. _omega = 2*PI*value/m_EaxSamplesPerSec;
  350. _k1 = (float)(-cos(2*PI*m_EaxCenter/m_EaxSamplesPerSec));
  351. _k2 = (float)((1 - tan(_omega/2)) / (1 + tan(_omega/2)));
  352. m_EaxScale = (float)(sqrt(1 - _k1*_k1) * sqrt(1 - _k2*_k2));
  353. m_EaxScale = (float)(m_EaxScale * LogNorm[(int)m_EaxEdge]);
  354. INTERPOLATE(K2, TOFRACTION(_k2));
  355. INTERPOLATE(InScale, TOFRACTION(m_EaxScale*m_EaxGain));
  356. break;
  357. }
  358. }
  359. // } EAX
  360. default:
  361. return E_FAIL;
  362. }
  363. // Let base class set this so it can handle all the rest of the param calls.
  364. // Skip the base class if fSkipPasssingToParamManager. This indicates that we're calling the function
  365. // internally using valuds that came from the base class -- thus there's no need to tell it values it
  366. // already knows.
  367. hr2 = fSkipPasssingToParamManager ? S_OK : CParamsManager::SetParam(dwParamIndex, value);
  368. //Preserve the S_FALSE if there is one
  369. if (FAILED(hr2))
  370. hr = hr2;
  371. return hr;
  372. }
  373. //////////////////////////////////////////////////////////////////////////////
  374. //
  375. // CDirectSoundDistortionDMO::SetAllParameters
  376. //
  377. STDMETHODIMP CDirectSoundDistortionDMO::SetAllParameters(LPCDSFXDistortion pDistort)
  378. {
  379. HRESULT hr = S_OK;
  380. HRESULT hr2[5];
  381. ZeroMemory(hr2,sizeof(hr2));
  382. // Check that the pointer is not NULL
  383. if (pDistort == NULL)
  384. {
  385. Trace(1,"ERROR: pDistort is NULL\n");
  386. hr = E_POINTER;
  387. }
  388. // Set the parameters
  389. if (SUCCEEDED(hr)) hr = hr2[0] = SetParam(DFP_Gain, pDistort->fGain);
  390. if (SUCCEEDED(hr)) hr = hr2[1] = SetParam(DFP_Edge, pDistort->fEdge);
  391. if (SUCCEEDED(hr)) hr = hr2[2] = SetParam(DFP_LpCutoff, pDistort->fPreLowpassCutoff);
  392. if (SUCCEEDED(hr)) hr = hr2[3] = SetParam(DFP_EqCenter, pDistort->fPostEQCenterFrequency);
  393. if (SUCCEEDED(hr)) hr = hr2[4] = SetParam(DFP_EqWidth, pDistort->fPostEQBandwidth);
  394. m_fDirty = true;
  395. // if we have any alternate success codes, grab the first one and return it.
  396. if(SUCCEEDED(hr))
  397. {
  398. for (int i = 0;i < 5; i++)
  399. {
  400. if (hr2[i] != S_OK)
  401. {
  402. hr = hr2[i];
  403. break;
  404. }
  405. }
  406. }
  407. return hr;
  408. }
  409. //////////////////////////////////////////////////////////////////////////////
  410. //
  411. // CDirectSoundDistortionDMO::GetAllParameters
  412. //
  413. STDMETHODIMP CDirectSoundDistortionDMO::GetAllParameters(LPDSFXDistortion pDistort)
  414. {
  415. HRESULT hr = S_OK;
  416. MP_DATA mpd;
  417. if (pDistort == NULL)
  418. {
  419. return E_POINTER;
  420. }
  421. #define GET_PARAM(x,y) \
  422. if (SUCCEEDED(hr)) { \
  423. hr = GetParam(x, &mpd); \
  424. if (SUCCEEDED(hr)) pDistort->y = mpd; \
  425. }
  426. GET_PARAM(DFP_Edge, fEdge);
  427. GET_PARAM(DFP_Gain, fGain);
  428. GET_PARAM(DFP_LpCutoff, fPreLowpassCutoff);
  429. GET_PARAM(DFP_EqCenter, fPostEQCenterFrequency);
  430. GET_PARAM(DFP_EqWidth, fPostEQBandwidth);
  431. return hr;
  432. }
  433. // GetClassID
  434. //
  435. // Part of the persistent file support. We must supply our class id
  436. // which can be saved in a graph file and used on loading a graph with
  437. // this fx in it to instantiate this filter via CoCreateInstance.
  438. //
  439. HRESULT CDirectSoundDistortionDMO::GetClassID(CLSID *pClsid)
  440. {
  441. if (pClsid==NULL) {
  442. return E_POINTER;
  443. }
  444. *pClsid = GUID_DSFX_STANDARD_DISTORTION;
  445. return NOERROR;
  446. } // GetClassID