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

📄 dsound_buf.cpp

📁 audio-video-codecs.rar语音编解码器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
//
//                  INTEL CORPORATION PROPRIETARY INFORMATION
//     This software is supplied under the terms of a license agreement or
//     nondisclosure agreement with Intel Corporation and may not be copied
//     or disclosed except in accordance with the terms of that agreement.
//       Copyright(c) 2003-2006 Intel Corporation. All Rights Reserved.
//
*/

#include "umc_defs.h"

#if defined UMC_ENABLE_DSOUND_AUDIO_RENDER

#include <vm_debug.h>
#include "ipps.h"
#include "vm_debug.h"
#include "dsound_buf.h"

UMC::Status UMC::DSBuffer::Init(const HWND hWnd,
                                const Ipp32u dwBufferSize,
                                const Ipp16u wChannels,
                                const Ipp32u dwFrequency,
                                const Ipp16u wBytesPerSample)
{
    Status umcRes = UMC_OK;

    VM_ASSERT(0 != dwBufferSize);
    VM_ASSERT(0 != wChannels);
    VM_ASSERT(0 != dwFrequency);
    VM_ASSERT(0 != wBytesPerSample);

    Close();

    m_dwInitedBufferSize    = dwBufferSize;
    m_wInitedChannels       = wChannels;
    m_dwInitedFrequency     = dwFrequency;
    m_wInitedBytesPerSample = wBytesPerSample;
    if (UMC_OK == umcRes)
    {
        m_hWnd = hWnd;
        if (NULL == m_hWnd) {    umcRes = UMC_ERR_FAILED;    }
    }

    if (UMC_OK == umcRes)
    {
        HRESULT hRes = DirectSoundCreate8( NULL, &m_pDS, NULL );
        if (FAILED(hRes))
        {
            vm_debug_trace(VM_DEBUG_ERROR, VM_STRING("Failed to initialize DirectSound 8 @DirectSoundRender"));
            umcRes = UMC_ERR_FAILED;
        }
    }

    if (UMC_OK == umcRes && FAILED(m_pDS->SetCooperativeLevel(m_hWnd, DSSCL_PRIORITY)))
    {    umcRes = UMC_ERR_FAILED;}

    DSBUFFERDESC dsbd;
    // Get the primary buffer
    if (UMC_OK == umcRes)
    {
        ippsZero_8u( (Ipp8u*)&dsbd, sizeof(DSBUFFERDESC) );
        dsbd.dwSize        = sizeof(DSBUFFERDESC);
        dsbd.dwFlags       = DSBCAPS_PRIMARYBUFFER;
        dsbd.dwBufferBytes = 0;
        dsbd.lpwfxFormat   = NULL;

        if ( FAILED(m_pDS->CreateSoundBuffer( &dsbd, &m_pDSBPrimary, NULL ) ) )
        {
            vm_debug_trace(VM_DEBUG_ALL, VM_STRING("Failed to create DirectSound primary buffer @Open"));
            umcRes = UMC_ERR_ALLOC;
        }
    }

    //    Set primary buffer format
    WAVEFORMATEX wfx;
    if (UMC_OK == umcRes)
    {
        ippsZero_8u( (Ipp8u*)&wfx, sizeof(WAVEFORMATEX) );
        wfx.wFormatTag      = WAVE_FORMAT_PCM;
        wfx.nChannels       = wChannels;
        wfx.nSamplesPerSec  = dwFrequency;
        wfx.wBitsPerSample  = (Ipp16u)(wBytesPerSample << 3);
        wfx.nBlockAlign     = (Ipp16u) (wfx.wBitsPerSample / 8 * wfx.nChannels);
        wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;

        if ( FAILED(m_pDSBPrimary->SetFormat(&wfx) ) )
        {
            vm_debug_trace(VM_DEBUG_ALL, VM_STRING("Failed to set PCM format for DirectSound primary buffer @Open"));
            umcRes = UMC_ERR_OPEN_FAILED;
        }
    }

    //    Create Secondary buffer
    if (UMC_OK == umcRes)
    {
        dsbd.dwSize        = sizeof(DSBUFFERDESC);
        dsbd.dwFlags       = DSBCAPS_GLOBALFOCUS|DSBCAPS_CTRLVOLUME|
                             DSBCAPS_CTRLFREQUENCY|DSBCAPS_GETCURRENTPOSITION2;
        dsbd.dwBufferBytes = dwBufferSize;
        dsbd.lpwfxFormat   = &wfx;

        if ( FAILED(m_pDS->CreateSoundBuffer( &dsbd, &m_pDSBSecondary, NULL )))
        {
            vm_debug_trace(VM_DEBUG_ALL, VM_STRING("Failed to create DirectSound secondary buffer @Open"));
            umcRes = UMC_ERR_ALLOC;
        }
    }

    if (UMC_OK == umcRes)
    {
        void *lock1_ptr, *lock2_ptr;
        Ipp32u lock1_bytes, lock2_bytes;
        if (FAILED(m_pDSBSecondary->Lock(0, m_dwDSBufferSize,
                                         &lock1_ptr, (LPDWORD)&lock1_bytes,
                                         &lock2_ptr, (LPDWORD)&lock2_bytes,
                                         DSBLOCK_ENTIREBUFFER)))
        {
            vm_debug_trace(VM_DEBUG_ALL, VM_STRING("Failed to lock DirectSound secondary buffer @Open"));
            umcRes = UMC_ERR_OPEN_FAILED;
        }
        else
        {
            ippsZero_8u((Ipp8u*)lock1_ptr,lock1_bytes);
            m_pDSBSecondary->Unlock(lock1_ptr,lock1_bytes,lock2_ptr,0);
        }
    }

    DSCAPS   dscaps = {0};
    if (UMC_OK == umcRes)
    {
        ippsZero_8u( (Ipp8u*)&dscaps, sizeof(DSCAPS) );
        dscaps.dwSize = sizeof(DSCAPS);
        if (FAILED(m_pDS->GetCaps(&dscaps)))
        {    umcRes = UMC_ERR_FAILED;    }
    }

    if(UMC_OK == umcRes)
    {
        m_dfCompensation = (dscaps.dwFlags & DSCAPS_EMULDRIVER) ? 0.020 : 0.005;
        m_dfNorm = 1.0/dwFrequency/wBytesPerSample/wChannels;
        m_dwNextWriteOffset = 0;
    }

    if (UMC_OK == umcRes)
    {
        m_dwDSBufferSize = dwBufferSize;
        m_bPausedWaitingData = true;
    }
    else
    {    Close();    }
    return umcRes;
}

UMC::Status UMC::DSBuffer::GetPlayPos(Ipp32u& rdwPos)
{
    if (!m_pDSBSecondary)
    {
        return UMC_ERR_FAILED;
    }
    m_MutAccess.Lock();
    Status umcRes = (m_pDSBSecondary) ? UMC_OK : UMC_ERR_NOT_INITIALIZED;
    if (UMC_OK == umcRes &&
        FAILED(m_pDSBSecondary->GetCurrentPosition((LPDWORD)&rdwPos, NULL)))
    {
        rdwPos = 0xFFFFFFFF;
        umcRes = UMC_ERR_FAILED;
    }
    m_MutAccess.Unlock();
    return umcRes;
}

UMC::Status UMC::DSBuffer::GetWritePos(Ipp32u& rdwPos)
{
    if (!m_pDSBSecondary)
    {
        return UMC_ERR_FAILED;
    }
    m_MutAccess.Lock();
    Status umcRes = (m_pDSBSecondary) ? UMC_OK : UMC_ERR_NOT_INITIALIZED;
    if (UMC_OK == umcRes &&
        FAILED(m_pDSBSecondary->GetCurrentPosition(NULL, (LPDWORD)&rdwPos)))
    {
        rdwPos = 0xFFFFFFFF;
        umcRes = UMC_ERR_FAILED;
    }
    m_MutAccess.Unlock();
    return umcRes;
}

UMC::Status UMC::DSBuffer::CopyDataToBuffer(Ipp8u* pucData,
                                            Ipp32u dwLength,
                                            Ipp32u& rdwBytesWrote)
{
    void *lock1_ptr = NULL;
    void *lock2_ptr = NULL;
    Ipp32u lock1_bytes = 0;
    Ipp32u lock2_bytes = 0;

    HRESULT hRes = DS_OK;

    if (!m_pDSBSecondary)
    {
        return UMC_ERR_FAILED;
    }

    if (dwLength == 0)
    {
      return UMC_OK;
    }

    m_MutAccess.Lock();

    Status umcRes = (NULL != m_pDSBSecondary) ? UMC_OK : UMC_ERR_NOT_INITIALIZED;

    if (UMC_OK == umcRes) {
        hRes = m_pDSBSecondary->Lock(m_dwNextWriteOffset,
                                     IPP_MIN(dwLength,m_dwDSBufferSize),
                                     &lock1_ptr, (LPDWORD)&lock1_bytes,
                                     &lock2_ptr, (LPDWORD)&lock2_bytes, 0);
        if (DSERR_BUFFERLOST == hRes) {
            m_pDSBSecondary->Restore();
            hRes = m_pDSBSecondary->Lock(m_dwNextWriteOffset,
                                         IPP_MIN(dwLength,m_dwDSBufferSize),
                                         &lock1_ptr, (LPDWORD)&lock1_bytes,
                                         &lock2_ptr, (LPDWORD)&lock2_bytes, 0);
        }
        if (DS_OK != hRes) {    umcRes = UMC_ERR_FAILED;    }
    }

    if (UMC_OK == umcRes)
    {
        ippsCopy_8u(pucData, (Ipp8u*)lock1_ptr, lock1_bytes);
        hRes = m_pDSBSecondary->Unlock(lock1_ptr, lock1_bytes, lock2_ptr,0);
        if (DS_OK != hRes) {    umcRes = UMC_ERR_FAILED;    }
    }

    if (UMC_OK == umcRes) {
        m_dwNextWriteOffset = (m_dwNextWriteOffset + lock1_bytes) % m_dwDSBufferSize;
        rdwBytesWrote = lock1_bytes;
    }

/*
    if (UMC_OK == umcRes && m_bPausedWaitingData &&
        (m_dwDSBufferSize /2 < m_dwNextWriteOffset ||
        (0 == m_dwNextWriteOffset && 0 != rdwBytesWrote)))
*/
    if (UMC_OK == umcRes && m_bPausedWaitingData && rdwBytesWrote)
    {
        if (FAILED(m_pDSBSecondary->Play( 0, 0, DSBPLAY_LOOPING)))
        {    umcRes = UMC_ERR_FAILED;    }
        else
        {    m_bPausedWaitingData = false;    }
    }
    m_MutAccess.Unlock();

    return umcRes;
}

UMC::Status UMC::DSBuffer::CopyZerosToBuffer(Ipp32u dwLength)
{
    void *lock1_ptr = NULL;
    void *lock2_ptr = NULL;
    Ipp32u lock1_bytes = 0;
    Ipp32u lock2_bytes = 0;

    HRESULT hRes = DS_OK;

    if (!m_pDSBSecondary) {
        return UMC_ERR_FAILED;
    }

    if (dwLength == 0)
      dwLength = m_dwDSBufferSize;

    m_MutAccess.Lock();

    Status umcRes = (NULL != m_pDSBSecondary) ? UMC_OK : UMC_ERR_NOT_INITIALIZED;

    if (UMC_OK == umcRes) {
        hRes = m_pDSBSecondary->Lock(m_dwNextWriteOffset,
                                     IPP_MIN(dwLength,m_dwDSBufferSize),
                                     &lock1_ptr, (LPDWORD)&lock1_bytes,
                                     &lock2_ptr, (LPDWORD)&lock2_bytes, 0);
        if (DSERR_BUFFERLOST == hRes) {
            m_pDSBSecondary->Restore();
            hRes = m_pDSBSecondary->Lock(m_dwNextWriteOffset,
                                         IPP_MIN(dwLength,m_dwDSBufferSize),
                                         &lock1_ptr, (LPDWORD)&lock1_bytes,

⌨️ 快捷键说明

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