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

📄 captureecho.cpp

📁 Windows CE .Net 下面 DIRECT SOUND编程的经典实例。对于初学Windows 平台下DIRECT SOUND编程技术的程序员颇具借鉴意义!
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    CheckHRESULT(hr, "IDirectSoundNotify::SetNotificationPositions", return);

    hr = piDSCB->Start(DSCBSTART_LOOPING);
    CheckHRESULT(hr, "IDirectSoundCaptureBuffer::Start(DSCBSTART_LOOPING)", return);

    dwStartTime = GetTickCount();
    dwTimeElapsed = 0;
    dwLastReadPosition = 0;
    dwWritePosition = 0;
    fPlaying = false;

    while (m_dwTimeout>dwTimeElapsed && dwWaitResult != WAIT_TIMEOUT)
    {
        dwWaitResult = WaitForMultipleObjects(nNumStreamingBlocks, (const HANDLE*) rhEvents, FALSE, 2 * m_dwDelay);

		//dbgout(TEXT("wait returns %d\n"), dwWaitResult);

        do
        {
            // Wait until portion of the capture buffer we want to lock is available.
            // If notifications are sent correctly this loop will execute only once.
            hr = piDSCB->GetCurrentPosition(&dwTmp, &dwReadPosition);
            CheckHRESULT(hr, "IDirectSoundCapture::GetCurrentPosition", return);

            // adjust the read position if we're wrapped around the end of the buffer
            if (dwReadPosition<dwLastReadPosition)
                dwReadPosition+=dwBufferSize;
        } while (dwLastReadPosition+dwBlockSize > dwReadPosition);

        // Note: Some types of audio systems use different clocks for capture and playback,
        // which can cause the streaming rate from the capture buffer to be slightly
        // different than the streaming rate into the playback buffer.  If that is the case,
        // there will eventually be a locking conflict when we try to lock the playback buffer.
        // This test will stop the audio capture if this condition occurs.
        // If this condition happens on your HW, it will happen sooner with small block sizes.
        // Using the -t and -d options, you can determine how large a block is needed to
        // achieve a reasonable mean time before failure.
#       ifdef DEBUG
        if (fPlaying)
        {
            // Get the play position
            DWORD dwCurrentPlayPosition, dwCurrentWritePosition;
            hr = piDSB->GetCurrentPosition(&dwCurrentPlayPosition, &dwCurrentWritePosition);
            CheckHRESULT(hr, "IDirectSoundBuffer::GetCurrentPosition", return);

            if (dwCurrentWritePosition<dwCurrentPlayPosition)
                dwCurrentWritePosition += dwBufferSize;

            if ((dwCurrentPlayPosition>=dwWritePosition && dwCurrentPlayPosition<=dwWritePosition+dwBlockSize)
                || (dwCurrentWritePosition>=dwWritePosition && dwCurrentWritePosition<=dwWritePosition+dwBlockSize))
            {
                dbgout(TEXT("IDirectSoundBuffer::Lock collided with the play position of the playback buffer at time %lums.\n"), GetTickCount()-dwStartTime);
                break;
            }
        }
#       endif

        //
        // Make sure that the write cursor is on a DWORD BOUNDARY.
        // This prevents copying audio data from an even address to an
        // odd address, or vice versa, which can lead to static or
        // white noise in the final audio.
        //
        // Without this fix, the application can sometimes copy 16-bit data
        // from an odd address to an even address, which has the effect of
        // swapping the high and low bytes of 16-bit PCM samples.
        //
        dwWritePosition &= (DWORD) ~3;

        // Lock the first half of the capture buffer and the next block in the playback buffer
        hr = piDSCB->Lock(dwLastReadPosition, dwBlockSize,
                          reinterpret_cast<LPVOID*>(&pbAudioCapturePtr0), &dwAudioCaptureBytes0,
                          reinterpret_cast<LPVOID*>(&pbAudioCapturePtr1), &dwAudioCaptureBytes1,
                          0);
        CheckHRESULT(hr, "IDirectSoundCaptureBuffer::Lock", return);

        // Lock the next block of the playback buffer
        hr = piDSB->Lock(dwWritePosition, dwBlockSize,
                         (LPVOID*)&pbAudioPlaybackPtr0, &dwAudioPlaybackBytes0,
                         (LPVOID*)&pbAudioPlaybackPtr1, &dwAudioPlaybackBytes1,
                         0);
        CheckHRESULT(hr, "IDirectSoundBuffer::Lock", return);

        // Sanity check
        ASSERT(dwAudioCaptureBytes0+dwAudioCaptureBytes1==dwBlockSize);
        ASSERT(dwAudioPlaybackBytes0+dwAudioPlaybackBytes1==dwBlockSize);

        // Copy the capture data to the locked portion of the playback buffer
        if (dwAudioPlaybackBytes0 <= dwAudioCaptureBytes0)
        {
            dwTmp = dwAudioCaptureBytes0-dwAudioPlaybackBytes0;
            memcpy(pbAudioPlaybackPtr0, pbAudioCapturePtr0, dwAudioPlaybackBytes0);
            if (dwTmp>0)
            {
                memcpy(pbAudioPlaybackPtr1, pbAudioCapturePtr0 + dwAudioPlaybackBytes0, dwTmp);
                if (dwAudioCaptureBytes1)
                    memcpy(pbAudioPlaybackPtr1+dwTmp, pbAudioCapturePtr1, dwAudioCaptureBytes1);
            }
        }
        else
        {
            memcpy(pbAudioPlaybackPtr0, pbAudioCapturePtr0, dwAudioCaptureBytes0);
            dwTmp = dwAudioPlaybackBytes0-dwAudioCaptureBytes0;
            if (dwTmp>0)
            {
                memcpy(pbAudioPlaybackPtr0+dwAudioCaptureBytes0, pbAudioCapturePtr1, dwTmp);
                if (dwAudioCaptureBytes1>dwTmp)
                    memcpy(pbAudioPlaybackPtr1, pbAudioCapturePtr1+dwTmp, dwAudioCaptureBytes1-dwTmp);
            }
        }

        // Unlock the buffers
        hr = piDSB->Unlock((LPVOID*)pbAudioPlaybackPtr0, dwAudioPlaybackBytes0,
                           (LPVOID*)pbAudioPlaybackPtr1, dwAudioPlaybackBytes1);
        CheckHRESULT(hr, "IDirectSoundBuffer::Unlock", return);

        hr = piDSCB->Unlock((LPVOID*)pbAudioCapturePtr0, dwAudioCaptureBytes0,
                            (LPVOID*)pbAudioCapturePtr1, dwAudioCaptureBytes1);
        CheckHRESULT(hr, "IDirectSoundCaptureBuffer::Unlock", return);

        if (!fPlaying && dwWritePosition != 0)
        {
            hr = piDSB->Play(0,0,DSBPLAY_LOOPING);
            CheckHRESULT(hr, "IDirectSoundBuffer::Play", return);
            fPlaying=true;
        }

        dwLastReadPosition = (dwLastReadPosition+dwBlockSize)%dwBufferSize;
        dwWritePosition = (dwWritePosition+dwBlockSize)%dwBufferSize;
        dwTimeElapsed = GetTickCount()-dwStartTime;
    }


    // clear the next playback block to prevent playing noise when we reach the end
    // of the last block
    hr = piDSB->Lock(dwWritePosition, dwBlockSize,
                     (LPVOID*)&pbAudioPlaybackPtr0, &dwAudioPlaybackBytes0,
                     (LPVOID*)&pbAudioPlaybackPtr1, &dwAudioPlaybackBytes1,
                     0);
    CheckHRESULT(hr, "IDirectSoundBuffer::Lock", return);

    memset(pbAudioPlaybackPtr0, 0, dwAudioPlaybackBytes0);
    if (pbAudioPlaybackPtr1)
        memset(pbAudioPlaybackPtr1, 0, dwAudioPlaybackBytes1);

    hr = piDSB->Unlock((LPVOID*)pbAudioPlaybackPtr0, dwAudioPlaybackBytes0,
                       (LPVOID*)pbAudioPlaybackPtr1, dwAudioPlaybackBytes1);
    CheckHRESULT(hr, "IDirectSoundBuffer::Unlock", return);

    // Wait until the next notification is sent. We're no longer streaming, but we're
    // going to continue to run the capture buffer to use its notification
    dwTmp = ((dwWritePosition/dwBlockSize)+nNumStreamingBlocks+1)%nNumStreamingBlocks;
    dwWaitResult = WaitForMultipleObjects(1, (const HANDLE*) &rhEvents[dwTmp], FALSE, m_dwDelay);

    hr = piDSB->Stop();
    CheckHRESULT(hr, "IDirectSoundBuffer::Stop", return);

    hr = piDSCB->Stop();
    CheckHRESULT(hr, "IDirectSoundCaptureBuffer::Stop", return);

    dbgout(TEXT("Capturing completed.\n"));

}

void CCaptureEchoApplication::DisplayUsage()
{
    dbgout(TEXT("\nCaptureEcho Usage:\n\tCaptureEcho [-f format] [-d delay] [-t timeout]\n"));
    dbgout(TEXT("\t-f capture format index (0-11) (See readme.txt)\n"));
    dbgout(TEXT("\t-d approximate delay in milliseconds, default = %lu\n"), DEFAULT_DELAY);
    dbgout(TEXT("\t   NOTE: Delay must be at least 500ms.\n"));
    dbgout(TEXT("\t-t timeout in seconds, default = %lu\n"), DEFAULT_TIMEOUT/1000);
    dbgout(TEXT("\t   NOTE: Timeout must be greater than 4 times the delay.\n"));
    dbgout(TEXT("\t         It will also be converted to ms and quantized to the delay.\n"));
}

bool CCaptureEchoApplication::ProcessCommandLine()
{
    LPCTSTR pszHelpOption = _tcsstr(m_pszCommandLine, TEXT("-?"));
    if (pszHelpOption==NULL) LPCTSTR pszHelpOption = _tcsstr(m_pszCommandLine, TEXT("-h"));
    LPCTSTR pszTimeOption   = _tcsstr(m_pszCommandLine, TEXT("-t"));
    LPCTSTR pszDelayOption  = _tcsstr(m_pszCommandLine, TEXT("-d"));
    LPCTSTR pszFormatOption = _tcsstr(m_pszCommandLine, TEXT("-f"));

    if (pszHelpOption!=NULL)
    {
        DisplayUsage();
        return false;
    }

    if (pszDelayOption!=NULL)
    {
        pszDelayOption+=2;

        // Skip Whitespace
        while (_istspace(*pszDelayOption))
            pszDelayOption++;

        m_dwDelay = _ttoi(pszDelayOption);

        if (m_dwDelay<500)
        {
            DisplayUsage();
            return false;
        }
    }

    if (pszTimeOption!=NULL)
    {
        pszTimeOption+=2;

        // Skip Whitespace
        while (_istspace(*pszTimeOption))
            pszTimeOption++;

        m_dwTimeout = _ttoi(pszTimeOption) * 1000;

        if (m_dwTimeout==0)
        {
            DisplayUsage();
            return false;
        }

        if (m_dwTimeout<4*m_dwDelay)
        {
            dbgout(TEXT("ERROR: Timeout must be at least 4 times the delay.\n"));
            DisplayUsage();
            return false;
        }

        m_dwTimeout -= m_dwTimeout%m_dwDelay;
    }

    if (pszFormatOption!=NULL)
    {
        pszFormatOption+=2;

        // Skip Whitespace
        while (_istspace(*pszFormatOption))
            pszFormatOption++;

        m_dwFormatIndex = _ttoi(pszFormatOption);

        if (m_dwFormatIndex > NUM_SUPPORTED_CAPTURE_FORMATS ||
            m_dwFormatIndex < 0)
        {
            DisplayUsage();
            return false;
        }
    }

    return true;
}

⌨️ 快捷键说明

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