📄 dsound_buf.cpp
字号:
/*
//
// 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 + -