📄 hwctxt.cpp
字号:
NULL);
m_hAudioInterruptThreadRx = CreateThread((LPSECURITY_ATTRIBUTES)NULL,
0,
(LPTHREAD_START_ROUTINE)CallInterruptThreadRx,
this,
0,
NULL);
m_hTimeoutThread = CreateThread ((LPSECURITY_ATTRIBUTES)NULL,
0,
(LPTHREAD_START_ROUTINE)CallTimeoutThread,
this,
0,
NULL);
return (m_hAudioInterruptThreadTx!=NULL && m_hAudioInterruptThreadRx!=NULL && m_hTimeoutThread!=NULL) ;
}
//------------------------------------------------------------------------------
//
// Function: Deinit()
//
//
//
BOOL
HardwareContext::Deinit()
{
return HWDeinit();
}
//------------------------------------------------------------------------------
//
// Function: TransferInputBuffer()
//
//
//
ULONG
HardwareContext::TransferInputBuffer(ULONG NumBuf)
{
ULONG BytesTransferred;
PBYTE pBufferStart = m_Input_pbDMA_PAGES[NumBuf];
PBYTE pBufferEnd = pBufferStart + AUDIO_DMA_PAGE_SIZE;
PBYTE pBufferLast;
DWORD NumStreams;
#ifdef PROFILE_MIXER
LARGE_INTEGER liPCStart, liPCStop;
QueryPerformanceCounter(&liPCStart);
#endif
pBufferLast = m_InputDeviceContext.TransferBuffer(pBufferStart, pBufferEnd, &NumStreams);
BytesTransferred = pBufferLast-pBufferStart;
#ifdef INPUT_CACHEDMEM
InputBufferCacheDiscard( pBufferStart, AUDIO_DMA_PAGE_SIZE);
#endif
#ifdef PROFILE_MIXER
QueryPerformanceCounter(&liPCStop);
m_InputDeviceContext.m_liPCTotal.QuadPart += liPCStop.QuadPart-liPCStart.QuadPart;
#endif
DEBUGMSG(ZONE_DMA, (TEXT("In(%d) %d bytes, str %d\r\n"),NumBuf, BytesTransferred, NumStreams));
#if 0
DWORD i;
PWORD pwData, pwLast;
RETAILMSG(1, (L"-------------------------------Input----------------------------------\r\n"));
pwData = (PWORD)pBufferStart;
pwLast = (PWORD)pBufferLast;
while (pwData < pwLast)
{
RETAILMSG(1, (L"\t"));
for (i = 0; i < 16 && pwData < pwLast; i++, pwData++)
{
RETAILMSG(1, (L"0x%04X, ", *pwData));
}
RETAILMSG(1, (L"\r\n"));
}
RETAILMSG(1, (L"-------------------------------Input----------------------------------\r\n"));
#endif
return BytesTransferred;
}
//------------------------------------------------------------------------------
//
// Function: HandleSaturation()
//
// check audio sample buffer for saturation conditions
//
#if USE_HW_SATURATE
void
HardwareContext::HandleSaturation(PBYTE pBuffer, PBYTE pBufferEnd)
{
for (;pBuffer<pBufferEnd;pBuffer+=sizeof(HWSAMPLE))
{
INT32 CurrSamp;
CurrSamp = *(HWSAMPLE *)pBuffer;
// Handle saturation
if (CurrSamp>AUDIO_SAMPLE_MAX)
{
*(HWSAMPLE *)pBuffer = AUDIO_SAMPLE_MAX;
}
if (CurrSamp<AUDIO_SAMPLE_MIN)
{
*(HWSAMPLE *)pBuffer = AUDIO_SAMPLE_MIN;
}
}
}
#endif
//------------------------------------------------------------------------------
//
// Function: TransferOutputBuffer()
//
// copy and reformat wave data for output through DMA
//
ULONG
HardwareContext::TransferOutputBuffer(ULONG NumBuf)
{
ULONG BytesTransferred;
PBYTE pBufferStart = m_Output_pbDMA_PAGES[NumBuf];
PBYTE pBufferEnd = pBufferStart + AUDIO_DMA_PAGE_SIZE;
PBYTE pBufferLast;
DWORD NumStreams;
DEBUGMSG(ZONE_DMA, (TEXT("TransferOutputBuffer: NumBuf=%d\r\n"), NumBuf));
#if 0
DWORD i;
PWORD pwData, pwLast;
RETAILMSG(1, (L"-------------------------------Output---------------------------------\r\n"));
pwData = (PWORD)pBufferStart;
pwLast = (PWORD)(pBufferStart + AUDIO_DMA_PAGE_SIZE);
while (pwData < pwLast)
{
RETAILMSG(1, (L"\t"));
for (i = 0; i < 16 && pwData < pwLast; i++, pwData++)
{
RETAILMSG(1, (L"0x%04X, ", *pwData));
}
RETAILMSG(1, (L"\r\n"));
}
RETAILMSG(1, (L"-------------------------------Output---------------------------------\r\n"));
#endif
#ifdef PROFILE_MIXER
LARGE_INTEGER liPCStart, liPCStop;
QueryPerformanceCounter(&liPCStart);
#endif
pBufferLast = m_OutputDeviceContext.TransferBuffer(pBufferStart, pBufferEnd, &NumStreams);
#if USE_HW_SATURATE
// If not using mix saturation, take care saturation here.
// If more than 1 stream rendered, guard against saturation.
if (NumStreams>1)
{
HandleSaturation(pBufferStart, pBufferLast);
}
#endif
// Clear the rest of the buffer
StreamContext::ClearBuffer(pBufferLast,pBufferEnd);
BytesTransferred = pBufferLast-pBufferStart;
#ifdef MIXER_CACHEDMEM
OutputBufferCacheFlush( pBufferStart, AUDIO_DMA_PAGE_SIZE);
#endif
#ifdef PROFILE_MIXER
QueryPerformanceCounter(&liPCStop);
m_OutputDeviceContext.m_liPCTotal.QuadPart += liPCStop.QuadPart-liPCStart.QuadPart;
#endif
DEBUGMSG(ZONE_DMA, (TEXT("Out(%d) %d bytes str %d\r\n"),NumBuf, BytesTransferred, NumStreams));
return BytesTransferred;
}
//------------------------------------------------------------------------------
//
// Function: InterruptThreadTx()
//
// play DMA IST
//
void
HardwareContext::InterruptThreadTx()
{
DEBUGMSG(ZONE_AC,
(TEXT("WaveDev: HardwareContext::InterruptThreadTx\r\n")));
// make sure that GWES APIs ready before calling:
if (WAIT_OBJECT_0 != WaitForAPIReady(SH_GDI, INFINITE))
{
DEBUGMSG(ZONE_ERROR, (TEXT("Wavedev driver: WaitForAPIReady failed.\r\n")));
return;
}
// Bump up the priority since the interrupt must be serviced immediately.
CeSetThreadPriority(GetCurrentThread(), m_dwPriority256);
DEBUGMSG(ZONE_AC,
(TEXT("WaveDev: HardwareContext::InterruptThreadTx Enable Interrupt!!!\r\n")));
while (!m_fTerminating)
{
DWORD dwWaitObject;
InterruptDone(m_IntrAudioTx);
dwWaitObject = WaitForSingleObject(m_hAudioInterruptTx, INFINITE);
DEBUGMSG(ZONE_IRQ,(TEXT("WAVE: Tx interrupt\r\n")));
// Grab the lock
Lock();
// Copy data to DMA buffers
HWTransferOutputBuffers();
Unlock();
}
}
//------------------------------------------------------------------------------
//
// Function: InterruptThreadRx()
//
// capture DMA IST
//
void
HardwareContext::InterruptThreadRx()
{
DEBUGMSG(ZONE_AC,
(TEXT("WaveDev: HardwareContext::InterruptThreadRx\r\n")));
// make sure that GWES APIs ready before calling:
if (WAIT_OBJECT_0 != WaitForAPIReady(SH_GDI, INFINITE))
{
DEBUGMSG(ZONE_ERROR, (TEXT("Wavedev driver: WaitForAPIReady failed.\r\n")));
return;
}
// Bump up the priority since the interrupt must be serviced immediately.
CeSetThreadPriority(GetCurrentThread(), m_dwPriority256);
while (!m_fTerminating)
{
DWORD dwWaitObject;
InterruptDone(m_IntrAudioRx);
dwWaitObject = WaitForSingleObject(m_hAudioInterruptRx, INFINITE);
DEBUGMSG(ZONE_IRQ,(TEXT("WAVE: Rx interrupt\r\n")));
// Grab the lock
Lock();
// Copy data from DMA buffers
HWTransferInputBuffers();
Unlock();
}
}
void
HardwareContext::TimeoutThread()
{
DEBUGMSG(ZONE_AC,
(TEXT("WaveDev: HardwareContext::TimeoutThread\r\n")));
DWORD dwTimeout = m_dwTimeoutTicks;
while (!m_fTerminating) {
DWORD dwWaitObject = WaitForSingleObject(m_hTimeoutEvent, dwTimeout);
if (dwWaitObject == WAIT_TIMEOUT) { // It is timeout.
DEBUGMSG(ZONE_AC,
(TEXT("WaveDev: HardwareContext::TimeoutThread Got timeout!\r\n")));
Lock();
DelayedUpdate() ;
Unlock();
dwTimeout = INFINITE;
}
else
dwTimeout = m_dwTimeoutTicks;
}
}
//------------------------------------------------------------------------------
//
// Function: CallInterruptThreadTx()
// CallInterruptThreadRx()
//
// static helper functions to start IST
//
static void
CallInterruptThreadTx(HardwareContext *pHWContext)
{
pHWContext->InterruptThreadTx();
}
static void
CallInterruptThreadRx(HardwareContext *pHWContext)
{
pHWContext->InterruptThreadRx();
}
static void
CallTimeoutThread(HardwareContext *pHWContext)
{
pHWContext->TimeoutThread();
}
//------------------------------------------------------------------------------
//
// Function: RecalcSpeakerEnable()
//
// RecalcSpeakerEnable decides whether to enable the speaker or not.
// For now, it only looks at the m_bForceSpeaker variable, but it could
// also look at whether the headset is plugged in (m_bHeadsetPluggedIn)
// and/or whether we're in a voice call (m_bInVoiceCall). Some mechanism would
// need to be implemented to inform the wave driver of changes in the state of
// these variables however.
//
void
HardwareContext::RecalcSpeakerEnable()
{
HWUpdateAudioPRC();
}
//------------------------------------------------------------------------------
//
// Function: ForceSpeaker()
//
// ForceSpeaker is called from the device context to update the state of the
// m_bForceSpeaker variable by MM_WOM_FORCESPEAKER.
//
DWORD
HardwareContext::ForceSpeaker( BOOL bForceSpeaker )
{
DEBUGMSG( ZONE_AC, (TEXT("WAVE: ForceSpeaker = %d\r\n"), bForceSpeaker));
// lock is only taken because of ++/-- operators
Lock();
// If m_NumForcedSpeaker is non-zero, audio should be routed to an
// external speaker (if hw permits).
if (bForceSpeaker)
{
m_NumForcedSpeaker++;
if (m_NumForcedSpeaker==1)
{
RecalcSpeakerEnable();
}
}
else
{
if (m_NumForcedSpeaker > 0)
{
m_NumForcedSpeaker--;
if (m_NumForcedSpeaker)
{
RecalcSpeakerEnable();
}
}
}
Unlock();
return MMSYSERR_NOERROR;
}
//------------------------------------------------------------------------------
//
// Function: PowerUp()
//
//
//
void
HardwareContext::PowerUp()
{
HWPowerUp();
}
//------------------------------------------------------------------------------
//
// Function: PowerDown()
//
//
//
void
HardwareContext::PowerDown()
{
HWPowerDown();
}
//------------------------------------------------------------------------------
//
// Function: SetExtSpeakerPower()
//
// Indicate amplifiers can be powered on/off.
//
BOOL
HardwareContext::SetExtSpeakerPower( BOOL fOn )
{
DEBUGMSG( ZONE_ERROR, ( TEXT( "WAVE: SetExtSpeakerPower not implemented!\r\n" )));
return FALSE;
}
//------------------------------------------------------------------------------
//
// Function: PrepareForVoiceCall( BOOL bInVoiceCall )
//
// get notice from Ril to get ready for a voice call
//
BOOL
HardwareContext::PrepareForVoiceCall( BOOL bInVoiceCall )
{
return HWEnableNetwork( bInVoiceCall );
}
//------------------------------------------------------------------------------
//
// Function: NotifyHeadsetOn()
//
// Route to headset or not.
//
//
VOID
HardwareContext::NotifyHeadsetOn(BOOL fHeadset)
{
m_bHeadsetPluggedIn = fHeadset;
HWUpdateAudioPRC();
}
//------------------------------------------------------------------------------
//
// Function: ToggleExtSpeaker()
//
// Toggle external speaker if available.
//
VOID
HardwareContext::ToggleExtSpeaker()
{
m_bToggleLoadSpeaker = TRUE;
HWUpdateAudioPRC();
}
//------------------------------------------------------------------------------
//
// Function: NotifyBtHeadsetOn()
//
// Route to BT headset or not.
//
VOID
HardwareContext::NotifyBtHeadsetOn(DWORD dwBtAudioRouting)
{
m_bBtHeadsetSelected = FALSE;
m_dwBtAudioRouting = BT_AUDIO_NONE;
dwBtAudioRouting &= (BT_AUDIO_SYSTEM | BT_AUDIO_MODEM);
if (dwBtAudioRouting)
{
m_bBtHeadsetSelected = TRUE;
m_dwBtAudioRouting = dwBtAudioRouting;
}
HWUpdateAudioPRC();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -