⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bttalk.cpp

📁 CE下基于PXA255的蓝牙驱动
💻 CPP
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//

#include <windows.h>
#include "utils.h"
#include "queue.h"

// events and channels
LPCTSTR pszChannels[] = {L"WaveIn0", L"WaveIn1", L"WaveOut0", L"WaveOut1"};
#define WAVEIN0     0
#define WAVEIN1     1
#define WAVEOUT0    2
#define WAVEOUT1    3
#define CHANNELS    4

#define HEADERS_PER_STREAM  8
#define BYTES_PER_HEADER    400 // 8bytes/ms ==> 400bytes=50ms

static DWORD    g_dwDuration        = 60000;
static BOOL     g_bDispUnderruns    = FALSE;

BOOL InitAudio(HANDLE*      phEvents, 
               LPVOID*      phWaves,
               PWAVEHDR     pStream0,
               PWAVEHDR     pStream1)
{
    int i;

    memset(phEvents, 0, sizeof(HANDLE) * CHANNELS);
    memset(phWaves , 0, sizeof(void*)  * CHANNELS);
    memset(pStream0, 0, sizeof(WAVEHDR) * HEADERS_PER_STREAM);
    memset(pStream1, 0, sizeof(WAVEHDR) * HEADERS_PER_STREAM);

    for (i = 0; i < HEADERS_PER_STREAM; i++)
    {
        pStream0[i].lpData = (LPSTR) LocalAlloc(0, BYTES_PER_HEADER);
        pStream1[i].lpData = (LPSTR) LocalAlloc(0, BYTES_PER_HEADER);
        if (!pStream0[i].lpData || !pStream1[i].lpData) {
            OutputMessage(L"LocalAlloc failed\n");
            return FALSE;
        }
        pStream0[i].dwBufferLength = BYTES_PER_HEADER;
        pStream1[i].dwBufferLength = BYTES_PER_HEADER;
    }

    for (i = 0; i < CHANNELS; i++)
    {
        phEvents[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
        if (!phEvents[i]) {
            OutputMessage(L"CreateEvent failed %d\n", GetLastError());
            return FALSE;
        }
    }

    MMRESULT mmr;
    WAVEFORMATEX wfx = {0};
    wfx.wFormatTag      = WAVE_FORMAT_PCM;
    wfx.wBitsPerSample  = 8;
    wfx.nSamplesPerSec  = 8000;
    wfx.nChannels       = 1;
    wfx.nBlockAlign     = wfx.nChannels * wfx.wBitsPerSample / 8;
    wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
    wfx.cbSize          = 0;

    mmr = waveInOpen((HWAVEIN*)&phWaves[WAVEIN0], 0, &wfx, (DWORD) phEvents[WAVEIN0], NULL, CALLBACK_EVENT);
    if (mmr != MMSYSERR_NOERROR) {
        OutputMessage(L"MMSYSERR %d opening WaveIn0 GetLastError=%d\n", mmr, GetLastError());
        return FALSE;
    }

    mmr = waveInOpen((HWAVEIN*)&phWaves[WAVEIN1], 1, &wfx, (DWORD) phEvents[WAVEIN1], NULL, CALLBACK_EVENT);
    if (mmr != MMSYSERR_NOERROR) {
        OutputMessage(L"MMSYSERR %d opening WaveIn1 GetLastError=%d\n", mmr, GetLastError());
        return FALSE;
    }

    mmr = waveOutOpen((HWAVEOUT*)&phWaves[WAVEOUT0], 0, &wfx, (DWORD) phEvents[WAVEOUT0], NULL, CALLBACK_EVENT);
    if (mmr != MMSYSERR_NOERROR) {
        OutputMessage(L"MMSYSERR %d opening WaveOut0 GetLastError=%d\n", mmr, GetLastError());
        return FALSE;
    }

    mmr = waveOutOpen((HWAVEOUT*)&phWaves[WAVEOUT1], 1, &wfx, (DWORD) phEvents[WAVEOUT1], NULL, CALLBACK_EVENT);
    if (mmr != MMSYSERR_NOERROR) {
        OutputMessage(L"MMSYSERR %d opening WaveOut1 GetLastError=%d\n", mmr, GetLastError());
        return FALSE;
    }

    return TRUE;
}

BOOL DeinitAudio ( HANDLE*      phEvents, 
                   LPVOID*      phWaves,
                   PWAVEHDR     pStream0,
                   PWAVEHDR     pStream1)
{
    int i;

    if (phWaves[WAVEIN0]) {
        waveInReset((HWAVEIN)phWaves[WAVEIN0]);
        waveInClose((HWAVEIN)phWaves[WAVEIN0]);
    }
    if (phWaves[WAVEIN1]) {
        waveInReset((HWAVEIN)phWaves[WAVEIN1]);
        waveInClose((HWAVEIN)phWaves[WAVEIN1]);
    }
    if (phWaves[WAVEOUT0]) {
        waveOutReset((HWAVEOUT)phWaves[WAVEOUT0]);
        waveOutClose((HWAVEOUT)phWaves[WAVEOUT0]);
    }
    if (phWaves[WAVEOUT1]) {
        waveOutReset((HWAVEOUT)phWaves[WAVEOUT1]);
        waveOutClose((HWAVEOUT)phWaves[WAVEOUT1]);
    }

    for (i = 0; i < CHANNELS; i++)
    {
        if (phEvents[i]) {
            CloseHandle(phEvents[i]);
        }
    }

    for (i = 0; i < HEADERS_PER_STREAM; i++)
    {
        if (pStream0[i].lpData) {
            LocalFree((HLOCAL)pStream0[i].lpData);
        }
        if (pStream1[i].lpData) {
            LocalFree((HLOCAL)pStream1[i].lpData);
        }
    }

    memset(phEvents, 0, sizeof(HANDLE) * CHANNELS);
    memset(phWaves, 0, sizeof(void*) * CHANNELS);
    memset(pStream0, 0, sizeof(WAVEHDR) * HEADERS_PER_STREAM);
    memset(pStream1, 0, sizeof(WAVEHDR) * HEADERS_PER_STREAM);

    return TRUE;
}

BOOL AddAllHeaders(HWAVEIN hwi, PWAVEHDR pHeaders)
{
    int i;
    MMRESULT mmr;

    for (i = 0; i < HEADERS_PER_STREAM; i++)
    {
        mmr = waveInPrepareHeader(hwi, pHeaders + i, sizeof(WAVEHDR));
        if (mmr) {
            OutputMessage(L"waveInPrepareHeader failed %d GetLastError=%d\n", mmr, GetLastError());
            return FALSE;
        }

        mmr = waveInAddBuffer(hwi, pHeaders + i, sizeof(WAVEHDR));
        if (mmr) {
            OutputMessage(L"waveInAddBuffer failed %d GetLastError=%d\n", mmr, GetLastError());
            return FALSE;
        }
    }

    return TRUE;
}

//
// stream0: read data from device0 and write it to device1 (WAVEIN0 -> WAVEOUT1)
// stream1: read data from device1 and write it to device0 (WAVEIN1 -> WAVEOUT0)
//
BOOL DoAudioTransfers()
{
    HANDLE          hEvents[CHANNELS];
    LPVOID          phWaves[CHANNELS];
    WAVEHDR         HdrStream0[HEADERS_PER_STREAM];
    WAVEHDR         HdrStream1[HEADERS_PER_STREAM];

    CSimpleQueue    RunningQ[CHANNELS];
    MMRESULT        mmr;
    DWORD           dwWaitRet;
    int             i;

    if (!InitAudio(hEvents, phWaves, HdrStream0, HdrStream1)) {
        DeinitAudio(hEvents, phWaves, HdrStream0, HdrStream1);
        return FALSE;
    }

    if (!AddAllHeaders((HWAVEIN)phWaves[WAVEIN0], HdrStream0)) {
        OutputMessage(L"Adding headers to WAVEIN0 failed\n");
        DeinitAudio(hEvents, phWaves, HdrStream0, HdrStream1);
        return FALSE;
    }

    if (!AddAllHeaders((HWAVEIN)phWaves[WAVEIN1], HdrStream1)) {
        OutputMessage(L"Adding headers to WAVEIN1 failed\n");
        DeinitAudio(hEvents, phWaves, HdrStream0, HdrStream1);
        return FALSE;
    }

    for (i = 0; i < HEADERS_PER_STREAM; i++)
        RunningQ[WAVEIN0].Enqueue(i);

    for (i = 0; i < HEADERS_PER_STREAM; i++)
        RunningQ[WAVEIN1].Enqueue(i);

    mmr = waveInStart((HWAVEIN)phWaves[WAVEIN0]);
    if (mmr) {
        OutputMessage(L"waveInStart(WAVEIN0) failed %d GetLastError=%d\n", mmr, GetLastError());
        DeinitAudio(hEvents, phWaves, HdrStream0, HdrStream1);
        return FALSE;
    }

    mmr = waveInStart((HWAVEIN)phWaves[WAVEIN1]);
    if (mmr) {
        OutputMessage(L"waveInStart(WAVEIN1) failed %d GetLastError=%d\n", mmr, GetLastError());
        DeinitAudio(hEvents, phWaves, HdrStream0, HdrStream1);
        return FALSE;
    }

    OutputMessage(L"<<<< Audio transfers in progress... >>>>\n");

    __int64 i64Start        = GetFileTimeMilliseconds();
    __int64 i64End          = i64Start + g_dwDuration;
    __int64 i64LastDisplay  = 0;
    __int64 i64DisplayTime  = 5000; // time display every 5000 ms

    while (1)
    {
        do {
            dwWaitRet = WaitForMultipleObjects(CHANNELS, hEvents, FALSE, 200);

            if ( dwWaitRet == WAIT_TIMEOUT ) {
            } else if ( (dwWaitRet < WAIT_OBJECT_0) || (dwWaitRet >= WAIT_OBJECT_0 + CHANNELS) ) {
                OutputMessage(L"WaitForMultipleObjects failed %d GetLastError=%d\n", dwWaitRet, GetLastError());
                DeinitAudio(hEvents, phWaves, HdrStream0, HdrStream1);
                return FALSE;
            }

            __int64 i64Now = GetFileTimeMilliseconds();

            if (i64Now >= i64End) {
                OutputMessage(L">>>> Duration (%dms) of audio transfer expired. Closing audio... <<<< \n", g_dwDuration);
                DeinitAudio(hEvents, phWaves, HdrStream0, HdrStream1);
                return TRUE;
            }

            if ( (i64Now - i64LastDisplay) > i64DisplayTime) {
                OutputMessage(L">>>> %I64dms remaining in audio transfer...\n", i64End - i64Now);
                i64LastDisplay = i64Now;
            }
        } while (dwWaitRet == WAIT_TIMEOUT);

        DWORD       dwSource  = dwWaitRet;
        DWORD       dwTarget  = (DWORD)-1;
        PWAVEHDR    pHeaders  = NULL;
        switch (dwWaitRet)
        {
            case WAVEIN0:
                dwTarget = WAVEOUT1;
                pHeaders = HdrStream0;
                break;
            case WAVEIN1:
                dwTarget = WAVEOUT0;
                pHeaders = HdrStream1;
                break;
            case WAVEOUT0:
                dwTarget = WAVEIN1;
                pHeaders = HdrStream1;
                break;
            case WAVEOUT1:
                dwTarget = WAVEIN0;
                pHeaders = HdrStream0;
                break;
        }

        while (1)
        {
            DWORD dwIdx;
            BOOL bHeadComplete = FALSE;
            if (RunningQ[dwSource].GetNumElements() > 0) {
                RunningQ[dwSource].PeekDequeue(&dwIdx);
                if (pHeaders[dwIdx].dwFlags & WHDR_DONE) {
                    bHeadComplete = TRUE;
                }
            }
            if (!bHeadComplete) {
                break;            		
            }

            RunningQ[dwSource].Dequeue(&dwIdx);
            RunningQ[dwTarget].Enqueue(dwIdx);

            if (RunningQ[dwSource].GetNumElements() == 0) {
                if (g_bDispUnderruns) {
                    OutputMessage(L"-- Underrun on channel %s\n", pszChannels[dwSource]);
                }
            }

            if ( (dwSource == WAVEIN0) || (dwSource == WAVEIN1) ) {

                mmr = waveInUnprepareHeader((HWAVEIN)phWaves[dwSource], pHeaders + dwIdx, sizeof(WAVEHDR));
                if (mmr) {
                    OutputMessage(L"waveInUnprepareHeader(%s) failed %d GetLastError=%d\n", pszChannels[dwSource], mmr, GetLastError());
                    DeinitAudio(hEvents, phWaves, HdrStream0, HdrStream1);
                    return FALSE;
                }

                pHeaders[dwIdx].dwBytesRecorded = 0;
                pHeaders[dwIdx].dwFlags = 0;
                pHeaders[dwIdx].dwLoops = 0;

                mmr = waveOutPrepareHeader((HWAVEOUT)phWaves[dwTarget], pHeaders + dwIdx, sizeof(WAVEHDR));
                if (mmr) {
                    OutputMessage(L"waveOutPrepareHeader(%s) failed %d GetLastError=%d\n", pszChannels[dwTarget], mmr, GetLastError());
                    DeinitAudio(hEvents, phWaves, HdrStream0, HdrStream1);
                    return FALSE;
                }

                mmr = waveOutWrite((HWAVEOUT)phWaves[dwTarget], pHeaders + dwIdx, sizeof(WAVEHDR));
                if (mmr) {
                    OutputMessage(L"waveOutWrite(%s) failed %d GetLastError=%d\n", pszChannels[dwTarget], mmr, GetLastError());
                    DeinitAudio(hEvents, phWaves, HdrStream0, HdrStream1);
                    return FALSE;
                }

            } else {

                mmr = waveOutUnprepareHeader((HWAVEOUT)phWaves[dwSource], pHeaders + dwIdx, sizeof(WAVEHDR));
                if (mmr) {
                    OutputMessage(L"waveOutUnprepareHeader(%s) failed %d GetLastError=%d\n", pszChannels[dwSource], mmr, GetLastError());
                    DeinitAudio(hEvents, phWaves, HdrStream0, HdrStream1);
                    return FALSE;
                }

                pHeaders[dwIdx].dwBufferLength = BYTES_PER_HEADER;
                pHeaders[dwIdx].dwBytesRecorded = 0;
                pHeaders[dwIdx].dwFlags = 0;
                pHeaders[dwIdx].dwLoops = 0;

                mmr = waveInPrepareHeader((HWAVEIN)phWaves[dwTarget], pHeaders + dwIdx, sizeof(WAVEHDR));
                if (mmr) {
                    OutputMessage(L"waveInPrepareHeader(%s) failed %d GetLastError=%d\n", pszChannels[dwTarget], mmr, GetLastError());
                    DeinitAudio(hEvents, phWaves, HdrStream0, HdrStream1);
                    return FALSE;
                }

                mmr = waveInAddBuffer((HWAVEIN)phWaves[dwTarget], pHeaders + dwIdx, sizeof(WAVEHDR));
                if (mmr) {
                    OutputMessage(L"waveInAddBuffer(%s) failed %d GetLastError=%d\n", pszChannels[dwTarget], mmr, GetLastError());
                    DeinitAudio(hEvents, phWaves, HdrStream0, HdrStream1);
                    return FALSE;
                }

            }
        }
    }
    ASSERT(0); // no fall through
    return 0;
}

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
{
	DWORD dwRetVal = ERROR_SUCCESS;
	DWORD dwInDevices;
	DWORD dwOutDevices;

	HANDLE hCurThread = (HANDLE) GetCurrentThreadId();
	CeSetThreadPriority(hCurThread, 156);

	dwInDevices = waveInGetNumDevs();
	dwOutDevices = waveOutGetNumDevs();
	if ( (dwInDevices != 2) || (dwOutDevices != 2) ) {
		OutputMessage(L"There must be two sound devices on the system (InDevices=%d OutDevices=%d)\n", dwInDevices, dwOutDevices);
		dwRetVal = 1;
		goto exit;
	}

	 DoAudioTransfers();	

exit:
	return dwRetVal;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -