📄 wavepdd.cxx
字号:
m8 = ((UINT8) (M >> 8)) ^ 0x80;
}
*pDst++ = m8;
}
}
// -----------------------------------------------------------------------------
// ExtractFromWaveBuffers
// -----------------------------------------------------------------------------
// Copies data from wave buffers to given buffer
// returns amount of data copied
// -----------------------------------------------------------------------------
static DWORD
ExtractFromWaveBuffers(
PWAVEHDR pwh,
PBYTE pBuffer,
DWORD dwBufferLen
)
{
DWORD dwTotalBytes = 0;
DWORD dwWaveBufferLen = dwBufferLen * 4;
while ( (dwWaveBufferLen > 0) && (pwh != NULL))
{
if (pwh->dwBytesRecorded >= pwh->dwBufferLength) {
pwh = pwh->lpNext;
continue;
}
// trasfer min(data_in_wavebuffer, room_in_pBuffer)
ULONG ulBytesCopied = pwh->dwBufferLength - pwh->dwBytesRecorded;
if ( ulBytesCopied > dwWaveBufferLen ) {
ulBytesCopied = dwWaveBufferLen;
}
/*
PWAVEHDR pTest = pwh;
DWORD dwTestBytes = pTest->dwBufferLength - pTest->dwBytesRecorded;
while(pTest->lpNext) {
pTest = pTest->lpNext;
dwTestBytes += pTest->dwBufferLength - pTest->dwBytesRecorded;
}
DEBUGMSG(1, (_T("=== BT Audio Driver Module: ExtractFromWaveBuffers. Total_Size=%u. GetTickCount=%u. ===\n"), dwTestBytes, GetTickCount()));
*/
// Convert from 16-bit stereo to 8-bit mono
ASSERT((ulBytesCopied % 4) == 0);
DWORD dwSamples = ulBytesCopied/4;
ConvertS16toM08((UINT32*)(pwh->lpData + pwh->dwBytesRecorded), pBuffer, dwSamples);
pwh->dwBytesRecorded += ulBytesCopied;
dwWaveBufferLen -= ulBytesCopied;
pBuffer += (ulBytesCopied/4);
dwTotalBytes += (ulBytesCopied/4);
}
return dwTotalBytes;
}
// -----------------------------------------------------------------------------
// TransmitPackets
// -----------------------------------------------------------------------------
// Takes data from wavebuffers and invokes DataPacketDown
// return: number of packets successfully sent down
// -----------------------------------------------------------------------------
static DWORD
TransmitPackets(
PWAVEHDR pwh,
DWORD dwCount,
PDWORD pdwError
)
{
DWORD dwDataBytes;
DWORD dwPacketCount;
int ret;
*pdwError = ERROR_SUCCESS;
//DEBUGMSG(1, (_T("=== BT Audio Driver Module: TransmitPackets. Count=%d. GetTickCount=%u. ===\n"), dwCount, GetTickCount()));
for (dwPacketCount = 0; dwPacketCount < dwCount; dwPacketCount++)
{
dwDataBytes = ExtractFromWaveBuffers (pwh, g_pTxBuffer, g_dwScoPacketSize);
if (dwDataBytes < g_dwScoPacketSize) {
//BSS_ERRMSG2(L"=== BT Audio Driver Module: TransmitPackets (SILENCE). Bytes=%d. GetTickCount=%u. ===\n", g_dwScoPacketSize - dwDataBytes, GetTickCount());
memset(g_pTxBuffer + dwDataBytes, SILENCE, g_dwScoPacketSize - dwDataBytes);
}
ret = g_ScoIntf.DataPacketDown (NULL, g_usScoConnHandle, g_pTxBuffer, g_dwScoPacketSize);
if (ret) {
*pdwError = ret;
return dwPacketCount;
}
}
return dwPacketCount;
}
// -----------------------------------------------------------------------------
// AudioThreadProc
// -----------------------------------------------------------------------------
// This is the thread which waits for and processes SCO events.
// -----------------------------------------------------------------------------
DWORD AudioThreadProc(LPVOID lpParameter)
{
int i;
DWORD dwWaitRet;
DWORD dwEvent;
HANDLE hEvents[NUM_AUDIO_EVENTS];
BOOL fAbort = FALSE;
BOOL bSwapped = FALSE;
HANDLE hTemp;
// Set thread priority higher so audio experience is good
// when system is busy
HANDLE hCurThread = (HANDLE) GetCurrentThreadId();
CeSetThreadPriority(hCurThread, DEFAULT_THREAD_PRIORITY);
for (i = 0; i < NUM_AUDIO_EVENTS; i++)
{
hEvents[i] = g_hAudioEvents[i];
}
//
// to access the gsi[apidir].pwh, need to set access key
//
DWORD dwAccessKey = GetCurrentPermissions();
SetProcPermissions((ULONG) -1); // access everybody
BSS_VERBOSE("AudioThreadProc ready");
while (1)
{
// documentation says that
// --WaitForMultipleObjects:
// ---If more than one object became signaled during the call, array index of the signaled object with
// ---the smallest index value of all the signaled objects is returned.
// since we want AUDIO_EVENT_RX_DATA and AUDIO_EVENT_TX_DATA to be treated fairly (equally)
// we will swap those 2 event handles every time we call WaitForMultipleObjects
//
// swap the RX/TX event handles
hTemp = hEvents[AUDIO_EVENT_RX_DATA];
hEvents[AUDIO_EVENT_RX_DATA] = hEvents[AUDIO_EVENT_TX_DATA];
hEvents[AUDIO_EVENT_TX_DATA] = hTemp;
bSwapped = !bSwapped;
dwWaitRet = WaitForMultipleObjects(NUM_AUDIO_EVENTS, hEvents, FALSE, INFINITE);
if ( (dwWaitRet < WAIT_OBJECT_0) || (dwWaitRet >= (WAIT_OBJECT_0 + NUM_AUDIO_EVENTS)) ) {
BSS_ERRMSG2("AudioThreadProc: WaitForMultipleObjects returned %#x, error %d", dwWaitRet, GetLastError());
DeinitSco();
return FALSE;
}
dwEvent = dwWaitRet - WAIT_OBJECT_0;
// index corresponds to event unless it was an RX/TX event and things were swapped
if (bSwapped && (dwEvent == AUDIO_EVENT_RX_DATA)) {
dwEvent = AUDIO_EVENT_TX_DATA;
} else if (bSwapped && (dwEvent == AUDIO_EVENT_TX_DATA)) {
dwEvent = AUDIO_EVENT_RX_DATA;
}
if (dwEvent == AUDIO_EVENT_EXIT_THREAD) {
BSS_INTMSG("AudioThreadProc : AUDIO_EVENT_EXIT_THREAD");
DeinitSco();
break;
}
switch (dwEvent)
{
case AUDIO_EVENT_RX_DATA:
//BSS_INTMSG("AudioThreadProc : AUDIO_EVENT_RX_DATA");
LOCK_STREAM_INFO(WAPI_IN);
if (g_StreamInfo[WAPI_IN].bOpened && g_StreamInfo[WAPI_IN].bStarted)
{
UNLOCK_STREAM_INFO(WAPI_IN);
LOCK_GSI(WAPI_IN);
LOCK_RXBUFFER();
BSS_VERBOSE1("AudioThreadProc : RxBufferToWaveBuffers g_dwRxBufferLen=%d", g_dwRxBufferLen);
RxBufferToWaveBuffers(gsi[WAPI_IN].pwh);
UNLOCK_RXBUFFER();
MarkFullAsDone(WAPI_IN);
RemoveCompleteBlocks(WAPI_IN);
UNLOCK_GSI(WAPI_IN);
}
else {
UNLOCK_STREAM_INFO(WAPI_IN);
}
break;
case AUDIO_EVENT_TX_DATA:
//BSS_INTMSG("AudioThreadProc : AUDIO_EVENT_TX_DATA");
LOCK_STREAM_INFO(WAPI_OUT);
if (g_StreamInfo[WAPI_OUT].bOpened && g_StreamInfo[WAPI_OUT].bStarted)
{
BOOL bSuccess;
DWORD dwError;
UNLOCK_STREAM_INFO(WAPI_OUT);
LOCK_GSI(WAPI_OUT);
LOCK_TXBUFFER();
BSS_VERBOSE1("AudioThreadProc : TransmitPackets num=%d", g_dwTxPacketsToSend);
bSuccess = ( g_dwTxPacketsToSend == TransmitPackets(gsi[WAPI_OUT].pwh, g_dwTxPacketsToSend, &dwError) );
g_dwTxPacketsToSend = 0;
UNLOCK_TXBUFFER();
if (bSuccess) {
MarkFullAsDone(WAPI_OUT);
RemoveCompleteBlocks(WAPI_OUT);
} else {
BSS_ERRMSG1("AudioThreadProc : error %d while transmitting packets", dwError);
fAbort = TRUE;
}
UNLOCK_GSI(WAPI_OUT);
}
else {
UNLOCK_STREAM_INFO(WAPI_OUT);
}
break;
case AUDIO_EVENT_STACK_DOWN:
case AUDIO_EVENT_SCO_LINK_DISCONNECT:
BSS_INTMSG("AudioThreadProc : AUDIO_EVENT_STACK_DOWN or AUDIO_EVENT_SCO_LINK_DISCONNECT");
fAbort = TRUE;
break;
case AUDIO_EVENT_STACK_UP:
BSS_INTMSG("AudioThreadProc : AUDIO_EVENT_STACK_UP");
break;
}
if (fAbort) {
wdev_WODM_RESET(0, 0, 0, 0);
wdev_WIDM_RESET(0, 0, 0, 0);
wdev_COMMON_CLOSE(WAPI_OUT, 0, 0, 0, 0);
wdev_COMMON_CLOSE(WAPI_IN, 0, 0, 0, 0);
DeinitSco();
break;
}
}
// change permission back
SetProcPermissions(dwAccessKey);
return TRUE;
}
// -----------------------------------------------------------------------------
// PddMsg_GetDevCaps
// -----------------------------------------------------------------------------
static MMRESULT
PddMsg_GetDevCaps(
WAPI_INOUT apidir,
PVOID pCaps,
UINT wSize
)
{
PWAVEINCAPS pwic = (PWAVEINCAPS)pCaps;
PWAVEOUTCAPS pwoc = (PWAVEOUTCAPS)pCaps;
MMRESULT mmRet = MMSYSERR_NOERROR;
BSS_FUNC_WPDD("+PddMsg_GetDevCaps");
if (!pCaps) {
return MMSYSERR_NOERROR;
}
pwoc->wMid = MM_MICROSOFT;
pwoc->vDriverVersion = 0x0001;
wsprintf (pwoc->szPname, TEXT("WinCE Bluetooth SCO Audio"));
pwoc->wChannels = 1;
if (apidir == WAPI_OUT)
{
pwoc->wPid = 24;
pwoc->wChannels = 2;
pwoc->dwFormats = WAVE_FORMAT_1M08 | WAVE_FORMAT_1S16 | WAVE_FORMAT_2S16 | WAVE_FORMAT_4S16;
// Caution: the WAVEINCAPS structure doesn't have a dwSupport field.
pwoc->dwSupport = 0;
}
else {
pwoc->wPid = 23;
pwoc->wChannels = 1;
pwoc->dwFormats = WAVE_FORMAT_1M08;
}
BSS_FUNC_WPDD("-PddMsg_GetDevCaps");
return mmRet;
}
// -----------------------------------------------------------------------------
// PddMsg_Start
// -----------------------------------------------------------------------------
static MMRESULT
PddMsg_Start (
WAPI_INOUT apidir,
PWAVEHDR pwh
)
{
BSS_FUNC_WPDD("+PddMsg_Start");
LOCK_STREAM_INFO(apidir);
g_StreamInfo[apidir].bStarted = TRUE;
UNLOCK_STREAM_INFO(apidir);
LOCK_TXBUFFER();
g_dwTxPacketsToSend = g_dwConcurrentPackets / 2;
UNLOCK_TXBUFFER();
if (apidir == WAPI_OUT) {
// kick start packet transmission
SetEvent(g_hAudioEvents[AUDIO_EVENT_TX_DATA]);
}
BSS_FUNC_WPDD("-PddMsg_Start");
return MMSYSERR_NOERROR;
}
// -----------------------------------------------------------------------------
// PddMsg_Stop
// -----------------------------------------------------------------------------
static MMRESULT
PddMsg_Stop(
WAPI_INOUT apidir
)
{
BSS_FUNC_WPDD("+PddMsg_Stop");
LOCK_STREAM_INFO(apidir);
g_StreamInfo[apidir].bStarted = FALSE;
UNLOCK_STREAM_INFO(apidir);
BSS_FUNC_WPDD("-PddMsg_Stop");
return MMSYSERR_NOERROR;
}
static DWORD
EstablishScoConnection(
USHORT *pusScoConnection
)
{
if (g_bConnectOut) {
int iErr;
//
// get a list of all the current connections
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -