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.

682 lines
18 KiB

  1. #include <windows.h>
  2. #include "compressp.h"
  3. #include "clone.h"
  4. STD_CREATE(Compressor)
  5. //////////////////////////////////////////////////////////////////////////////
  6. //
  7. // CDirectSoundCompressorDMO::QueryInterface
  8. //
  9. // Subclass can override if it wants to implement more interfaces.
  10. //
  11. STDMETHODIMP CDirectSoundCompressorDMO::NDQueryInterface(THIS_ REFIID riid, LPVOID *ppv)
  12. {
  13. IMP_DSDMO_QI(riid,ppv);
  14. if (riid == IID_IPersist)
  15. {
  16. return GetInterface((IPersist*)this, ppv);
  17. }
  18. else if (riid == IID_IMediaObject)
  19. {
  20. return GetInterface((IMediaObject*)this, ppv);
  21. }
  22. else if (riid == IID_IDirectSoundFXCompressor)
  23. {
  24. return GetInterface((IDirectSoundFXCompressor*)this, ppv);
  25. }
  26. else if (riid == IID_ISpecifyPropertyPages)
  27. {
  28. return GetInterface((ISpecifyPropertyPages*)this, ppv);
  29. }
  30. else if (riid == IID_IMediaParams)
  31. {
  32. return GetInterface((IMediaParams*)this, ppv);
  33. }
  34. else if (riid == IID_IMediaParamInfo)
  35. {
  36. return GetInterface((IMediaParamInfo*)this, ppv);
  37. }
  38. else
  39. return CComBase::NDQueryInterface(riid, ppv);
  40. }
  41. //////////////////////////////////////////////////////////////////////////////
  42. //
  43. // CDirectSoundCompressorDMO::CDirectSoundCompressorDMO
  44. //
  45. CDirectSoundCompressorDMO::CDirectSoundCompressorDMO( IUnknown *pUnk, HRESULT *phr )
  46. : CComBase( pUnk, phr),
  47. m_fDirty(false)
  48. // { EAX: put init data here if any (otherwise use Discontinuity).
  49. // } EAX
  50. {
  51. m_EaxSamplesPerSec = 22050;
  52. m_LeftDelay. Init(0);
  53. m_RightDelay.Init(0);
  54. }
  55. //////////////////////////////////////////////////////////////////////////////
  56. //
  57. // CDirectSoundCompressorDMO::Init()
  58. //
  59. HRESULT CDirectSoundCompressorDMO::Init()
  60. {
  61. DSFXCompressor compress;
  62. HRESULT hr;
  63. // Force recalc of all internal parameters
  64. //
  65. hr = GetAllParameters(&compress);
  66. if (SUCCEEDED(hr)) hr = SetAllParameters(&compress);
  67. if (SUCCEEDED(hr)) hr = m_LeftDelay. Init(m_EaxSamplesPerSec);
  68. if (SUCCEEDED(hr) && m_cChannels == 2) {
  69. hr = m_RightDelay.Init(m_EaxSamplesPerSec);
  70. }
  71. if (SUCCEEDED(hr)) hr = Discontinuity();
  72. return hr;
  73. }
  74. 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;
  75. static ParamInfo g_params[] =
  76. {
  77. // index type caps min, max, neutral, unit text, label, pwchText
  78. CPFP_Gain, MPT_FLOAT, g_capsAll, DSFXCOMPRESSOR_GAIN_MIN, DSFXCOMPRESSOR_GAIN_MAX, 0, L"", L"Gain", L"",
  79. CPFP_Attack, MPT_FLOAT, g_capsAll, DSFXCOMPRESSOR_ATTACK_MIN, DSFXCOMPRESSOR_ATTACK_MAX, 10, L"", L"Attack", L"",
  80. CPFP_Release, MPT_FLOAT, g_capsAll, DSFXCOMPRESSOR_RELEASE_MIN, DSFXCOMPRESSOR_RELEASE_MAX, 200, L"", L"Release", L"",
  81. CPFP_Threshold, MPT_FLOAT, g_capsAll, DSFXCOMPRESSOR_THRESHOLD_MIN, DSFXCOMPRESSOR_THRESHOLD_MAX, -20, L"", L"Threshold", L"",
  82. CPFP_Ratio, MPT_FLOAT, g_capsAll, DSFXCOMPRESSOR_RATIO_MIN, DSFXCOMPRESSOR_RATIO_MAX, 3, L"", L"Ratio", L"",
  83. CPFP_Predelay, MPT_FLOAT, g_capsAll, DSFXCOMPRESSOR_PREDELAY_MIN, DSFXCOMPRESSOR_PREDELAY_MAX, 4, L"", L"Predelay", L"",
  84. };
  85. HRESULT CDirectSoundCompressorDMO::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. //////////////////////////////////////////////////////////////////////////////
  91. //
  92. // CDirectSoundCompressorDMO::~CDirectSoundCompressorDMO
  93. //
  94. CDirectSoundCompressorDMO::~CDirectSoundCompressorDMO()
  95. {
  96. m_LeftDelay. Init(-1);
  97. m_RightDelay.Init(-1);
  98. }
  99. //////////////////////////////////////////////////////////////////////////////
  100. //
  101. // CDirectSoundCompressorDMO::Clone
  102. //
  103. STDMETHODIMP CDirectSoundCompressorDMO::Clone(IMediaObjectInPlace **pp)
  104. {
  105. return StandardDMOClone<CDirectSoundCompressorDMO, DSFXCompressor>(this, pp);
  106. }
  107. //
  108. // Bump - bump the delay pointers.
  109. //
  110. void CDirectSoundCompressorDMO::Bump(void)
  111. {
  112. // EAX {
  113. m_LeftDelay.Bump();
  114. m_RightDelay.Bump();
  115. // }
  116. }
  117. HRESULT CDirectSoundCompressorDMO::Discontinuity()
  118. {
  119. // { EAX
  120. m_LeftDelay.ZeroBuffer();
  121. if (m_cChannels == 2) {
  122. m_RightDelay.ZeroBuffer();
  123. }
  124. m_Envelope = m_CompGain = 0;
  125. // } EAX
  126. return S_OK;
  127. }
  128. //////////////////////////////////////////////////////////////////////////////
  129. float myexp( float finput, unsigned long maxexponent)
  130. {
  131. unsigned long mantissa, exponent, exponentwidth ;
  132. long sign;
  133. long input;
  134. #ifdef DONTUSEi386
  135. _asm {
  136. fld finput
  137. fistp input
  138. }
  139. #else
  140. input = (int)(finput);
  141. #endif
  142. mantissa = input & 0x7FFFFFFFL ;
  143. sign = input & 0x80000000L ; /* Preserve sign */
  144. exponentwidth = 5;
  145. if ((0x80000000L & input) != 0) { /* Take absolute value of input */
  146. input = -input ;
  147. }
  148. /* Left-justify the mantissa and right-justify the exponent to separate */
  149. mantissa = input << exponentwidth ;
  150. exponent = input >> ( 31-exponentwidth ) ;
  151. /*
  152. * Insert the implied '1' at the mantissa MSB if not a zero exponent and
  153. * adjust it.
  154. */
  155. if( exponent != 0 ) {
  156. mantissa = mantissa | 0x80000000L ;
  157. exponent-- ;
  158. }
  159. mantissa = mantissa >> ( maxexponent-exponent ) ;
  160. if( sign != 0 )
  161. mantissa = ~mantissa ;
  162. float x = (float)mantissa;
  163. return(x);
  164. }
  165. __forceinline void CDirectSoundCompressorDMO::DoOneSampleMono(int *l)
  166. {
  167. int Pos0, PosX;
  168. float inPortL = (float)*l;
  169. float outPortL;
  170. float temp1, temp2;
  171. temp1 = inPortL;
  172. // left_delay[] = temp1;
  173. Pos0 = m_LeftDelay.Pos(0);
  174. m_LeftDelay[Pos0] = temp1;
  175. temp1 = (float)fabs(temp1);
  176. // Take the log
  177. #define LOG(x,y) mylog(x,y)
  178. temp1 = (float)fabs(LOG(temp1 * 0x8000,31));
  179. temp1 /= 0x80000000;
  180. // Sidechain level meter
  181. #ifndef MAX
  182. #define MAX(x,y) ((x > y) ? x : y)
  183. #endif
  184. m_EaxCompInputPeak = MAX(temp1, m_EaxCompInputPeak);
  185. // Envelope follower
  186. temp2 = temp1 >= m_Envelope ? m_EaxAttackCoef : -m_EaxAttackCoef;
  187. temp2 = temp2 <= 0 ? m_EaxReleaseCoef : temp2;
  188. // m_Envelope = temp2 : temp1 < m_Envelope;
  189. m_Envelope = Interpolate(temp1, m_Envelope, temp2);
  190. m_CompGain = MAX(m_Envelope, m_EaxCompThresh);
  191. // Log Difference between signal level and threshold level
  192. m_CompGain = m_EaxCompThresh - m_CompGain;
  193. #define cPOSFSCALE (float)0.9999999
  194. m_CompGain = cPOSFSCALE + m_CompGain * m_EaxCompressionRatio;
  195. // Compressor gain reduction meter
  196. #ifndef MIN
  197. #define MIN(x,y) ((x < y) ? x : y)
  198. #endif
  199. #define EXP(x,y) myexp(x,y)
  200. m_EaxCompGainMin= MIN(m_CompGain, m_EaxCompGainMin);
  201. m_CompGain = (float)EXP(m_CompGain * 0x80000000, 31);
  202. m_CompGain /= 0x80000000;
  203. // outPortL = left_point[@] * compGain;
  204. PosX = m_LeftDelay.LastPos((int)m_EaxLeftPoint);
  205. outPortL = m_LeftDelay[PosX] * m_CompGain;
  206. temp1 = outPortL * m_EaxGainBiasIP;
  207. outPortL = temp1 + outPortL * m_EaxGainBiasFP;
  208. *l = Saturate(outPortL);
  209. //Bump();
  210. m_LeftDelay.Bump();
  211. }
  212. __forceinline void CDirectSoundCompressorDMO::DoOneSample(int *l, int *r)
  213. {
  214. int Pos0, PosX;
  215. float inPortL = (float)*l;
  216. float inPortR = (float)*r;
  217. float outPortL, outPortR;
  218. float temp1, temp2;
  219. temp1 = inPortL;
  220. temp2 = inPortR;
  221. // left_delay[] = temp1;
  222. Pos0 = m_LeftDelay.Pos(0);
  223. m_LeftDelay[Pos0] = temp1;
  224. // right_delay[] = temp2;
  225. Pos0 = m_RightDelay.Pos(0);
  226. m_RightDelay[Pos0] = temp2;
  227. //Take the magnitude
  228. temp1 = (float)fabs(temp1);
  229. temp2 = (float)fabs(temp2);
  230. // Take the average
  231. // temp1 = 0.5 : temp1 < temp2;
  232. temp1 = (temp1 + temp2) / 2;
  233. // Take the log
  234. #define LOG(x,y) mylog(x,y)
  235. temp1 = (float)fabs(LOG(temp1 * 0x8000,31));
  236. temp1 /= 0x80000000;
  237. // Sidechain level meter
  238. #ifndef MAX
  239. #define MAX(x,y) ((x > y) ? x : y)
  240. #endif
  241. m_EaxCompInputPeak = MAX(temp1, m_EaxCompInputPeak);
  242. // Envelope follower
  243. temp2 = temp1 >= m_Envelope ? m_EaxAttackCoef : -m_EaxAttackCoef;
  244. temp2 = temp2 <= 0 ? m_EaxReleaseCoef : temp2;
  245. // m_Envelope = temp2 : temp1 < m_Envelope;
  246. m_Envelope = Interpolate(temp1, m_Envelope, temp2);
  247. m_CompGain = MAX(m_Envelope, m_EaxCompThresh);
  248. // Log Difference between signal level and threshold level
  249. m_CompGain = m_EaxCompThresh - m_CompGain;
  250. #define cPOSFSCALE (float)0.9999999
  251. m_CompGain = cPOSFSCALE + m_CompGain * m_EaxCompressionRatio;
  252. // Compressor gain reduction meter
  253. #ifndef MIN
  254. #define MIN(x,y) ((x < y) ? x : y)
  255. #endif
  256. #define EXP(x,y) myexp(x,y)
  257. m_EaxCompGainMin= MIN(m_CompGain, m_EaxCompGainMin);
  258. m_CompGain = (float)EXP(m_CompGain * 0x80000000, 31);
  259. m_CompGain /= 0x80000000;
  260. // outPortL = left_point[@] * compGain;
  261. PosX = m_LeftDelay.LastPos((int)m_EaxLeftPoint);
  262. outPortL = m_LeftDelay[PosX] * m_CompGain;
  263. // outPortR = right_point[@] * compGain;
  264. PosX = m_RightDelay.LastPos((int)m_EaxRightPoint);
  265. outPortR = m_RightDelay[PosX] * m_CompGain;
  266. temp1 = outPortL * m_EaxGainBiasIP;
  267. outPortL = temp1 + outPortL * m_EaxGainBiasFP;
  268. temp1 = outPortR * m_EaxGainBiasIP;
  269. outPortR = temp1 + outPortR * m_EaxGainBiasFP;
  270. *l = Saturate(outPortL);
  271. *r = Saturate(outPortR);
  272. Bump();
  273. }
  274. //////////////////////////////////////////////////////////////////////////////
  275. //
  276. // CDirectSoundCompressorDMO::FBRProcess
  277. //
  278. HRESULT CDirectSoundCompressorDMO::FBRProcess(DWORD cCompressors, BYTE *pIn, BYTE *pOut)
  279. {
  280. // { EAX
  281. #define cb cCompressors
  282. #define pin pIn
  283. #define pout pOut
  284. if (m_cChannels == 1) {
  285. if (m_b8bit) {
  286. for (;cb > 0; --cb) {
  287. int i, j;
  288. i = *(pin+0)-128;
  289. i *=256;
  290. // j = i;
  291. DoOneSampleMono(&i);
  292. // i += j;
  293. // i /= 2;
  294. i /= 256;
  295. *(pout+0) = (unsigned char)(i + 128);
  296. pin += sizeof(unsigned char);
  297. pout += sizeof(unsigned char);
  298. }
  299. }
  300. else if (!m_b8bit) {
  301. for (;cb > 0; --cb) { // for (;cb > 0; cb -= sizeof(short)) {
  302. short int *psi = (short int *)pin;
  303. short int *pso = (short int *)pout;
  304. int i, j;
  305. i = *psi;
  306. // j = i;
  307. DoOneSampleMono(&i);
  308. // i += j;
  309. // i /= 2;
  310. *pso = (short)i;
  311. pin += sizeof(short);
  312. pout += sizeof(short);
  313. }
  314. }
  315. }
  316. else if (m_cChannels == 2) {
  317. if (m_b8bit) {
  318. for (;cb > 0; --cb) { // for (;cb > 0; cb -= 2 * sizeof(unsigned char)) {
  319. int i, j;
  320. i = *(pin+0)-128;
  321. j = *(pin+1)-128;
  322. i *=256; j *=256;
  323. DoOneSample(&i, &j);
  324. i /= 256; j /= 256;
  325. *(pout+0) = (unsigned char)(i + 128);
  326. *(pout+1) = (unsigned char)(j + 128);
  327. pin += 2 * sizeof(unsigned char);
  328. pout += 2 * sizeof(unsigned char);
  329. }
  330. }
  331. else if (!m_b8bit) {
  332. for (;cb > 0; --cb) { // for (;cb > 0; cb -= 2 * sizeof(short)) {
  333. short int *psi = (short int *)pin;
  334. short int *pso = (short int *)pout;
  335. int i, j;
  336. i = *(psi+0);
  337. j = *(psi+1);
  338. DoOneSample(&i, &j);
  339. *(pso+0) = (short)i;
  340. *(pso+1) = (short)j;
  341. pin += 2 * sizeof(short);
  342. pout += 2 * sizeof(short);
  343. }
  344. }
  345. }
  346. // } EAX
  347. return S_OK;
  348. }
  349. //////////////////////////////////////////////////////////////////////////////
  350. //
  351. // CDirectSoundCompressorDMO::ProcessInPlace
  352. //
  353. HRESULT CDirectSoundCompressorDMO::ProcessInPlace(ULONG ulQuanta, LPBYTE pcbData, REFERENCE_TIME rtStart, DWORD dwFlags)
  354. {
  355. // Update parameter values from any curves that may be in effect.
  356. this->UpdateActiveParams(rtStart, *this);
  357. return FBRProcess(ulQuanta, pcbData, pcbData);
  358. }
  359. //////////////////////////////////////////////////////////////////////////////
  360. //
  361. // CDirectSoundCompressorDMO::SetParam
  362. //
  363. // { EAX
  364. // }
  365. HRESULT CDirectSoundCompressorDMO::SetParamInternal(DWORD dwParamIndex, MP_DATA value, bool fSkipPasssingToParamManager)
  366. {
  367. float fVal;
  368. if (!m_EaxSamplesPerSec) return DMO_E_TYPE_NOT_ACCEPTED; // NO TYPE!
  369. switch (dwParamIndex)
  370. {
  371. // { EAX
  372. case CPFP_Gain : {
  373. CHECK_PARAM(DSFXCOMPRESSOR_GAIN_MIN, DSFXCOMPRESSOR_GAIN_MAX);
  374. fVal = (float)pow(10, value/20); //Convert from dB to linear
  375. float _gainBiasIP, _gainBiasFP;
  376. double d;
  377. _gainBiasFP = (float)modf((double)fVal, &d);
  378. _gainBiasIP = (float)d;
  379. INTERPOLATE (GainBiasFP, TOFRACTION(_gainBiasFP));
  380. PUT_EAX_FVAL(GainBiasIP, TOFRACTION(_gainBiasIP));
  381. break;
  382. }
  383. case CPFP_Attack :
  384. CHECK_PARAM(DSFXCOMPRESSOR_ATTACK_MIN, DSFXCOMPRESSOR_ATTACK_MAX);
  385. m_EaxAttackCoef = (float)pow(10, -1/(value*m_EaxSamplesPerSec/1000));
  386. PUT_EAX_FVAL(AttackCoef, TOFRACTION(m_EaxAttackCoef));
  387. break;
  388. case CPFP_Release :
  389. CHECK_PARAM(DSFXCOMPRESSOR_RELEASE_MIN, DSFXCOMPRESSOR_RELEASE_MAX);
  390. m_EaxReleaseCoef = (float)pow(10, -1/(value*m_EaxSamplesPerSec/1000));
  391. break;
  392. case CPFP_Threshold : {
  393. CHECK_PARAM(DSFXCOMPRESSOR_THRESHOLD_MIN, DSFXCOMPRESSOR_THRESHOLD_MAX);
  394. fVal = (float)pow(10, value/20); //Convert from dB to linear
  395. float _compThresh;
  396. float a, b;
  397. a = (float)(pow(2, 26) * log(fVal * pow(2, 31))/log(2) + pow(2, 26));
  398. b = (float)(pow(2, 31) - 1.0);
  399. _compThresh = a < b ? a : b;
  400. _compThresh /= (float)0x80000000;
  401. PUT_EAX_FVAL(CompThresh, _compThresh);
  402. break;
  403. }
  404. case CPFP_Ratio :
  405. CHECK_PARAM(DSFXCOMPRESSOR_RATIO_MIN, DSFXCOMPRESSOR_RATIO_MAX);
  406. m_EaxCompressionRatio = (float)(1.0 - 1.0/value);
  407. PUT_EAX_FVAL(CompressionRatio, TOFRACTION(m_EaxCompressionRatio));
  408. break;
  409. case CPFP_Predelay : {
  410. CHECK_PARAM(DSFXCOMPRESSOR_PREDELAY_MIN, DSFXCOMPRESSOR_PREDELAY_MAX);
  411. float _length = (float)(value * m_EaxSamplesPerSec/1000.0);
  412. PUT_EAX_LVAL(LeftPoint, _length + 2);
  413. PUT_EAX_LVAL(RightPoint, _length + 2);
  414. break;
  415. }
  416. /*
  417. ** Removed from PropertySet, Processing code left behind so we can resurrect later
  418. **
  419. case CPFP_CompMeterReset : {
  420. CHECK_PARAM(DSFXCOMPRESSOR_COMPMETERRESET_MIN, DSFXCOMPRESSOR_COMPMETERRESET_MAX);
  421. if(!value)
  422. break; // return E_FAIL;
  423. float InputPeak = m_EaxCompInputPeak;
  424. float GainMin = m_EaxCompGainMin;
  425. PUT_EAX_FVAL(CompInputPeak, 0);
  426. PUT_EAX_FVAL(CompGainMin, 0.999999999);
  427. InputPeak = (float)(186.0 * (InputPeak - 0.999999999)/0.999999999);
  428. GainMin = - (float)(186.0 * (GainMin - 0.999999999)/0.999999999);
  429. CParamsManager::SetParam(CPFP_CompMeterReset , 0);
  430. if (!fSkipPasssingToParamManager)
  431. CParamsManager::SetParam(CPFP_CompInputMeter , InputPeak);
  432. if (!fSkipPasssingToParamManager)
  433. CParamsManager::SetParam(CPFP_CompGainMeter , GainMin);
  434. break;
  435. }
  436. */
  437. /* These values can't be set, only queried.
  438. */
  439. /*
  440. case CPFP_CompInputMeter :
  441. CHECK_PARAM(DSFXCOMPRESSOR_COMPINPUTMETER_MIN, DSFXCOMPRESSOR_COMPINPUTMETER_MAX);
  442. return E_FAIL;
  443. case CPFP_CompGainMeter :
  444. CHECK_PARAM(DSFXCOMPRESSOR_COMPGAINMETER_MIN, DSFXCOMPRESSOR_COMPGAINMETER_MAX);
  445. return E_FAIL;
  446. // } EAX
  447. */
  448. default:
  449. return E_FAIL;
  450. }
  451. // Let base class set this so it can handle all the rest of the param calls.
  452. // Skip the base class if fSkipPasssingToParamManager. This indicates that we're calling the function
  453. // internally using valuds that came from the base class -- thus there's no need to tell it values it
  454. // already knows.
  455. return fSkipPasssingToParamManager ? S_OK : CParamsManager::SetParam(dwParamIndex, value);
  456. }
  457. //////////////////////////////////////////////////////////////////////////////
  458. //
  459. // CDirectSoundCompressorDMO::SetAllParameters
  460. //
  461. STDMETHODIMP CDirectSoundCompressorDMO::SetAllParameters(LPCDSFXCompressor pComp)
  462. {
  463. HRESULT hr = S_OK;
  464. // Check that the pointer is not NULL
  465. if (pComp == NULL)
  466. {
  467. Trace(1,"ERROR: pComp is NULL\n");
  468. hr = E_POINTER;
  469. }
  470. // Set the parameters
  471. if (SUCCEEDED(hr)) hr = SetParam(CPFP_Gain, pComp->fGain);
  472. if (SUCCEEDED(hr)) hr = SetParam(CPFP_Attack, pComp->fAttack);
  473. if (SUCCEEDED(hr)) hr = SetParam(CPFP_Release, pComp->fRelease);
  474. if (SUCCEEDED(hr)) hr = SetParam(CPFP_Threshold, pComp->fThreshold);
  475. if (SUCCEEDED(hr)) hr = SetParam(CPFP_Ratio, pComp->fRatio);
  476. if (SUCCEEDED(hr)) hr = SetParam(CPFP_Predelay, pComp->fPredelay);
  477. /* These values can only be queried, not set. CPFP_CompMeterReset fills
  478. * the values.
  479. */
  480. // if (SUCCEEDED(hr)) hr = SetParam(CPFP_CompInputMeter, pComp->fCompInputMeter);
  481. // if (SUCCEEDED(hr)) hr = SetParam(CPFP_CompGainMeter, pComp->fCompGainMeter);
  482. m_fDirty = true;
  483. return hr;
  484. }
  485. //////////////////////////////////////////////////////////////////////////////
  486. //
  487. // CDirectSoundCompressorDMO::GetAllParameters
  488. //
  489. STDMETHODIMP CDirectSoundCompressorDMO::GetAllParameters(LPDSFXCompressor pCompressor)
  490. {
  491. HRESULT hr = S_OK;
  492. MP_DATA mpd;
  493. if (pCompressor == NULL) return E_POINTER;
  494. #define GET_PARAM(x,y) \
  495. if (SUCCEEDED(hr)) { \
  496. hr = GetParam(x, &mpd); \
  497. if (SUCCEEDED(hr)) pCompressor->y = mpd; \
  498. }
  499. GET_PARAM(CPFP_Attack, fAttack);
  500. GET_PARAM(CPFP_Release, fRelease);
  501. GET_PARAM(CPFP_Threshold, fThreshold);
  502. GET_PARAM(CPFP_Ratio, fRatio);
  503. GET_PARAM(CPFP_Gain, fGain);
  504. GET_PARAM(CPFP_Predelay, fPredelay);
  505. return hr;
  506. }
  507. // GetClassID
  508. //
  509. // Part of the persistent file support. We must supply our class id
  510. // which can be saved in a graph file and used on loading a graph with
  511. // this fx in it to instantiate this filter via CoCreateInstance.
  512. //
  513. HRESULT CDirectSoundCompressorDMO::GetClassID(CLSID *pClsid)
  514. {
  515. if (pClsid==NULL) {
  516. return E_POINTER;
  517. }
  518. *pClsid = GUID_DSFX_STANDARD_COMPRESSOR;
  519. return NOERROR;
  520. } // GetClassID