📄 hwctxt.cpp
字号:
0,
NULL
);
if (!m_hAudioHiFiOutputInterruptThread)
{
goto error;
}
# if WM_VOICE
if ( WM_HANDLE_INVALID != m_hVoiceInputStream )
{
m_hAudioVoiceInputInterruptThread = CreateThread( (LPSECURITY_ATTRIBUTES)NULL,
0,
(LPTHREAD_START_ROUTINE)CallVoiceInputInterruptThread,
this,
0,
NULL
);
if (!m_hAudioVoiceInputInterruptThread)
{
goto error;
}
}
if ( WM_HANDLE_INVALID != m_hVoiceOutputStream )
{
m_hAudioVoiceOutputInterruptThread = CreateThread( (LPSECURITY_ATTRIBUTES)NULL,
0,
(LPTHREAD_START_ROUTINE)CallVoiceOutputInterruptThread,
this,
0,
NULL
);
if (!m_hAudioVoiceOutputInterruptThread)
{
goto error;
}
}
# endif // WM_VOICE
# if WM_MONODAC
if ( WM_HANDLE_INVALID != m_hMonoOutputStream )
{
m_hAudioMonoOutputInterruptThread = CreateThread( (LPSECURITY_ATTRIBUTES)NULL,
0,
(LPTHREAD_START_ROUTINE)CallMonoOutputInterruptThread,
this,
0,
NULL
);
if (!m_hAudioMonoOutputInterruptThread)
{
goto error;
}
}
# endif // WM_MONODAC
// Bump up the priority since the interrupt must be serviced immediately.
if ( WM_HANDLE_INVALID != m_hHiFiInputStream )
{
CeSetThreadPriority(m_hAudioHiFiInputInterruptThread, GetInterruptThreadPriority());
}
CeSetThreadPriority(m_hAudioHiFiOutputInterruptThread, GetInterruptThreadPriority());
# if WM_VOICE
if ( WM_HANDLE_INVALID != m_hVoiceInputStream )
{
CeSetThreadPriority(m_hAudioVoiceInputInterruptThread, GetInterruptThreadPriority());
}
if ( WM_HANDLE_INVALID != m_hVoiceOutputStream )
{
CeSetThreadPriority(m_hAudioVoiceOutputInterruptThread, GetInterruptThreadPriority());
}
# endif // WM_VOICE
# if WM_MONODAC
if ( WM_HANDLE_INVALID != m_hMonoOutputStream )
{
CeSetThreadPriority(m_hAudioMonoOutputInterruptThread, GetInterruptThreadPriority());
}
# endif // WM_MONODAC
#else // WM_USE_DYNAMIC_DMA_CHANNEL
m_hAudioInterrupt = CreateEvent( NULL, FALSE, FALSE, NULL);
if (!m_hAudioInterrupt)
{
goto error;
}
bSuccess = InterruptInitialize(m_IntrAudio, m_hAudioInterrupt, NULL, 0);
m_hAudioInterruptThread = CreateThread((LPSECURITY_ATTRIBUTES)NULL,
0,
(LPTHREAD_START_ROUTINE)CallInterruptThread,
this,
0,
NULL);
if (!m_hAudioInterruptThread)
{
goto error;
}
// Bump up the priority since the interrupt must be serviced immediately.
CeSetThreadPriority(m_hAudioInterruptThread, GetInterruptThreadPriority());
#endif // WM_USE_DYNAMIC_DMA_CHANNEL
DEBUGMSG(ZONE_INIT|ZONE_FUNCTION, (TEXT("-InitInterruptThread\r\n")));
return bSuccess;
error:
//
// To clean up the threads, we say we're shutting down, and then
// wake them all up. They will see the shutting down flag and exit.
//
m_shuttingDown = TRUE;
#if WM_USE_DYNAMIC_DMA_CHANNEL
if ( hHiFiOutputIntEvent )
SetEvent( hHiFiOutputIntEvent );
if ( WM_HANDLE_INVALID != m_hHiFiInputStream )
{
if ( hHiFiInputIntEvent )
SetEvent( hHiFiInputIntEvent );
}
#if WM_VOICE
if ( WM_HANDLE_INVALID != m_hVoiceInputStream )
{
if ( hVoiceInputIntEvent )
SetEvent( hVoiceInputIntEvent );
}
if ( WM_HANDLE_INVALID != m_hVoiceOutputStream )
{
if ( hVoiceOutputIntEvent )
SetEvent( hVoiceOutputIntEvent );
}
#endif WM_VOICE
#if WM_MONODAC
if ( WM_HANDLE_INVALID != m_hMonoOutputStream )
{
if ( hMonoOutputIntEvent )
SetEvent( hMonoOutputIntEvent );
}
#endif WM_MONODAC
#else // WM_USE_DYNAMIC_DMA_CHANNEL
if ( m_hAudioInterrupt )
SetEvent( m_hAudioInterrupt );
#endif // WM_USE_DYNAMIC_DMA_CHANNEL
DEBUGMSG(ZONE_INIT|ZONE_FUNCTION, (TEXT("-InitInterruptThread ERROR\r\n")));
return ( FALSE );
}
#if WM_OUTPUT_MUTE_DELAY
//-----------------------------------------------------------------------------
// Member function: InitOutputMuteTimerThread
//
// Sets the output mute timer thread running.
//
// Parameters:
// none
//
// Returns: BOOL
// TRUE = success
// FALSE = failure
//-----------------------------------------------------------------------------
BOOL HardwareContext::InitOutputMuteTimerThread()
{
BOOL bSuccess = TRUE;
DEBUGMSG(ZONE_INIT|ZONE_FUNCTION, (TEXT("+InitOutputMuteTimerThread\r\n")));
m_hOutputMuteIntEvent = CreateEvent( NULL, FALSE, FALSE, NULL);
if (!m_hOutputMuteIntEvent)
{
ASSERT( 0 );
goto error;
}
// Create a timeout event.
m_hOutputMuteTimeoutEvent = CreateEvent( NULL,
FALSE,
FALSE,
WM_OUTPUT_MUTE_TIMEOUT_EVENT_NAME
);
if (!m_hOutputMuteTimeoutEvent)
{
ASSERT( 0 );
goto error;
}
m_hOutputMuteInterruptThread = CreateThread( (LPSECURITY_ATTRIBUTES)NULL,
0,
(LPTHREAD_START_ROUTINE)CallOutputMuteInterruptThread,
this,
0,
NULL
);
if (!m_hOutputMuteInterruptThread)
{
ASSERT( 0 );
goto error;
}
CeSetThreadPriority(m_hOutputMuteInterruptThread, GetInterruptThreadPriority());
DEBUGMSG(ZONE_INIT|ZONE_FUNCTION, (TEXT("-InitOutputMuteTimerThread\r\n")));
return bSuccess;
error:
//
// To clean up the threads, we say we're shutting down, and then
// wake them all up. They will see the shutting down flag and exit.
//
m_shuttingDown = TRUE;
if ( m_hOutputMuteIntEvent )
SetEvent( m_hOutputMuteIntEvent );
DEBUGMSG(ZONE_INIT|ZONE_FUNCTION, (TEXT("-InitOutputMuteTimerThread ERROR\r\n")));
return ( FALSE );
}
#endif /* WM_OUTPUT_MUTE_DELAY */
//-----------------------------------------------------------------------------
// Member function: Deinit
//
// Does any cleanup.
//
// Parameters:
// none
//
// Returns: BOOL
// TRUE = success
// FALSE = failure
//-----------------------------------------------------------------------------
BOOL HardwareContext::Deinit()
{
WMCloseDevice( m_hAudioDevice, WM_DRIVER_AUDIO );
return TRUE;
}
//-----------------------------------------------------------------------------
// Member function: TransferHiFiInputBuffer
//
// Attempts to transfer a buffer-worth of data to all input streams from the
// HiFi DMA.
//
// Parameters:
// NumBuf Buffer number to use when updating the local details.
// pBytesTransferred Variable to receive the number of bytes transferred.
//
// Returns: BOOL
// TRUE = DMA data available and transfer done
// FALSE = no DMA data available
//-----------------------------------------------------------------------------
BOOL HardwareContext::TransferHiFiInputBuffer( ULONG NumBuf, ULONG *pBytesTransferred )
{
ULONG BytesTransferred = 0;
PBYTE pBufferStart;
unsigned int nBufferSize;
PBYTE pBufferEnd;
PBYTE pBufferLast;
BOOL bufferAvailable = TRUE;
//
// Get our buffer from the API.
//
pBufferStart = (PBYTE) WMAudioStartRendering( m_hAudioDevice, m_hHiFiInputStream );
nBufferSize = WMAudioBufferSize( m_hAudioDevice, m_hHiFiInputStream );
pBufferEnd = pBufferStart + nBufferSize; // IBB: Is this correct? Do we need '-1'?
//
// If we've not got a buffer, they're all full so we'll need to wait.
//
if ( !pBufferStart )
{
bufferAvailable = FALSE;
goto end;
}
//
// Render all streams into the current buffer as appropriate.
//
pBufferLast = m_HiFiInputDeviceContext.TransferBuffer(pBufferStart, pBufferEnd,NULL);
BytesTransferred = m_HiFiInBytes[NumBuf] = pBufferLast-pBufferStart;
//
// Tell the API we've finished this buffer.
//
WMAudioFinishRendering( m_hAudioDevice, m_hHiFiInputStream, pBufferStart );
end:
*pBytesTransferred = BytesTransferred;
DEBUGMSG( ZONE_STREAMING,
( TEXT("HiFi In: %d bytes\r\n"), BytesTransferred )
);
return bufferAvailable;
}
//-----------------------------------------------------------------------------
// Member function: TransferHiFiInputBuffers
//
// Continues transferring data from the HiFi DMA buffers to the local streams
// until there is no more data available or no more space in the local streams.
//
// Parameters:
// none
//
// Returns: ULONG
// Number of bytes transferred.
//-----------------------------------------------------------------------------
ULONG HardwareContext::TransferHiFiInputBuffers()
{
BOOL BufferAvailable;
ULONG BytesTransferred = 0;
ULONG BytesTotal = 0;
ULONG BytesWaiting = 0;
do
{
BufferAvailable = TransferHiFiInputBuffer( m_nextHiFiInputBuf, &BytesTransferred );
if ( BufferAvailable )
{
BytesTotal += BytesTransferred;
m_nextHiFiInputBuf = 1 - m_nextHiFiInputBuf;
}
} while ( BufferAvailable );
//
// If it was our interrupt, but we weren't able to receive any bytes
// (e.g. no full buffers ready to be emptied)
// and all the input DMA buffers are now empty, then stop the input DMA
//
BytesWaiting = m_HiFiInBytes[0] + m_HiFiInBytes[1];
if (BytesWaiting==0)
{
StopHiFiInputDMA( m_pWMAudioDeviceData );
}
return BytesTotal;
}
//-----------------------------------------------------------------------------
// Member function: TransferHiFiOutputBuffer
//
// Attempts to transfer a buffer-worth of data from all output streams to the
// HiFi DMA. This will start the HiFi DMA streaming if required.
//
// Parameters:
// NumBuf Buffer number to use when updating the local details.
// pBytesTransferred Variable to receive the number of bytes transferred.
//
// Returns: BOOL
// TRUE = DMA buffer space available and transfer done
// FALSE = no DMA buffer space available
//-----------------------------------------------------------------------------
BOOL HardwareContext::TransferHiFiOutputBuffer( ULONG NumBuf, ULONG *pBytesTransferred )
{
ULONG BytesTransferred = 0;
PBYTE pBufferStart;
unsigned int nBufferSize;
PBYTE pBufferEnd;
PBYTE pBufferLast;
BOOL bufferAvailable = TRUE;
//
// Get our buffer from the API.
//
pBufferStart = (PBYTE) WMAudioStartRendering( m_hAudioDevice, m_hHiFiOutputStream );
nBufferSize = WMAudioBufferSize( m_hAudioDevice, m_hHiFiOutputStream );
pBufferEnd = pBufferStart + nBufferSize; // IBB: Is this correct? Do we need '-1'?
//
// If we've not got a buffer, they're all full so we'll need to wait.
//
if ( !pBufferStart )
{
bufferAvailable = FALSE;
goto end;
}
//
// Render all streams into the current buffer as appropriate.
//
pBufferLast = m_HiFiOutputDeviceContext.TransferBuffer(pBufferStart, pBufferEnd,NULL);
BytesTransferred = m_HiFiOutBytes[NumBuf] = pBufferLast-pBufferStart;
#if CLEAR_BUFFER // Enable if you need to clear the rest of the DMA buffer
StreamContext::ClearBuffer( pBufferLast, pBufferEnd );
#endif
//
// Tell the API we've finished this buffer.
//
WMAudioFinishRendering( m_hAudioDevice, m_hHiFiOutputStream, pBufferStart );
end:
DEBUGMSG( ZONE_STREAMING,
( TEXT("HiFi Out: %d bytes\r\n"), BytesTransferred )
);
*pBytesTransferred = BytesTransferred;
return bufferAvailable;
}
//-----------------------------------------------------------------------------
// Member function: TransferHiFiOutputBuffers
//
// Continues transferring data to the HiFi DMA buffers from the local streams
// until there is no more data available or no more space in the DMA buffers.
// This will start the DMA streaming if required.
//
// Parameters:
// none
//
// Returns: ULONG
// Number of bytes transferred.
//-----------------------------------------------------------------------------
ULONG HardwareContext::TransferHiFiOutputBuffers()
{
BOOL BufferAvailable;
ULONG BytesTransferred = 0;
ULONG BytesTotal = 0;
ULONG BytesWaiting = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -