Source code of Windows XP (NT5)
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.

379 lines
8.3 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1999 - 1999 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: vplayer.h
  6. * Content: Voice Player Entry
  7. *
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 03/26/00 rodtoll Created
  12. * 07/09/2000 rodtoll Added signature bytes
  13. ***************************************************************************/
  14. #include "dxvoicepch.h"
  15. CVoicePlayer::CVoicePlayer()
  16. {
  17. m_dwSignature = VSIG_VOICEPLAYER;
  18. Reset();
  19. }
  20. CVoicePlayer::~CVoicePlayer()
  21. {
  22. if( IsInitialized() )
  23. DeInitialize();
  24. m_dwSignature = VSIG_VOICEPLAYER_FREE;
  25. }
  26. void CVoicePlayer::Reset()
  27. {
  28. m_dwFlags = 0;
  29. m_dvidPlayer = 0;
  30. m_lRefCount = 0;
  31. m_lpInBoundAudioConverter = NULL;
  32. m_lpInputQueue = NULL;
  33. m_dwLastData = 0;
  34. m_dwHostOrderID = 0xFFFFFFFF;
  35. m_bLastPeak = 0;
  36. m_dwLastPlayback = 0;
  37. m_dwNumSilentFrames = 0;
  38. m_dwTransportFlags = 0;
  39. m_dwNumLostFrames = 0;
  40. m_dwNumSpeechFrames = 0;
  41. m_dwNumReceivedFrames = 0;
  42. m_pvPlayerContext = NULL;
  43. InitBilink( &m_blNotifyList, this );
  44. InitBilink( &m_blPlayList, this );
  45. m_dwNumTargets = 0;
  46. m_pdvidTargets = NULL;
  47. }
  48. #undef DPF_MODNAME
  49. #define DPF_MODNAME "CVoicePlayer::SetPlayerTargets"
  50. //
  51. // Assumes the array has been checked for validity
  52. //
  53. HRESULT CVoicePlayer::SetPlayerTargets( PDVID pdvidTargets, DWORD dwNumTargets )
  54. {
  55. Lock();
  56. delete [] m_pdvidTargets;
  57. if( dwNumTargets == 0 )
  58. {
  59. m_pdvidTargets = NULL;
  60. }
  61. else
  62. {
  63. m_pdvidTargets = new DVID[dwNumTargets];
  64. if( m_pdvidTargets == NULL )
  65. {
  66. m_pdvidTargets = NULL;
  67. m_dwNumTargets = 0;
  68. DPFX(DPFPREP, DVF_ERRORLEVEL, "Error allocating memory" );
  69. UnLock();
  70. return DVERR_OUTOFMEMORY;
  71. }
  72. memcpy( m_pdvidTargets, pdvidTargets, sizeof(DVID)*dwNumTargets );
  73. }
  74. m_dwNumTargets = dwNumTargets;
  75. UnLock();
  76. return DV_OK;
  77. }
  78. HRESULT CVoicePlayer::Initialize( const DVID dvidPlayer, const DWORD dwHostOrder, DWORD dwFlags, PVOID pvContext,
  79. CLockedFixedPool<CVoicePlayer> *pOwner )
  80. {
  81. if (!DNInitializeCriticalSection( &m_csLock ))
  82. {
  83. return DVERR_OUTOFMEMORY;
  84. }
  85. m_lRefCount = 1;
  86. m_pOwner = pOwner;
  87. m_dvidPlayer = dvidPlayer;
  88. m_dwHostOrderID = dwHostOrder;
  89. m_dwLastData = GetTickCount();
  90. m_dwLastPlayback = 0;
  91. m_dwTransportFlags = dwFlags;
  92. m_pvPlayerContext = pvContext;
  93. m_dwFlags |= VOICEPLAYER_FLAGS_INITIALIZED;
  94. return DV_OK;
  95. }
  96. void CVoicePlayer::GetStatistics( PVOICEPLAYER_STATISTICS pStats )
  97. {
  98. memset( pStats, 0x00, sizeof( VOICEPLAYER_STATISTICS ) );
  99. // Get queue statistics
  100. if( m_lpInputQueue != NULL )
  101. {
  102. Lock();
  103. m_lpInputQueue->GetStatistics( &pStats->queueStats );
  104. UnLock();
  105. }
  106. pStats->dwNumLostFrames = m_dwNumLostFrames;
  107. pStats->dwNumSilentFrames = m_dwNumSilentFrames;
  108. pStats->dwNumSpeechFrames = m_dwNumSpeechFrames;
  109. pStats->dwNumReceivedFrames = m_dwNumReceivedFrames;
  110. return;
  111. }
  112. HRESULT CVoicePlayer::CreateQueue( PQUEUE_PARAMS pQueueParams )
  113. {
  114. HRESULT hr;
  115. DNEnterCriticalSection( &CDirectVoiceEngine::s_csSTLLock );
  116. m_lpInputQueue = new CInputQueue2();
  117. if( m_lpInputQueue == NULL )
  118. {
  119. DPFX(DPFPREP, 0, "Error allocating memory" );
  120. return DVERR_OUTOFMEMORY;
  121. }
  122. hr = m_lpInputQueue->Initialize( pQueueParams );
  123. if( FAILED( hr ) )
  124. {
  125. DPFX(DPFPREP, 0, "Failed initializing queue hr=0x%x", hr );
  126. delete m_lpInputQueue;
  127. m_lpInputQueue = NULL;
  128. return hr;
  129. }
  130. DNLeaveCriticalSection( &CDirectVoiceEngine::s_csSTLLock );
  131. return hr;
  132. }
  133. HRESULT CVoicePlayer::CreateInBoundConverter( const GUID &guidCT, PWAVEFORMATEX pwfxTargetFormat )
  134. {
  135. HRESULT hr;
  136. hr = DVCDB_CreateConverter( guidCT, pwfxTargetFormat, &m_lpInBoundAudioConverter );
  137. if( FAILED( hr ) )
  138. {
  139. DPFX(DPFPREP, 0, "Error creating audio converter hr=0x%x" , hr );
  140. return hr;
  141. }
  142. if( pwfxTargetFormat->wBitsPerSample == 8)
  143. {
  144. m_dwFlags |= VOICEPLAYER_FLAGS_TARGETIS8BIT;
  145. }
  146. return hr;
  147. }
  148. HRESULT CVoicePlayer::DeInitialize()
  149. {
  150. FreeResources();
  151. m_pOwner->Release( this );
  152. return DV_OK;
  153. }
  154. HRESULT CVoicePlayer::HandleReceive( PDVPROTOCOLMSG_SPEECHHEADER pdvSpeechHeader, PBYTE pbData, DWORD dwSize )
  155. {
  156. CFrame tmpFrame;
  157. tmpFrame.SetSeqNum( pdvSpeechHeader->bSeqNum );
  158. tmpFrame.SetMsgNum( pdvSpeechHeader->bMsgNum );
  159. tmpFrame.SetIsSilence( FALSE );
  160. tmpFrame.SetFrameLength( dwSize );
  161. tmpFrame.UserOwn_SetData( pbData, dwSize );
  162. Lock();
  163. DPFX(DPFPREP, DVF_CLIENT_SEQNUM_DEBUG_LEVEL, "SEQ: Receive: Msg [%d] Seq [%d]", pdvSpeechHeader->bMsgNum, pdvSpeechHeader->bSeqNum );
  164. // STATSBLOCK: Begin
  165. //m_stats.m_dwPRESpeech++;
  166. // STATSBLOCK: End
  167. m_lpInputQueue->Enqueue( tmpFrame );
  168. m_dwLastData = GetTickCount();
  169. DPFX(DPFPREP, DVF_INFOLEVEL, "Received speech is buffered!" );
  170. m_dwNumReceivedFrames++;
  171. UnLock();
  172. return DV_OK;
  173. }
  174. CFrame *CVoicePlayer::Dequeue(BOOL *pfLost, BOOL *pfSilence)
  175. {
  176. CFrame *frTmpFrame;
  177. Lock();
  178. frTmpFrame = m_lpInputQueue->Dequeue();
  179. UnLock();
  180. if( !frTmpFrame->GetIsSilence() )
  181. {
  182. *pfSilence = FALSE;
  183. m_dwLastPlayback = GetTickCount();
  184. m_dwNumSpeechFrames++;
  185. }
  186. else
  187. {
  188. m_dwNumSilentFrames++;
  189. *pfSilence = TRUE;
  190. }
  191. if( frTmpFrame->GetIsLost() )
  192. {
  193. *pfLost = TRUE;
  194. m_dwNumLostFrames++;
  195. }
  196. else
  197. {
  198. *pfLost = FALSE;
  199. }
  200. return frTmpFrame;
  201. }
  202. HRESULT CVoicePlayer::DeCompressInBound( CFrame *frCurrentFrame, PVOID pvBuffer, PDWORD pdwBufferSize )
  203. {
  204. HRESULT hr;
  205. hr = m_lpInBoundAudioConverter->Convert( frCurrentFrame->GetDataPointer(), frCurrentFrame->GetFrameLength(), pvBuffer, pdwBufferSize, frCurrentFrame->GetIsSilence() );
  206. if( FAILED( hr ) )
  207. {
  208. DPFX(DPFPREP, 0, "Failed converting audio hr=0x%x", hr );
  209. return hr;
  210. }
  211. return hr;
  212. }
  213. HRESULT CVoicePlayer::GetNextFrameAndDecompress( PVOID pvBuffer, PDWORD pdwBufferSize, BOOL *pfLost, BOOL *pfSilence, DWORD *pdwSeqNum, DWORD *pdwMsgNum )
  214. {
  215. CFrame *frTmpFrame;
  216. BYTE bLastPeak;
  217. HRESULT hr;
  218. frTmpFrame = Dequeue(pfLost,pfSilence );
  219. *pdwSeqNum = frTmpFrame->GetSeqNum();
  220. *pdwMsgNum = frTmpFrame->GetMsgNum();
  221. hr = DeCompressInBound( frTmpFrame, pvBuffer, pdwBufferSize );
  222. frTmpFrame->Return();
  223. if( FAILED( hr ) )
  224. {
  225. DPFX(DPFPREP, 0, "Failed converting audio hr=0x%x", hr );
  226. return hr;
  227. }
  228. if( *pfSilence )
  229. {
  230. m_bLastPeak = 0;
  231. }
  232. else
  233. {
  234. m_bLastPeak = FindPeak( (PBYTE) pvBuffer, *pdwBufferSize, Is8BitUnCompressed() );
  235. }
  236. return hr;
  237. }
  238. void CVoicePlayer::FreeResources()
  239. {
  240. DNDeleteCriticalSection( &m_csLock );
  241. DNEnterCriticalSection( &CDirectVoiceEngine::s_csSTLLock );
  242. if( m_lpInputQueue != NULL )
  243. {
  244. delete m_lpInputQueue;
  245. m_lpInputQueue = NULL;
  246. }
  247. DNLeaveCriticalSection( &CDirectVoiceEngine::s_csSTLLock );
  248. if( m_lpInBoundAudioConverter != NULL )
  249. {
  250. m_lpInBoundAudioConverter->Release();
  251. m_lpInBoundAudioConverter = NULL;
  252. }
  253. if( m_pdvidTargets != NULL )
  254. {
  255. delete [] m_pdvidTargets;
  256. m_pdvidTargets = NULL;
  257. }
  258. Reset();
  259. }
  260. #undef DPF_MODNAME
  261. #define DPF_MODNAME "CVoicePlayer::FindAndRemovePlayerTarget"
  262. //
  263. // FindAndRemovePlayerTarget
  264. //
  265. // Searches the list of targets for this player and removes the specified player if it is part
  266. // of the list. The pfFound variable is set to TRUE if the player specfied was in the target
  267. // list, false otherwise.
  268. //
  269. BOOL CVoicePlayer::FindAndRemovePlayerTarget( DVID dvidTargetToRemove )
  270. {
  271. BOOL fFound = FALSE;
  272. Lock();
  273. for( DWORD dwTargetIndex = 0; dwTargetIndex < m_dwNumTargets; dwTargetIndex++ )
  274. {
  275. if( m_pdvidTargets[dwTargetIndex] == dvidTargetToRemove )
  276. {
  277. if( m_dwNumTargets == 1 )
  278. {
  279. delete [] m_pdvidTargets;
  280. m_pdvidTargets = NULL;
  281. }
  282. // Shortcut, move last element into the current element
  283. // prevents re-allocation. (However, it wastes an element of
  284. // target space) *Shrug*. If this is the last element in the list
  285. // we're removing this will simply provide an unessessary duplication
  286. // of the last element. (But num targets is correct so that's ok).
  287. else
  288. {
  289. m_pdvidTargets[dwTargetIndex] = m_pdvidTargets[m_dwNumTargets-1];
  290. }
  291. m_dwNumTargets--;
  292. fFound = TRUE;
  293. break;
  294. }
  295. }
  296. UnLock();
  297. return fFound;
  298. }