|
|
/*==========================================================================
* * Copyright (C) 1999 - 1999 Microsoft Corporation. All Rights Reserved. * * File: vplayer.h * Content: Voice Player Entry * * History: * Date By Reason * ==== == ====== * 03/26/00 rodtoll Created * 07/09/2000 rodtoll Added signature bytes ***************************************************************************/
#include "dxvoicepch.h"
CVoicePlayer::CVoicePlayer() { m_dwSignature = VSIG_VOICEPLAYER; Reset(); }
CVoicePlayer::~CVoicePlayer() { if( IsInitialized() ) DeInitialize();
m_dwSignature = VSIG_VOICEPLAYER_FREE; }
void CVoicePlayer::Reset() { m_dwFlags = 0; m_dvidPlayer = 0; m_lRefCount = 0; m_lpInBoundAudioConverter = NULL; m_lpInputQueue = NULL; m_dwLastData = 0; m_dwHostOrderID = 0xFFFFFFFF; m_bLastPeak = 0; m_dwLastPlayback = 0; m_dwNumSilentFrames = 0; m_dwTransportFlags = 0; m_dwNumLostFrames = 0; m_dwNumSpeechFrames = 0; m_dwNumReceivedFrames = 0; m_pvPlayerContext = NULL; InitBilink( &m_blNotifyList, this ); InitBilink( &m_blPlayList, this ); m_dwNumTargets = 0; m_pdvidTargets = NULL; }
#undef DPF_MODNAME
#define DPF_MODNAME "CVoicePlayer::SetPlayerTargets"
//
// Assumes the array has been checked for validity
//
HRESULT CVoicePlayer::SetPlayerTargets( PDVID pdvidTargets, DWORD dwNumTargets ) { Lock();
delete [] m_pdvidTargets;
if( dwNumTargets == 0 ) { m_pdvidTargets = NULL; } else { m_pdvidTargets = new DVID[dwNumTargets];
if( m_pdvidTargets == NULL ) { m_pdvidTargets = NULL; m_dwNumTargets = 0; DPFX(DPFPREP, DVF_ERRORLEVEL, "Error allocating memory" ); UnLock(); return DVERR_OUTOFMEMORY; }
memcpy( m_pdvidTargets, pdvidTargets, sizeof(DVID)*dwNumTargets ); }
m_dwNumTargets = dwNumTargets; UnLock();
return DV_OK; }
HRESULT CVoicePlayer::Initialize( const DVID dvidPlayer, const DWORD dwHostOrder, DWORD dwFlags, PVOID pvContext, CLockedFixedPool<CVoicePlayer> *pOwner ) { if (!DNInitializeCriticalSection( &m_csLock )) { return DVERR_OUTOFMEMORY; } m_lRefCount = 1; m_pOwner = pOwner; m_dvidPlayer = dvidPlayer; m_dwHostOrderID = dwHostOrder; m_dwLastData = GetTickCount(); m_dwLastPlayback = 0; m_dwTransportFlags = dwFlags; m_pvPlayerContext = pvContext; m_dwFlags |= VOICEPLAYER_FLAGS_INITIALIZED; return DV_OK; }
void CVoicePlayer::GetStatistics( PVOICEPLAYER_STATISTICS pStats ) { memset( pStats, 0x00, sizeof( VOICEPLAYER_STATISTICS ) );
// Get queue statistics
if( m_lpInputQueue != NULL ) { Lock(); m_lpInputQueue->GetStatistics( &pStats->queueStats );
UnLock(); } pStats->dwNumLostFrames = m_dwNumLostFrames; pStats->dwNumSilentFrames = m_dwNumSilentFrames; pStats->dwNumSpeechFrames = m_dwNumSpeechFrames; pStats->dwNumReceivedFrames = m_dwNumReceivedFrames;
return; }
HRESULT CVoicePlayer::CreateQueue( PQUEUE_PARAMS pQueueParams ) { HRESULT hr;
DNEnterCriticalSection( &CDirectVoiceEngine::s_csSTLLock );
m_lpInputQueue = new CInputQueue2(); if( m_lpInputQueue == NULL ) { DPFX(DPFPREP, 0, "Error allocating memory" ); return DVERR_OUTOFMEMORY; } hr = m_lpInputQueue->Initialize( pQueueParams );
if( FAILED( hr ) ) { DPFX(DPFPREP, 0, "Failed initializing queue hr=0x%x", hr ); delete m_lpInputQueue; m_lpInputQueue = NULL; return hr; }
DNLeaveCriticalSection( &CDirectVoiceEngine::s_csSTLLock );
return hr; }
HRESULT CVoicePlayer::CreateInBoundConverter( const GUID &guidCT, PWAVEFORMATEX pwfxTargetFormat ) { HRESULT hr;
hr = DVCDB_CreateConverter( guidCT, pwfxTargetFormat, &m_lpInBoundAudioConverter );
if( FAILED( hr ) ) { DPFX(DPFPREP, 0, "Error creating audio converter hr=0x%x" , hr ); return hr; }
if( pwfxTargetFormat->wBitsPerSample == 8) { m_dwFlags |= VOICEPLAYER_FLAGS_TARGETIS8BIT; }
return hr; }
HRESULT CVoicePlayer::DeInitialize() { FreeResources();
m_pOwner->Release( this );
return DV_OK; }
HRESULT CVoicePlayer::HandleReceive( PDVPROTOCOLMSG_SPEECHHEADER pdvSpeechHeader, PBYTE pbData, DWORD dwSize ) { CFrame tmpFrame;
tmpFrame.SetSeqNum( pdvSpeechHeader->bSeqNum ); tmpFrame.SetMsgNum( pdvSpeechHeader->bMsgNum ); tmpFrame.SetIsSilence( FALSE ); tmpFrame.SetFrameLength( dwSize ); tmpFrame.UserOwn_SetData( pbData, dwSize );
Lock();
DPFX(DPFPREP, DVF_CLIENT_SEQNUM_DEBUG_LEVEL, "SEQ: Receive: Msg [%d] Seq [%d]", pdvSpeechHeader->bMsgNum, pdvSpeechHeader->bSeqNum );
// STATSBLOCK: Begin
//m_stats.m_dwPRESpeech++;
// STATSBLOCK: End
m_lpInputQueue->Enqueue( tmpFrame ); m_dwLastData = GetTickCount();
DPFX(DPFPREP, DVF_INFOLEVEL, "Received speech is buffered!" );
m_dwNumReceivedFrames++;
UnLock();
return DV_OK; }
CFrame *CVoicePlayer::Dequeue(BOOL *pfLost, BOOL *pfSilence) { CFrame *frTmpFrame;
Lock(); frTmpFrame = m_lpInputQueue->Dequeue(); UnLock();
if( !frTmpFrame->GetIsSilence() ) { *pfSilence = FALSE; m_dwLastPlayback = GetTickCount(); m_dwNumSpeechFrames++; } else { m_dwNumSilentFrames++; *pfSilence = TRUE; }
if( frTmpFrame->GetIsLost() ) { *pfLost = TRUE; m_dwNumLostFrames++; } else { *pfLost = FALSE; }
return frTmpFrame; }
HRESULT CVoicePlayer::DeCompressInBound( CFrame *frCurrentFrame, PVOID pvBuffer, PDWORD pdwBufferSize ) { HRESULT hr;
hr = m_lpInBoundAudioConverter->Convert( frCurrentFrame->GetDataPointer(), frCurrentFrame->GetFrameLength(), pvBuffer, pdwBufferSize, frCurrentFrame->GetIsSilence() );
if( FAILED( hr ) ) { DPFX(DPFPREP, 0, "Failed converting audio hr=0x%x", hr ); return hr; }
return hr; }
HRESULT CVoicePlayer::GetNextFrameAndDecompress( PVOID pvBuffer, PDWORD pdwBufferSize, BOOL *pfLost, BOOL *pfSilence, DWORD *pdwSeqNum, DWORD *pdwMsgNum ) { CFrame *frTmpFrame; BYTE bLastPeak; HRESULT hr;
frTmpFrame = Dequeue(pfLost,pfSilence );
*pdwSeqNum = frTmpFrame->GetSeqNum(); *pdwMsgNum = frTmpFrame->GetMsgNum();
hr = DeCompressInBound( frTmpFrame, pvBuffer, pdwBufferSize );
frTmpFrame->Return();
if( FAILED( hr ) ) { DPFX(DPFPREP, 0, "Failed converting audio hr=0x%x", hr ); return hr; }
if( *pfSilence ) { m_bLastPeak = 0; } else { m_bLastPeak = FindPeak( (PBYTE) pvBuffer, *pdwBufferSize, Is8BitUnCompressed() ); }
return hr; }
void CVoicePlayer::FreeResources() { DNDeleteCriticalSection( &m_csLock );
DNEnterCriticalSection( &CDirectVoiceEngine::s_csSTLLock ); if( m_lpInputQueue != NULL ) { delete m_lpInputQueue; m_lpInputQueue = NULL; } DNLeaveCriticalSection( &CDirectVoiceEngine::s_csSTLLock );
if( m_lpInBoundAudioConverter != NULL ) { m_lpInBoundAudioConverter->Release(); m_lpInBoundAudioConverter = NULL; }
if( m_pdvidTargets != NULL ) { delete [] m_pdvidTargets; m_pdvidTargets = NULL; }
Reset(); }
#undef DPF_MODNAME
#define DPF_MODNAME "CVoicePlayer::FindAndRemovePlayerTarget"
//
// FindAndRemovePlayerTarget
//
// Searches the list of targets for this player and removes the specified player if it is part
// of the list. The pfFound variable is set to TRUE if the player specfied was in the target
// list, false otherwise.
//
BOOL CVoicePlayer::FindAndRemovePlayerTarget( DVID dvidTargetToRemove ) { BOOL fFound = FALSE; Lock();
for( DWORD dwTargetIndex = 0; dwTargetIndex < m_dwNumTargets; dwTargetIndex++ ) { if( m_pdvidTargets[dwTargetIndex] == dvidTargetToRemove ) { if( m_dwNumTargets == 1 ) { delete [] m_pdvidTargets; m_pdvidTargets = NULL; } // Shortcut, move last element into the current element
// prevents re-allocation. (However, it wastes an element of
// target space) *Shrug*. If this is the last element in the list
// we're removing this will simply provide an unessessary duplication
// of the last element. (But num targets is correct so that's ok).
else { m_pdvidTargets[dwTargetIndex] = m_pdvidTargets[m_dwNumTargets-1]; }
m_dwNumTargets--; fFound = TRUE; break; } }
UnLock();
return fFound; }
|