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.

435 lines
9.5 KiB

  1. #include "tones.h"
  2. //////////////////////////////////////////////////////////////////////////////
  3. //
  4. // Helper function used to read a wave file's data into an in-memory buffer.
  5. //
  6. HRESULT ReadWaveFile(char * szFileName, DWORD dwFileSize, BYTE * pbData)
  7. {
  8. const int WAVE_HEADER_SIZE = 44;
  9. FILE * fp;
  10. size_t result;
  11. //
  12. // Check arguments.
  13. //
  14. // Assumption: we are reading at least WAVE_HEADER_SIZE bytes from the file.
  15. // Note: this is data in addition to the header.
  16. //
  17. // _ASSERTE( ! IsBadWritePtr( pbData, dwFileSize ) );
  18. // _ASSERTE( ! IsBadStringPtr( szFileName, (UINT) -1 ) );
  19. if ( dwFileSize < WAVE_HEADER_SIZE )
  20. {
  21. return E_INVALIDARG;
  22. }
  23. //
  24. // Open the file for reading.
  25. //
  26. fp = fopen(szFileName, "rb");
  27. if ( fp == NULL )
  28. {
  29. return E_FAIL;
  30. }
  31. //
  32. // Skip the wave header.
  33. //
  34. result = fread(pbData, sizeof(BYTE), WAVE_HEADER_SIZE, fp);
  35. if ( result != WAVE_HEADER_SIZE )
  36. {
  37. fclose(fp);
  38. return E_FAIL;
  39. }
  40. //
  41. // Read the waveform from the file and close the file.
  42. //
  43. result = fread(pbData, sizeof(BYTE), dwFileSize, fp);
  44. fclose(fp);
  45. if ( result != dwFileSize )
  46. {
  47. return E_FAIL;
  48. }
  49. return S_OK;
  50. }
  51. //////////////////////////////////////////////////////////////////////////////
  52. //
  53. CTonePlayer::CTonePlayer()
  54. {
  55. m_hWaveOut = NULL;
  56. m_fInitialized = FALSE;
  57. m_fDialtonePlaying = FALSE;
  58. }
  59. //////////////////////////////////////////////////////////////////////////////
  60. //
  61. CTonePlayer::~CTonePlayer()
  62. {
  63. //
  64. // We should have closed the wave device by now.
  65. //
  66. if ( m_fInitialized == TRUE )
  67. {
  68. ASSERT( m_hWaveOut == NULL );
  69. }
  70. }
  71. //////////////////////////////////////////////////////////////////////////////
  72. //
  73. HRESULT CTonePlayer::Initialize(void)
  74. {
  75. int i;
  76. //
  77. // It's wasteful to initialize twice, but it won't break anything.
  78. //
  79. ASSERT( m_fInitialized == FALSE );
  80. //
  81. // Read all the files.
  82. //
  83. HRESULT hr = ReadWaveFile(
  84. "dialtone.wav",
  85. WAVE_FILE_SIZE,
  86. (BYTE * ) & m_abDialtoneWaveform
  87. );
  88. if ( FAILED(hr) )
  89. {
  90. return hr;
  91. }
  92. //
  93. // For each digit
  94. //
  95. for ( i = 0; i < NUM_DIGITS; i ++ )
  96. {
  97. //
  98. // Construct the filename for this digit.
  99. //
  100. char szFilename[20];
  101. if ( i < 10 )
  102. {
  103. sprintf(szFilename,"dtmf%d.wav", i);
  104. }
  105. else if ( i == 10 )
  106. {
  107. sprintf(szFilename,"dtmfstar.wav", i);
  108. }
  109. else if ( i == 11 )
  110. {
  111. sprintf(szFilename,"dtmfpound.wav", i);
  112. }
  113. else
  114. {
  115. ASSERT( FALSE );
  116. }
  117. //
  118. // Read the wave file for this digit.
  119. //
  120. HRESULT hr = ReadWaveFile(
  121. szFilename,
  122. WAVE_FILE_SIZE,
  123. (BYTE * ) ( & m_abDigitWaveforms ) + ( i * WAVE_FILE_SIZE )
  124. );
  125. if ( FAILED(hr) )
  126. {
  127. return hr;
  128. }
  129. }
  130. //
  131. // We can now go ahead with the other methods.
  132. //
  133. m_fInitialized = TRUE;
  134. return S_OK;
  135. }
  136. //////////////////////////////////////////////////////////////////////////////
  137. //
  138. HRESULT CTonePlayer::StartDialtone(
  139. void
  140. )
  141. {
  142. MMRESULT mmresult;
  143. if ( m_fInitialized == FALSE )
  144. {
  145. ASSERT( FALSE );
  146. return E_UNEXPECTED;
  147. }
  148. if ( m_hWaveOut == NULL )
  149. {
  150. ASSERT( FALSE );
  151. return E_UNEXPECTED;
  152. }
  153. //
  154. // Reset the wave device to flush out any pending buffers.
  155. //
  156. waveOutReset( m_hWaveOut );
  157. //
  158. // Construct a wave header structure that will indicate what to play
  159. // in waveOutWrite, and read in the data from the file. This can also
  160. // be done ahead of time.
  161. //
  162. ZeroMemory( & m_WaveHeader, sizeof( m_WaveHeader ) );
  163. m_WaveHeader.lpData = (LPSTR) & m_abDialtoneWaveform;
  164. m_WaveHeader.dwBufferLength = WAVE_FILE_SIZE;
  165. m_WaveHeader.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
  166. m_WaveHeader.dwLoops = (DWORD) -1;
  167. //
  168. // Submit the data to the wave device. The wave header indicated that
  169. // we want to loop. Need to prepare the header first, but it can
  170. // only be prepared after the device has been opened.
  171. //
  172. mmresult = waveOutPrepareHeader(m_hWaveOut,
  173. & m_WaveHeader,
  174. sizeof(WAVEHDR)
  175. );
  176. if ( mmresult != MMSYSERR_NOERROR )
  177. {
  178. return E_FAIL;
  179. }
  180. mmresult = waveOutWrite(m_hWaveOut,
  181. & m_WaveHeader,
  182. sizeof(WAVEHDR)
  183. );
  184. if ( mmresult != MMSYSERR_NOERROR )
  185. {
  186. return E_FAIL;
  187. }
  188. m_fDialtonePlaying = TRUE;
  189. return S_OK;
  190. }
  191. //////////////////////////////////////////////////////////////////////////////
  192. //
  193. // Reset the device to stop playing.
  194. //
  195. HRESULT CTonePlayer::StopDialtone( void )
  196. {
  197. if ( m_fInitialized == FALSE )
  198. {
  199. ASSERT( FALSE );
  200. return E_UNEXPECTED;
  201. }
  202. if ( m_hWaveOut == NULL )
  203. {
  204. ASSERT( FALSE );
  205. return E_UNEXPECTED;
  206. }
  207. waveOutReset( m_hWaveOut );
  208. m_fDialtonePlaying = FALSE;
  209. return S_OK;
  210. }
  211. //////////////////////////////////////////////////////////////////////////////
  212. //
  213. HRESULT CTonePlayer::GenerateDTMF(
  214. long lDigit
  215. )
  216. {
  217. MMRESULT mmresult;
  218. if ( lDigit < 0 )
  219. {
  220. ASSERT( FALSE );
  221. return E_UNEXPECTED;
  222. }
  223. if ( lDigit > NUM_DIGITS )
  224. {
  225. ASSERT( FALSE );
  226. return E_UNEXPECTED;
  227. }
  228. if ( m_fInitialized == FALSE )
  229. {
  230. ASSERT( FALSE );
  231. return E_UNEXPECTED;
  232. }
  233. if ( m_hWaveOut == NULL )
  234. {
  235. ASSERT( FALSE );
  236. return E_UNEXPECTED;
  237. }
  238. //
  239. // Reset the wave device to flush out any pending buffers.
  240. //
  241. waveOutReset( m_hWaveOut );
  242. m_fDialtonePlaying = FALSE;
  243. //
  244. // Construct a wave header structure that will indicate what to play
  245. // in waveOutWrite, and read in the data from the file. This can also
  246. // be done ahead of time.
  247. //
  248. ZeroMemory( & m_WaveHeader, sizeof( m_WaveHeader ) );
  249. m_WaveHeader.lpData = (LPSTR) & m_abDigitWaveforms + lDigit * WAVE_FILE_SIZE;
  250. m_WaveHeader.dwBufferLength = WAVE_FILE_SIZE;
  251. m_WaveHeader.dwFlags = 0;
  252. m_WaveHeader.dwLoops = (DWORD) 0;
  253. //
  254. // Submit the data to the wave device. The wave header indicated that
  255. // we want to loop. Need to prepare the header first, but it can
  256. // only be prepared after the device has been opened.
  257. //
  258. mmresult = waveOutPrepareHeader(m_hWaveOut,
  259. & m_WaveHeader,
  260. sizeof(WAVEHDR)
  261. );
  262. if ( mmresult != MMSYSERR_NOERROR )
  263. {
  264. return E_FAIL;
  265. }
  266. mmresult = waveOutWrite(m_hWaveOut,
  267. & m_WaveHeader,
  268. sizeof(WAVEHDR)
  269. );
  270. if ( mmresult != MMSYSERR_NOERROR )
  271. {
  272. return E_FAIL;
  273. }
  274. return S_OK;
  275. }
  276. //////////////////////////////////////////////////////////////////////////////
  277. //
  278. HRESULT CTonePlayer::OpenWaveDevice(
  279. long lWaveID
  280. )
  281. {
  282. MMRESULT mmresult;
  283. if ( m_fInitialized == FALSE )
  284. {
  285. ASSERT( FALSE );
  286. return E_UNEXPECTED;
  287. }
  288. //
  289. // We expect that the wave device will not be opened twice. This is
  290. // dependent on the calling code.
  291. //
  292. ASSERT( m_hWaveOut == NULL );
  293. //
  294. // Open the wave device. Here we specify a hard-coded audio format.
  295. //
  296. WAVEFORMATEX waveFormat;
  297. waveFormat.wFormatTag = WAVE_FORMAT_PCM; // linear PCM
  298. waveFormat.nChannels = 1; // mono
  299. waveFormat.nSamplesPerSec = 8000; // 8 KHz
  300. waveFormat.wBitsPerSample = 16; // 16-bit samples
  301. waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8;
  302. waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
  303. waveFormat.cbSize = 0; // no extra format info
  304. mmresult = waveOutOpen(& m_hWaveOut, // returned handle
  305. lWaveID, // which device to use
  306. &waveFormat, // wave format to use
  307. 0, // callback function pointer
  308. 0, // callback instance data
  309. WAVE_FORMAT_DIRECT // we don't want ACM
  310. );
  311. if ( mmresult != MMSYSERR_NOERROR )
  312. {
  313. return E_FAIL;
  314. }
  315. return S_OK;
  316. }
  317. //////////////////////////////////////////////////////////////////////////////
  318. //
  319. void CTonePlayer::CloseWaveDevice(void)
  320. {
  321. if ( m_fInitialized == FALSE )
  322. {
  323. ASSERT( FALSE );
  324. }
  325. ASSERT( m_hWaveOut != NULL );
  326. if ( m_hWaveOut != NULL )
  327. {
  328. waveOutClose( m_hWaveOut );
  329. m_hWaveOut = NULL;
  330. }
  331. }