📄 buffer.c
字号:
if (p2) probably_valid_to = (((LPBYTE)p2)-This->buffer->memory) + x2;
else probably_valid_to = (((LPBYTE)p1)-This->buffer->memory) + x1;
probably_valid_to %= This->buflen;
if ((probably_valid_to == 0) && ((x1+x2) == This->buflen) &&
((This->state == STATE_STARTING) ||
(This->state == STATE_PLAYING)))
/* see IDirectSoundBufferImpl_Lock */
probably_valid_to = (DWORD)-1;
This->probably_valid_to = probably_valid_to;
}
LeaveCriticalSection(&(This->lock));
/* **** */
TRACE("probably_valid_to=%ld\n", This->probably_valid_to);
return hres;
}
static HRESULT WINAPI IDirectSoundBufferImpl_Restore(
LPDIRECTSOUNDBUFFER8 iface
) {
IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
FIXME("(%p):stub\n",This);
return DS_OK;
}
static HRESULT WINAPI IDirectSoundBufferImpl_GetFrequency(
LPDIRECTSOUNDBUFFER8 iface,LPDWORD freq
) {
IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
TRACE("(%p,%p)\n",This,freq);
if (freq == NULL) {
WARN("invalid parameter: freq = NULL\n");
return DSERR_INVALIDPARAM;
}
*freq = This->freq;
TRACE("-> %ld\n", *freq);
return DS_OK;
}
static HRESULT WINAPI IDirectSoundBufferImpl_SetFX(
LPDIRECTSOUNDBUFFER8 iface,DWORD dwEffectsCount,LPDSEFFECTDESC pDSFXDesc,LPDWORD pdwResultCodes
) {
IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
DWORD u;
FIXME("(%p,%lu,%p,%p): stub\n",This,dwEffectsCount,pDSFXDesc,pdwResultCodes);
if (pdwResultCodes)
for (u=0; u<dwEffectsCount; u++) pdwResultCodes[u] = DSFXR_UNKNOWN;
WARN("control unavailable\n");
return DSERR_CONTROLUNAVAIL;
}
static HRESULT WINAPI IDirectSoundBufferImpl_AcquireResources(
LPDIRECTSOUNDBUFFER8 iface,DWORD dwFlags,DWORD dwEffectsCount,LPDWORD pdwResultCodes
) {
IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
DWORD u;
FIXME("(%p,%08lu,%lu,%p): stub\n",This,dwFlags,dwEffectsCount,pdwResultCodes);
if (pdwResultCodes)
for (u=0; u<dwEffectsCount; u++) pdwResultCodes[u] = DSFXR_UNKNOWN;
WARN("control unavailable\n");
return DSERR_CONTROLUNAVAIL;
}
static HRESULT WINAPI IDirectSoundBufferImpl_GetObjectInPath(
LPDIRECTSOUNDBUFFER8 iface,REFGUID rguidObject,DWORD dwIndex,REFGUID rguidInterface,LPVOID* ppObject
) {
IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
FIXME("(%p,%s,%lu,%s,%p): stub\n",This,debugstr_guid(rguidObject),dwIndex,debugstr_guid(rguidInterface),ppObject);
WARN("control unavailable\n");
return DSERR_CONTROLUNAVAIL;
}
static HRESULT WINAPI IDirectSoundBufferImpl_Initialize(
LPDIRECTSOUNDBUFFER8 iface,LPDIRECTSOUND dsound,LPCDSBUFFERDESC dbsd
) {
IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
FIXME("(%p,%p,%p):stub\n",This,dsound,dbsd);
DPRINTF("Re-Init!!!\n");
WARN("already initialized\n");
return DSERR_ALREADYINITIALIZED;
}
static HRESULT WINAPI IDirectSoundBufferImpl_GetCaps(
LPDIRECTSOUNDBUFFER8 iface,LPDSBCAPS caps
) {
IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
TRACE("(%p)->(%p)\n",This,caps);
if (caps == NULL) {
WARN("invalid parameter: caps == NULL\n");
return DSERR_INVALIDPARAM;
}
if (caps->dwSize < sizeof(*caps)) {
WARN("invalid parameter: caps->dwSize = %ld < %d\n",caps->dwSize, sizeof(*caps));
return DSERR_INVALIDPARAM;
}
caps->dwFlags = This->dsbd.dwFlags;
if (This->hwbuf) caps->dwFlags |= DSBCAPS_LOCHARDWARE;
else caps->dwFlags |= DSBCAPS_LOCSOFTWARE;
caps->dwBufferBytes = This->buflen;
/* This value represents the speed of the "unlock" command.
As unlock is quite fast (it does not do anything), I put
4096 ko/s = 4 Mo / s */
/* FIXME: hwbuf speed */
caps->dwUnlockTransferRate = 4096;
caps->dwPlayCpuOverhead = 0;
return DS_OK;
}
static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface(
LPDIRECTSOUNDBUFFER8 iface,REFIID riid,LPVOID *ppobj
) {
IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
if (ppobj == NULL) {
WARN("invalid parameter\n");
return E_INVALIDARG;
}
*ppobj = NULL; /* assume failure */
if ( IsEqualGUID(riid, &IID_IUnknown) ||
IsEqualGUID(riid, &IID_IDirectSoundBuffer) ||
IsEqualGUID(riid, &IID_IDirectSoundBuffer8) ) {
if (!This->dsb)
SecondaryBufferImpl_Create(This, &(This->dsb));
if (This->dsb) {
IDirectSoundBuffer8_AddRef((LPDIRECTSOUNDBUFFER8)This->dsb);
*ppobj = This->dsb;
return S_OK;
}
WARN("IID_IDirectSoundBuffer\n");
return E_NOINTERFACE;
}
if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) {
if (!This->notify)
IDirectSoundNotifyImpl_Create(This, &(This->notify));
if (This->notify) {
IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY)This->notify);
*ppobj = This->notify;
return S_OK;
}
WARN("IID_IDirectSoundNotify\n");
return E_NOINTERFACE;
}
if ( IsEqualGUID( &IID_IDirectSound3DBuffer, riid ) ) {
if (!This->ds3db)
IDirectSound3DBufferImpl_Create(This, &(This->ds3db));
if (This->ds3db) {
IDirectSound3DBuffer_AddRef((LPDIRECTSOUND3DBUFFER)This->ds3db);
*ppobj = This->ds3db;
return S_OK;
}
WARN("IID_IDirectSound3DBuffer\n");
return E_NOINTERFACE;
}
if ( IsEqualGUID( &IID_IDirectSound3DListener, riid ) ) {
ERR("app requested IDirectSound3DListener on secondary buffer\n");
return E_NOINTERFACE;
}
if ( IsEqualGUID( &IID_IKsPropertySet, riid ) ) {
if (!This->iks)
IKsBufferPropertySetImpl_Create(This, &(This->iks));
if (This->iks) {
IKsPropertySet_AddRef((LPKSPROPERTYSET)This->iks);
*ppobj = This->iks;
return S_OK;
}
WARN("IID_IKsPropertySet\n");
return E_NOINTERFACE;
}
FIXME( "Unknown IID %s\n", debugstr_guid( riid ) );
return E_NOINTERFACE;
}
static const IDirectSoundBuffer8Vtbl dsbvt =
{
IDirectSoundBufferImpl_QueryInterface,
IDirectSoundBufferImpl_AddRef,
IDirectSoundBufferImpl_Release,
IDirectSoundBufferImpl_GetCaps,
IDirectSoundBufferImpl_GetCurrentPosition,
IDirectSoundBufferImpl_GetFormat,
IDirectSoundBufferImpl_GetVolume,
IDirectSoundBufferImpl_GetPan,
IDirectSoundBufferImpl_GetFrequency,
IDirectSoundBufferImpl_GetStatus,
IDirectSoundBufferImpl_Initialize,
IDirectSoundBufferImpl_Lock,
IDirectSoundBufferImpl_Play,
IDirectSoundBufferImpl_SetCurrentPosition,
IDirectSoundBufferImpl_SetFormat,
IDirectSoundBufferImpl_SetVolume,
IDirectSoundBufferImpl_SetPan,
IDirectSoundBufferImpl_SetFrequency,
IDirectSoundBufferImpl_Stop,
IDirectSoundBufferImpl_Unlock,
IDirectSoundBufferImpl_Restore,
IDirectSoundBufferImpl_SetFX,
IDirectSoundBufferImpl_AcquireResources,
IDirectSoundBufferImpl_GetObjectInPath
};
HRESULT WINAPI IDirectSoundBufferImpl_Create(
IDirectSoundImpl *ds,
IDirectSoundBufferImpl **pdsb,
LPCDSBUFFERDESC dsbd)
{
IDirectSoundBufferImpl *dsb;
LPWAVEFORMATEX wfex = dsbd->lpwfxFormat;
HRESULT err = DS_OK;
DWORD capf = 0;
int use_hw, alloc_size, cp_size;
TRACE("(%p,%p,%p)\n",ds,pdsb,dsbd);
if (dsbd->dwBufferBytes < DSBSIZE_MIN || dsbd->dwBufferBytes > DSBSIZE_MAX) {
WARN("invalid parameter: dsbd->dwBufferBytes = %ld\n", dsbd->dwBufferBytes);
*pdsb = NULL;
return DSERR_INVALIDPARAM; /* FIXME: which error? */
}
dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
if (dsb == 0) {
WARN("out of memory\n");
*pdsb = NULL;
return DSERR_OUTOFMEMORY;
}
TRACE("Created buffer at %p\n", dsb);
dsb->ref = 0;
dsb->dsb = 0;
dsb->dsound = ds;
dsb->lpVtbl = &dsbvt;
dsb->iks = NULL;
/* size depends on version */
CopyMemory(&dsb->dsbd, dsbd, dsbd->dwSize);
/* variable sized struct so calculate size based on format */
if (wfex->wFormatTag == WAVE_FORMAT_PCM) {
alloc_size = sizeof(WAVEFORMATEX);
cp_size = sizeof(PCMWAVEFORMAT);
} else
alloc_size = cp_size = sizeof(WAVEFORMATEX) + wfex->cbSize;
dsb->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,alloc_size);
if (dsb->pwfx == NULL) {
WARN("out of memory\n");
HeapFree(GetProcessHeap(),0,dsb);
*pdsb = NULL;
return DSERR_OUTOFMEMORY;
}
CopyMemory(dsb->pwfx, wfex, cp_size);
if (dsbd->dwBufferBytes % dsbd->lpwfxFormat->nBlockAlign)
dsb->buflen = dsbd->dwBufferBytes +
(dsbd->lpwfxFormat->nBlockAlign -
(dsbd->dwBufferBytes % dsbd->lpwfxFormat->nBlockAlign));
else
dsb->buflen = dsbd->dwBufferBytes;
dsb->freq = dsbd->lpwfxFormat->nSamplesPerSec;
dsb->notify = NULL;
dsb->notifies = NULL;
dsb->nrofnotifies = 0;
dsb->hwnotify = 0;
/* Check necessary hardware mixing capabilities */
if (wfex->nChannels==2) capf |= DSCAPS_SECONDARYSTEREO;
else capf |= DSCAPS_SECONDARYMONO;
if (wfex->wBitsPerSample==16) capf |= DSCAPS_SECONDARY16BIT;
else capf |= DSCAPS_SECONDARY8BIT;
use_hw = (ds->device->drvcaps.dwFlags & capf) == capf;
TRACE("use_hw = 0x%08x, capf = 0x%08lx, ds->drvcaps.dwFlags = 0x%08lx\n", use_hw, capf, ds->device->drvcaps.dwFlags);
/* FIXME: check hardware sample rate mixing capabilities */
/* FIXME: check app hints for software/hardware buffer (STATIC, LOCHARDWARE, etc) */
/* FIXME: check whether any hardware buffers are left */
/* FIXME: handle DSDHEAP_CREATEHEAP for hardware buffers */
/* Allocate an empty buffer */
dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
if (dsb->buffer == NULL) {
WARN("out of memory\n");
HeapFree(GetProcessHeap(),0,dsb->pwfx);
HeapFree(GetProcessHeap(),0,dsb);
*pdsb = NULL;
return DSERR_OUTOFMEMORY;
}
/* Allocate system memory for buffer if applicable */
if ((ds->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) || !use_hw) {
dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen);
if (dsb->buffer->memory == NULL) {
WARN("out of memory\n");
HeapFree(GetProcessHeap(),0,dsb->pwfx);
HeapFree(GetProcessHeap(),0,dsb->buffer);
HeapFree(GetProcessHeap(),0,dsb);
*pdsb = NULL;
return DSERR_OUTOFMEMORY;
}
dsb->buffer->ref = 1;
FillMemory(dsb->buffer->memory, dsb->buflen, dsbd->lpwfxFormat->wBitsPerSample == 8 ? 128 : 0);
}
/* Allocate the hardware buffer */
if (use_hw) {
err = IDsDriver_CreateSoundBuffer(ds->device->driver,wfex,dsbd->dwFlags,0,
&(dsb->buflen),&(dsb->buffer->memory),
(LPVOID*)&(dsb->hwbuf));
/* fall back to software buffer on failure */
if (err != DS_OK) {
TRACE("IDsDriver_CreateSoundBuffer failed, falling back to software buffer\n");
use_hw = 0;
if (ds->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen);
if (dsb->buffer->memory == NULL) {
WARN("out of memory\n");
HeapFree(GetProcessHeap(),0,dsb->buffer);
HeapFree(GetProcessHeap(),0,dsb->pwfx);
HeapFree(GetProcessHeap(),0,dsb);
*pdsb = NULL;
return DSERR_OUTOFMEMORY;
}
dsb->buffer->ref = 1;
FillMemory(dsb->buffer->memory, dsb->buflen, dsbd->lpwfxFormat->wBitsPerSample == 8 ? 128 : 0);
}
err = DS_OK;
}
}
/* calculate fragment size and write lead */
DSOUND_RecalcFormat(dsb);
/* It's not necessary to initialize values to zero since */
/* we allocated this structure with HEAP_ZERO_MEMORY... */
dsb->playpos = 0;
dsb->buf_mixpos = 0;
dsb->state = STATE_STOPPED;
dsb->freqAdjust = (dsb->freq << DSOUND_FREQSHIFT) /
ds->device->pwfx->nSamplesPerSec;
dsb->nAvgBytesPerSec = dsb->freq *
dsbd->lpwfxFormat->nBlockAlign;
if (dsb->dsbd.dwFlags & DSBCAPS_CTRL3D) {
dsb->ds3db_ds3db.dwSize = sizeof(DS3DBUFFER);
dsb->ds3db_ds3db.vPosition.x = 0.0;
dsb->ds3db_ds3db.vPosition.y = 0.0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -