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.

277 lines
5.4 KiB

  1. #include "precomp.h"
  2. #include "mixer.h"
  3. #include "agc.h"
  4. // this should be moved to the mixer class - but right
  5. // now we already have two instances of that class (one in NAC, the other in CONF)
  6. static BOOL GetVolume(CMixerDevice *pMixer, DWORD *pdwVol)
  7. {
  8. DWORD dwSub=0, dwMain=0;
  9. BOOL fSubAvail, fMainAvail;
  10. if (pMixer == NULL)
  11. {
  12. return FALSE;
  13. }
  14. fSubAvail = pMixer->GetSubVolume(&dwSub);
  15. fMainAvail = pMixer->GetMainVolume(&dwMain);
  16. if ((!fSubAvail) && (!fMainAvail))
  17. {
  18. *pdwVol = 0;
  19. return FALSE;
  20. }
  21. if ((fSubAvail) && (fMainAvail))
  22. {
  23. *pdwVol = ((dwSub + dwMain)/2);
  24. }
  25. else if (fSubAvail)
  26. {
  27. *pdwVol = dwSub;
  28. }
  29. else
  30. {
  31. *pdwVol = dwMain;
  32. }
  33. return TRUE;
  34. }
  35. // check to see if volume has changed since the last update of the mixer
  36. // if so, we update m_dsLastVolumeSetting and return TRUE
  37. BOOL AGC::HasVolumeChanged()
  38. {
  39. DWORD dwVol;
  40. if (m_pMixer)
  41. {
  42. if (GetVolume(m_pMixer, &dwVol))
  43. {
  44. if (dwVol != m_dwLastVolumeSetting)
  45. {
  46. m_dwLastVolumeSetting = dwVol;
  47. return TRUE;
  48. }
  49. }
  50. }
  51. return FALSE;
  52. }
  53. // raise the volume my the increment amount
  54. inline BOOL AGC::RaiseVolume()
  55. {
  56. DWORD dwVol;
  57. if (m_pMixer)
  58. {
  59. if (GetVolume(m_pMixer, &dwVol))
  60. {
  61. if (dwVol < (AGC_MAXVOL-AGC_INCREMENT))
  62. {
  63. dwVol += AGC_INCREMENT;
  64. }
  65. else
  66. {
  67. dwVol = AGC_MAXVOL;
  68. }
  69. m_pMixer->SetVolume(dwVol);
  70. GetVolume(m_pMixer, &m_dwLastVolumeSetting);
  71. return TRUE;
  72. }
  73. else
  74. {
  75. return FALSE;
  76. }
  77. }
  78. return FALSE;
  79. }
  80. // lower the volume by the increment amount
  81. inline BOOL AGC::LowerVolume()
  82. {
  83. DWORD dwRet;
  84. if (m_pMixer)
  85. {
  86. if (GetVolume(m_pMixer, &dwRet))
  87. {
  88. if (dwRet > (AGC_INCREMENT+AGC_INCREMENT/2))
  89. m_dwLastVolumeSetting = dwRet - AGC_INCREMENT;
  90. else
  91. m_dwLastVolumeSetting = AGC_INCREMENT / 2;
  92. m_pMixer->SetVolume(m_dwLastVolumeSetting);
  93. GetVolume(m_pMixer, &m_dwLastVolumeSetting);
  94. return TRUE;
  95. }
  96. else
  97. {
  98. return FALSE;
  99. }
  100. }
  101. return FALSE;
  102. }
  103. AGC::AGC(CMixerDevice *pMixer) :
  104. m_cPeaks(0), m_wCurrentPeak(0),
  105. m_dwCollectionTime(0),
  106. m_pMixer(pMixer),
  107. m_wThreshStrength(AGC_DEFAULT_THRESH),
  108. m_dwLastVolumeSetting(0),
  109. m_nLastUpdateResult(AGC_NOUPDATE)
  110. {;}
  111. // resets all stats inside the AGC control except the mixer object
  112. void AGC::Reset()
  113. {
  114. m_cPeaks = 0;
  115. m_wCurrentPeak = 0;
  116. m_dwCollectionTime = 0;
  117. m_wThreshStrength = AGC_DEFAULT_THRESH;
  118. m_dwLastVolumeSetting = 0;
  119. m_nLastUpdateResult = AGC_NOUPDATE;
  120. }
  121. // initialize the AGC control with an instance of a mixer object
  122. // (you can also set the mixer in the constructor)
  123. void AGC::SetMixer(CMixerDevice *pMixer)
  124. {
  125. m_pMixer = pMixer;
  126. if (pMixer)
  127. {
  128. GetVolume(pMixer, &m_dwLastVolumeSetting);
  129. pMixer->SetVolume(m_dwLastVolumeSetting);
  130. }
  131. }
  132. // call this method for all recorded packets that
  133. // are begin sent. mixer will get raised/lowered as
  134. // appropriate. wPeakStrength can be any WORD that
  135. // represents a volume amount, but is designed to be
  136. // the highest sample value in a packet.
  137. int AGC::Update(WORD wPeakStrength, DWORD dwLengthMS)
  138. {
  139. int nIndex;
  140. DWORD dwTotal=0, dwMin=AGC_PEAKVOL, dwMax=0;
  141. DWORD dwAvg=0;
  142. BOOL nMaxPeaks=0;
  143. ASSERT (PEAKARRAYSIZE >= 2);
  144. if (wPeakStrength > m_wCurrentPeak)
  145. {
  146. m_wCurrentPeak = wPeakStrength;
  147. }
  148. m_dwCollectionTime += dwLengthMS;
  149. // have we exceeded one second worth of collections
  150. if (m_dwCollectionTime > 1000)
  151. {
  152. m_aPeaks[m_cPeaks++] = m_wCurrentPeak;
  153. m_dwCollectionTime = 0;
  154. m_wCurrentPeak = 0;
  155. }
  156. if (m_cPeaks >= 2)
  157. {
  158. // compute the average volume and number of clips that occurred
  159. for (nIndex = 0; nIndex < m_cPeaks; nIndex++)
  160. {
  161. dwTotal += m_aPeaks[nIndex];
  162. if (m_aPeaks[nIndex] < dwMin)
  163. {
  164. dwMin = m_aPeaks[nIndex];
  165. }
  166. else if (m_aPeaks[nIndex] > dwMax)
  167. {
  168. dwMax = m_aPeaks[nIndex];
  169. }
  170. if (m_aPeaks[nIndex] >= AGC_PEAKVOL)
  171. {
  172. nMaxPeaks++;
  173. }
  174. }
  175. dwAvg = (dwTotal-dwMin) / (PEAKARRAYSIZE-1);
  176. // check for clipping every 2 seconds
  177. if (((nMaxPeaks >= 1) && (dwAvg > AGC_HIGHVOL)) || (nMaxPeaks >=2))
  178. {
  179. // if the volume changed during (user manually adjusted sliders)
  180. // then allow those settings to stay in effect for this update
  181. if (HasVolumeChanged())
  182. {
  183. m_nLastUpdateResult = AGC_NOUPDATE;
  184. }
  185. else
  186. {
  187. m_cPeaks = 0;
  188. LowerVolume();
  189. m_nLastUpdateResult = AGC_UPDATE_LOWERVOL;
  190. }
  191. return m_nLastUpdateResult;
  192. }
  193. if (m_cPeaks >= PEAKARRAYSIZE)
  194. {
  195. m_cPeaks = 0;
  196. // if the volume changed during (user manually adjusted sliders)
  197. // then allow those settings to stay in effect for this update
  198. if (HasVolumeChanged())
  199. {
  200. m_nLastUpdateResult = AGC_NOUPDATE;
  201. }
  202. // should we actually raise the volume ?
  203. // if we just lowered the volume, don't raise it again
  204. // prevents the system from appearing "jerky"
  205. // if we just raised the volume, then don't raise immediately
  206. // again... let silence detection catch up.
  207. else if ((dwAvg < m_wThreshStrength) && (m_nLastUpdateResult == AGC_NOUPDATE))
  208. {
  209. RaiseVolume();
  210. m_nLastUpdateResult = AGC_UPDATE_RAISEVOL;
  211. }
  212. else
  213. {
  214. m_nLastUpdateResult = AGC_NOUPDATE;
  215. }
  216. return m_nLastUpdateResult;
  217. }
  218. return AGC_NOUPDATE;
  219. }
  220. // return NOUPDATE, but don't set m_nLastUpdateResult since
  221. // there was no decision made.
  222. return AGC_NOUPDATE;
  223. }