📄 dsdriverbuffer.cpp
字号:
//////////////////////////////////////////////////////////////////////////////
/*****************************************************************************
Copyright (c) 1999 Microsoft Corporation
Module Name:
DsPlaybackDriverBuffer.cpp
Abstract:
Implementation file for the DsPlaybackDriverBuffer class.
NOTE: Unlike the desktop, the CE DirectSound version will NOT use
the waveOut API's for emulation. On CE, the waveOut API's (in waveapi.dll)
speak to the underlying audio device driver (wavedev.dll) and so will
DirectSound.
Revision History:
mmaguire 08/19/99 - based on waveOutRenderer
*****************************************************************************/
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// BEGIN INCLUDES
//
// standard includes:
//
//
// where we can find declaration for main class in this file:
//
#include "includes.h"
#include "MemoryBuffer.h"
#include "DsDriverBuffer.h"
//
//
// where we can find declarations needed in this file:
//
//
// END INCLUDES
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
/*****************************************************************************
*****************************************************************************/
//////////////////////////////////////////////////////////////////////////////
DsPlaybackDriverBuffer::DsPlaybackDriverBuffer( HRESULT &hr, USHORT index, volatile struct BusMasterRegisters* pRegs):
CHardwareBuffer(hr, index, pRegs),
m_ulRefCount(1),
m_dsbPlayFlags(0),
m_dwCurrentFrequency(48000)
{
FUNCMSG("DsPlaybackDriverBuffer::DsPlaybackDriverBuffer");
if (FAILED(hr))
return;
// register to receive interrupts
hr = DS_OK;
}
//////////////////////////////////////////////////////////////////////////////
/*****************************************************************************
*****************************************************************************/
//////////////////////////////////////////////////////////////////////////////
DsPlaybackDriverBuffer::~DsPlaybackDriverBuffer()
{
FUNCMSG("DsPlaybackDriverBuffer::~DsPlaybackDriverBuffer");
}
//////////////////////////////////////////////////////////////////////////////
/*****************************************************************************
QueryInterface is where DirectSound will ask us whether we support any
additional capabilities for a buffer. If we support other interfaces
(in other words, if we inherit from another abstract C++ base class)
we should return a pointer to that interfaces here.
*****************************************************************************/
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP DsPlaybackDriverBuffer::QueryInterface (
REFIID pIid,
LPVOID *ppNew )
{
FUNCMSG("DsPlaybackDriverBuffer::QueryInterface");
DEBUGCHK(ppNew != NULL);
#ifdef PARAMETER_VALIDATIONS
if( ! ppNew )
{
ERRMSG("DsPlaybackDriverBuffer::QueryInterface -- invalid pointer");
return DSERR_INVALIDPARAM;
}
#endif
if( IsEqualIID(IID_IUnknown, pIid)
|| IsEqualIID(IID_IDsDriverBuffer,pIid))
{
DEBUGMSG(ZONE_INFO, (TEXT("DsPlaybackDriverBuffer::QueryInterface -- %s\r\n"),
IsEqualIID(IID_IUnknown, pIid)? TEXT("IID_IUnknown")
: TEXT("IID_IDsDriverBuffer")));
// Increase RefCount.
InterlockedIncrement( (LPLONG) &m_ulRefCount );
// Cast ourselves to the type of base class requested.
*ppNew = (IDsDriverBuffer*)this;
return NO_ERROR;
}
else if (IsEqualIID(IID_IDsDriverNotify, pIid))
{
INFMSG("DsPlaybackDriverBuffer::QueryInterface -- IID_IDsDriverNotify");
// Increase RefCount.
InterlockedIncrement( (LPLONG) &m_ulRefCount );
// Cast ourselves to the type of base class requested.
*ppNew = (IDsDriverNotify*)((CHardwareBuffer*)this);
return NO_ERROR;
}
DEBUGMSG(ZONE_INFO,(TEXT("DsPlaybackDriverBuffer::QueryInterface -- unknown IID\r\n")));
*ppNew = NULL;
return DSERR_NOINTERFACE;
}
//////////////////////////////////////////////////////////////////////////////
/*****************************************************************************
AddRef and Release are how other clients of our component tell us that
it is no longer needed. When the RefCount goes to zero, we know we are
not needed, and we will delete ourselves.
*****************************************************************************/
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) DsPlaybackDriverBuffer::AddRef(void)
{
DEBUGMSG(ZONE_REFCOUNT,(TEXT("DsPlaybackDriverBuffer::AddRef previous:%d\r\n"), m_ulRefCount));
return InterlockedIncrement( (LPLONG) &m_ulRefCount );
}
//////////////////////////////////////////////////////////////////////////////
/*****************************************************************************
AddRef and Release are how other clients of our component tell us that
it is no longer needed. When the RefCount goes to zero, we know we are
not needed, and we will delete ourselves.
*****************************************************************************/
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) DsPlaybackDriverBuffer::Release(void)
{
DEBUGMSG(ZONE_REFCOUNT,(TEXT("DsPlaybackDriverBuffer::Release previous=%ld\r\n"), m_ulRefCount));
ULONG ulRefs = InterlockedDecrement( (LPLONG) &m_ulRefCount );
if( ulRefs == 0 )
{
DEBUGMSG(ZONE_REFCOUNT,(TEXT("DsPlaybackDriverBuffer::Release final on 0x%08x\n"), this ));
// Unassociate from the hardware's list of buffers
m_pCX5530->ReleasePlaybackBuffer(m_uChannel);
delete this;
}
return ulRefs;
}
//////////////////////////////////////////////////////////////////////////////
/*****************************************************************************
*****************************************************************************/
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP DsPlaybackDriverBuffer::Lock(
/* [out] */ LPLPVOID ppAudio1,
/* [out] */ LPDWORD pAudioBytes1,
/* [out] */ LPLPVOID ppAudio2,
/* [out] */ LPDWORD pAudioBytes2,
/* [in] */ DWORD dwWriteCursor,
/* [in] */ DWORD dwWriteBytes,
/* [in] */ DWORD dsbLockFlags
)
{
// FUNCMSG3("+DsPlaybackDriverBuffer::Lock dwWriteCursor 0x%x, dwWriteBytes 0x%x, buf %d\r\n",
// dwWriteCursor, dwWriteBytes, m_uChannel);
HRESULT hr = DS_OK;
// Do stuff here to provide access to the actual sound buffer data as requested.
// Return pointers to that data.
CriticalSectionAcquisition csa(&m_csBuffer);
// Buffer is already locked (when allocated). So we'll just return appropriate positions
if(dwWriteBytes > m_ulSize)
{
ERRMSG2("DsPlaybackDriverBuffer::Lock: dwWriteBytes(%d) > m_ulSize (%d)", dwWriteBytes , m_ulSize);
return DSERR_INVALIDPARAM;
}
if (!ppAudio1 || !pAudioBytes1)
{
ERRMSG("DsPlaybackDriverBuffer::Lock: NULL pointer parameter");
return DSERR_INVALIDPARAM;
}
*ppAudio1 = m_pVirtualAddress + dwWriteCursor;
if(dwWriteBytes > m_ulSize - dwWriteCursor) // Wraparound (need two buffers)?
{ // yes
INFMSG3("DsPlaybackDriverBuffer::Lock: 2 buffers\r\n\tdwWriteBytes = %d, m_ulSize = %d, dwWriteCursor = %d",
dwWriteBytes, m_ulSize, dwWriteCursor);
*pAudioBytes1 = m_ulSize - dwWriteCursor;
if(ppAudio2)
{
*ppAudio2 = m_pVirtualAddress;
}
else
{
ERRMSG("DsPlaybackDriverBuffer::Lock:Two buffers needed, but 2nd param is NULL");
}
if(pAudioBytes2)
*pAudioBytes2 = dwWriteBytes - *pAudioBytes1;
//m_dwWritePosition = *pAudioBytes2;
}
else
{ // no, one buffer suffices
// INFMSG("DsPlaybackDriverBuffer::Lock: one buffer");
*pAudioBytes1 = dwWriteBytes;
if(ppAudio2)
*ppAudio2 = NULL;
if(pAudioBytes2)
*pAudioBytes2 = 0;
}
// FUNCMSG2("-DsPlaybackDriverBuffer::Lock: Buffer1: 0x%8.8x, size %lu", *ppAudio1, *pAudioBytes1);
// FUNCMSG2("-DsPlaybackDriverBuffer::Lock: Buffer2: 0x%8.8x, size %lu", ppAudio2?(*ppAudio2):0,
// pAudioBytes2?(*pAudioBytes2):0);
return hr;
}
//////////////////////////////////////////////////////////////////////////////
/*****************************************************************************
*****************************************************************************/
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP DsPlaybackDriverBuffer::Unlock(
/* [in] */ void *pAudio1,
/* [in] */ DWORD dwAudioBytes1,
/* [in] */ void *pAudio2,
/* [in] */ DWORD dwAudioBytes2)
{
// FUNCMSG3("DsDriverBuffer::Unlock pAudio1 %x, pAudio2 %x, buf %d", pAudio1, pAudio2, m_uChannel);
HRESULT hr = DS_OK;
/*
CriticalSectionAcquisition csa(&m_csBuffer);
// The client of this interface is finished with accessing the actual
// data of the buffer.
// Do any tasks your hardware requires here.
// For example, if your hardware supports on-board audio RAM, and this
// is a static buffer, you may have provided a pointer to system RAM
// in the Lock method, the client will have written some data to it,
// and at this point you can move that data to on-board RAM.
// just update positions
// m_dwLastOffsetSize = dwAudioBytes1 + dwAudioBytes2;
if(pAudio2)
m_dwWritePosition = dwAudioBytes2;
else
m_dwWritePosition = ((LPBYTE)pAudio1 - m_pVirtualAddress) + dwAudioBytes1;
if(m_dwWritePosition >= m_ulSize)
m_dwWritePosition = 0;
*/
return hr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -