* Sync to Wine 1.3.29 in an attempt to get it working again.
* Dedicated to Daniel Reimer.
* Thanks to Sylvain for pinpointing this version.
svn path=/trunk/; revision=64379
target_link_libraries(dsound mingwex)
endif()
-add_importlibs(dsound winmm ole32 advapi32 user32 msvcrt kernel32 ntdll)
+add_importlibs(dsound winmm advapi32 msvcrt kernel32 ntdll)
add_cd_file(TARGET dsound DESTINATION reactos/system32 FOR all)
* IDirectSoundNotify
*/
-static inline struct IDirectSoundBufferImpl *impl_from_IDirectSoundNotify(IDirectSoundNotify *iface)
+struct IDirectSoundNotifyImpl
{
- return CONTAINING_RECORD(iface, struct IDirectSoundBufferImpl, IDirectSoundNotify_iface);
-}
+ /* IUnknown fields */
+ const IDirectSoundNotifyVtbl *lpVtbl;
+ LONG ref;
+ IDirectSoundBufferImpl* dsb;
+};
-static HRESULT WINAPI IDirectSoundNotifyImpl_QueryInterface(IDirectSoundNotify *iface, REFIID riid,
- void **ppobj)
-{
- IDirectSoundBufferImpl *This = impl_from_IDirectSoundNotify(iface);
+static HRESULT IDirectSoundNotifyImpl_Create(IDirectSoundBufferImpl *dsb,
+ IDirectSoundNotifyImpl **pdsn);
+static HRESULT IDirectSoundNotifyImpl_Destroy(IDirectSoundNotifyImpl *pdsn);
+
+static HRESULT WINAPI IDirectSoundNotifyImpl_QueryInterface(
+ LPDIRECTSOUNDNOTIFY iface,REFIID riid,LPVOID *ppobj
+) {
+ IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface;
+ TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
- TRACE("(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj);
+ if (This->dsb == NULL) {
+ WARN("invalid parameter\n");
+ return E_INVALIDARG;
+ }
- return IDirectSoundBuffer8_QueryInterface(&This->IDirectSoundBuffer8_iface, riid, ppobj);
+ return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER)This->dsb, riid, ppobj);
}
-static ULONG WINAPI IDirectSoundNotifyImpl_AddRef(IDirectSoundNotify *iface)
+static ULONG WINAPI IDirectSoundNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSoundNotify(iface);
- ULONG ref = InterlockedIncrement(&This->refn);
-
+ IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface;
+ ULONG ref = InterlockedIncrement(&(This->ref));
TRACE("(%p) ref was %d\n", This, ref - 1);
-
- if(ref == 1)
- InterlockedIncrement(&This->numIfaces);
-
return ref;
}
-static ULONG WINAPI IDirectSoundNotifyImpl_Release(IDirectSoundNotify *iface)
+static ULONG WINAPI IDirectSoundNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSoundNotify(iface);
- ULONG ref = InterlockedDecrement(&This->refn);
-
+ IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface;
+ ULONG ref = InterlockedDecrement(&(This->ref));
TRACE("(%p) ref was %d\n", This, ref + 1);
- if (!ref && !InterlockedDecrement(&This->numIfaces))
- secondarybuffer_destroy(This);
-
+ if (!ref) {
+ This->dsb->notify = NULL;
+ IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER)This->dsb);
+ HeapFree(GetProcessHeap(), 0, This);
+ TRACE("(%p) released\n", This);
+ }
return ref;
}
-static HRESULT WINAPI IDirectSoundNotifyImpl_SetNotificationPositions(IDirectSoundNotify *iface,
- DWORD howmuch, const DSBPOSITIONNOTIFY *notify)
-{
- IDirectSoundBufferImpl *This = impl_from_IDirectSoundNotify(iface);
-
+static HRESULT WINAPI IDirectSoundNotifyImpl_SetNotificationPositions(
+ LPDIRECTSOUNDNOTIFY iface,DWORD howmuch,LPCDSBPOSITIONNOTIFY notify
+) {
+ IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface;
TRACE("(%p,0x%08x,%p)\n",This,howmuch,notify);
if (howmuch > 0 && notify == NULL) {
notify[i].dwOffset,notify[i].hEventNotify);
}
- if (howmuch > 0) {
+ if (This->dsb->hwnotify) {
+ HRESULT hres;
+ hres = IDsDriverNotify_SetNotificationPositions(This->dsb->hwnotify, howmuch, notify);
+ if (hres != DS_OK)
+ WARN("IDsDriverNotify_SetNotificationPositions failed\n");
+ return hres;
+ } else if (howmuch > 0) {
/* Make an internal copy of the caller-supplied array.
* Replace the existing copy if one is already present. */
- HeapFree(GetProcessHeap(), 0, This->notifies);
- This->notifies = HeapAlloc(GetProcessHeap(), 0,
+ HeapFree(GetProcessHeap(), 0, This->dsb->notifies);
+ This->dsb->notifies = HeapAlloc(GetProcessHeap(), 0,
howmuch * sizeof(DSBPOSITIONNOTIFY));
- if (This->notifies == NULL) {
+ if (This->dsb->notifies == NULL) {
WARN("out of memory\n");
return DSERR_OUTOFMEMORY;
}
- CopyMemory(This->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY));
- This->nrofnotifies = howmuch;
- } else {
- HeapFree(GetProcessHeap(), 0, This->notifies);
- This->notifies = NULL;
- This->nrofnotifies = 0;
- }
+ CopyMemory(This->dsb->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY));
+ This->dsb->nrofnotifies = howmuch;
+ } else {
+ HeapFree(GetProcessHeap(), 0, This->dsb->notifies);
+ This->dsb->notifies = NULL;
+ This->dsb->nrofnotifies = 0;
+ }
return S_OK;
}
IDirectSoundNotifyImpl_SetNotificationPositions,
};
+static HRESULT IDirectSoundNotifyImpl_Create(
+ IDirectSoundBufferImpl * dsb,
+ IDirectSoundNotifyImpl **pdsn)
+{
+ IDirectSoundNotifyImpl * dsn;
+ TRACE("(%p,%p)\n",dsb,pdsn);
+
+ dsn = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dsn));
+
+ if (dsn == NULL) {
+ WARN("out of memory\n");
+ return DSERR_OUTOFMEMORY;
+ }
+
+ dsn->ref = 0;
+ dsn->lpVtbl = &dsnvt;
+ dsn->dsb = dsb;
+ dsb->notify = dsn;
+ IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)dsb);
+
+ *pdsn = dsn;
+ return DS_OK;
+}
+
+static HRESULT IDirectSoundNotifyImpl_Destroy(
+ IDirectSoundNotifyImpl *pdsn)
+{
+ TRACE("(%p)\n",pdsn);
+
+ while (IDirectSoundNotifyImpl_Release((LPDIRECTSOUNDNOTIFY)pdsn) > 0);
+
+ return DS_OK;
+}
+
/*******************************************************************************
* IDirectSoundBuffer
*/
static inline BOOL is_primary_buffer(IDirectSoundBufferImpl *This)
{
- return (This->dsbd.dwFlags & DSBCAPS_PRIMARYBUFFER) != 0;
+ return This->dsbd.dwFlags & DSBCAPS_PRIMARYBUFFER ? TRUE : FALSE;
}
static HRESULT WINAPI IDirectSoundBufferImpl_SetFormat(IDirectSoundBuffer8 *iface,
DSOUND_RecalcVolPan(&(This->volpan));
}
+ if (vol != oldVol) {
+ if (This->hwbuf) {
+ hres = IDsDriverBuffer_SetVolumePan(This->hwbuf, &(This->volpan));
+ if (hres != DS_OK)
+ WARN("IDsDriverBuffer_SetVolumePan failed\n");
+ }
+ }
+
RtlReleaseResource(&This->lock);
/* **** */
oldFreq = This->freq;
This->freq = freq;
if (freq != oldFreq) {
- This->freqAdjust = This->freq / (float)This->device->pwfx->nSamplesPerSec;
+ This->freqAdjust = ((DWORD64)This->freq << DSOUND_FREQSHIFT) / This->device->pwfx->nSamplesPerSec;
This->nAvgBytesPerSec = freq * This->pwfx->nBlockAlign;
DSOUND_RecalcFormat(This);
+ DSOUND_MixToTemporary(This, 0, This->buflen, FALSE);
}
RtlReleaseResource(&This->lock);
RtlAcquireResourceExclusive(&This->lock, TRUE);
This->playflags = flags;
- if (This->state == STATE_STOPPED) {
+ if (This->state == STATE_STOPPED && !This->hwbuf) {
This->leadin = TRUE;
This->state = STATE_STARTING;
} else if (This->state == STATE_STOPPING)
This->state = STATE_PLAYING;
+ if (This->hwbuf) {
+ hres = IDsDriverBuffer_Play(This->hwbuf, 0, 0, This->playflags);
+ if (hres != DS_OK)
+ WARN("IDsDriverBuffer_Play failed\n");
+ else
+ This->state = STATE_PLAYING;
+ }
RtlReleaseResource(&This->lock);
/* **** */
This->state = STATE_STOPPED;
DSOUND_CheckEvent(This, 0, 0);
}
+ if (This->hwbuf) {
+ hres = IDsDriverBuffer_Stop(This->hwbuf);
+ if (hres != DS_OK)
+ WARN("IDsDriverBuffer_Stop failed\n");
+ else
+ This->state = STATE_STOPPED;
+ }
RtlReleaseResource(&This->lock);
/* **** */
static ULONG WINAPI IDirectSoundBufferImpl_Release(IDirectSoundBuffer8 *iface)
{
IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
- ULONG ref;
-
- if (is_primary_buffer(This)){
- ref = capped_refcount_dec(&This->ref);
- if(!ref)
- capped_refcount_dec(&This->numIfaces);
- TRACE("(%p) ref is now: %d\n", This, ref);
- return ref;
- }
-
- ref = InterlockedDecrement(&This->ref);
- if (!ref && !InterlockedDecrement(&This->numIfaces))
- secondarybuffer_destroy(This);
+ ULONG ref = InterlockedDecrement(&This->ref);
- TRACE("(%p) ref is now %d\n", This, ref);
+ TRACE("(%p) ref was %d\n", This, ref + 1);
+ if (!ref && !InterlockedDecrement(&This->numIfaces)) {
+ if (is_primary_buffer(This))
+ primarybuffer_destroy(This);
+ else
+ secondarybuffer_destroy(This);
+ }
return ref;
}
DWORD *playpos, DWORD *writepos)
{
IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
- DWORD pos;
+ HRESULT hres;
TRACE("(%p,%p,%p)\n",This,playpos,writepos);
RtlAcquireResourceShared(&This->lock, TRUE);
+ if (This->hwbuf) {
+ hres=IDsDriverBuffer_GetPosition(This->hwbuf,playpos,writepos);
+ if (hres != DS_OK) {
+ WARN("IDsDriverBuffer_GetPosition failed\n");
+ return hres;
+ }
+ } else {
+ DWORD pos = This->sec_mixpos;
- pos = This->sec_mixpos;
+ /* sanity */
+ if (pos >= This->buflen){
+ FIXME("Bad play position. playpos: %d, buflen: %d\n", pos, This->buflen);
+ pos %= This->buflen;
+ }
- /* sanity */
- if (pos >= This->buflen){
- FIXME("Bad play position. playpos: %d, buflen: %d\n", pos, This->buflen);
- pos %= This->buflen;
+ if (playpos)
+ *playpos = pos;
+ if (writepos)
+ *writepos = pos;
}
-
- if (playpos)
- *playpos = pos;
- if (writepos)
- *writepos = pos;
-
- if (writepos && This->state != STATE_STOPPED) {
+ if (writepos && This->state != STATE_STOPPED && (!This->hwbuf || !(This->device->drvdesc.dwFlags & DSDDESC_DONTNEEDWRITELEAD))) {
/* apply the documented 10ms lead to writepos */
*writepos += This->writelead;
*writepos %= This->buflen;
}
-
RtlReleaseResource(&This->lock);
TRACE("playpos = %d, writepos = %d, buflen=%d (%p, time=%d)\n",
/* **** */
RtlAcquireResourceShared(&This->lock, TRUE);
- if (writecursor+writebytes <= This->buflen) {
- *(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor;
- if (This->sec_mixpos >= writecursor && This->sec_mixpos < writecursor + writebytes && This->state == STATE_PLAYING)
- WARN("Overwriting mixing position, case 1\n");
- *audiobytes1 = writebytes;
- if (lplpaudioptr2)
- *(LPBYTE*)lplpaudioptr2 = NULL;
- if (audiobytes2)
- *audiobytes2 = 0;
- TRACE("Locked %p(%i bytes) and %p(%i bytes) writecursor=%d\n",
- *(LPBYTE*)lplpaudioptr1, *audiobytes1, lplpaudioptr2 ? *(LPBYTE*)lplpaudioptr2 : NULL, audiobytes2 ? *audiobytes2: 0, writecursor);
- TRACE("->%d.0\n",writebytes);
+ if (!(This->device->drvdesc.dwFlags & DSDDESC_DONTNEEDSECONDARYLOCK) && This->hwbuf) {
+ hres = IDsDriverBuffer_Lock(This->hwbuf,
+ lplpaudioptr1, audiobytes1,
+ lplpaudioptr2, audiobytes2,
+ writecursor, writebytes,
+ 0);
+ if (hres != DS_OK) {
+ WARN("IDsDriverBuffer_Lock failed\n");
+ RtlReleaseResource(&This->lock);
+ return hres;
+ }
} else {
- DWORD remainder = writebytes + writecursor - This->buflen;
- *(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor;
- *audiobytes1 = This->buflen-writecursor;
- if (This->sec_mixpos >= writecursor && This->sec_mixpos < writecursor + writebytes && This->state == STATE_PLAYING)
- WARN("Overwriting mixing position, case 2\n");
- if (lplpaudioptr2)
- *(LPBYTE*)lplpaudioptr2 = This->buffer->memory;
- if (audiobytes2)
- *audiobytes2 = writebytes-(This->buflen-writecursor);
- if (audiobytes2 && This->sec_mixpos < remainder && This->state == STATE_PLAYING)
- WARN("Overwriting mixing position, case 3\n");
- TRACE("Locked %p(%i bytes) and %p(%i bytes) writecursor=%d\n", *(LPBYTE*)lplpaudioptr1, *audiobytes1, lplpaudioptr2 ? *(LPBYTE*)lplpaudioptr2 : NULL, audiobytes2 ? *audiobytes2: 0, writecursor);
+ if (writecursor+writebytes <= This->buflen) {
+ *(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor;
+ if (This->sec_mixpos >= writecursor && This->sec_mixpos < writecursor + writebytes && This->state == STATE_PLAYING)
+ WARN("Overwriting mixing position, case 1\n");
+ *audiobytes1 = writebytes;
+ if (lplpaudioptr2)
+ *(LPBYTE*)lplpaudioptr2 = NULL;
+ if (audiobytes2)
+ *audiobytes2 = 0;
+ TRACE("Locked %p(%i bytes) and %p(%i bytes) writecursor=%d\n",
+ *(LPBYTE*)lplpaudioptr1, *audiobytes1, lplpaudioptr2 ? *(LPBYTE*)lplpaudioptr2 : NULL, audiobytes2 ? *audiobytes2: 0, writecursor);
+ TRACE("->%d.0\n",writebytes);
+ } else {
+ DWORD remainder = writebytes + writecursor - This->buflen;
+ *(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor;
+ *audiobytes1 = This->buflen-writecursor;
+ if (This->sec_mixpos >= writecursor && This->sec_mixpos < writecursor + writebytes && This->state == STATE_PLAYING)
+ WARN("Overwriting mixing position, case 2\n");
+ if (lplpaudioptr2)
+ *(LPBYTE*)lplpaudioptr2 = This->buffer->memory;
+ if (audiobytes2)
+ *audiobytes2 = writebytes-(This->buflen-writecursor);
+ if (audiobytes2 && This->sec_mixpos < remainder && This->state == STATE_PLAYING)
+ WARN("Overwriting mixing position, case 3\n");
+ TRACE("Locked %p(%i bytes) and %p(%i bytes) writecursor=%d\n", *(LPBYTE*)lplpaudioptr1, *audiobytes1, lplpaudioptr2 ? *(LPBYTE*)lplpaudioptr2 : NULL, audiobytes2 ? *audiobytes2: 0, writecursor);
+ }
}
RtlReleaseResource(&This->lock);
{
IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
HRESULT hres = DS_OK;
+ DWORD oldpos;
TRACE("(%p,%d)\n",This,newpos);
/* **** */
RtlAcquireResourceExclusive(&This->lock, TRUE);
+ oldpos = This->sec_mixpos;
+
/* start mixing from this new location instead */
newpos %= This->buflen;
newpos -= newpos%This->pwfx->nBlockAlign;
/* at this point, do not attempt to reset buffers, mess with primary mix position,
or anything like that to reduce latency. The data already prebuffered cannot be changed */
+ /* position HW buffer if applicable, else just start mixing from new location instead */
+ if (This->hwbuf) {
+ hres = IDsDriverBuffer_SetPosition(This->hwbuf, This->buf_mixpos);
+ if (hres != DS_OK)
+ WARN("IDsDriverBuffer_SetPosition failed\n");
+ }
+ else if (oldpos != newpos)
+ /* FIXME: Perhaps add a call to DSOUND_MixToTemporary here? Not sure it's needed */
+ This->buf_mixpos = DSOUND_secpos_to_bufpos(This, newpos, 0, NULL);
+
RtlReleaseResource(&This->lock);
/* **** */
if (This->volpan.lPan != pan) {
This->volpan.lPan = pan;
DSOUND_RecalcVolPan(&(This->volpan));
+
+ if (This->hwbuf) {
+ hres = IDsDriverBuffer_SetVolumePan(This->hwbuf, &(This->volpan));
+ if (hres != DS_OK)
+ WARN("IDsDriverBuffer_SetVolumePan failed\n");
+ }
}
RtlReleaseResource(&This->lock);
TRACE("(%p,%p,%d,%p,%d)\n", This,p1,x1,p2,x2);
+ /* **** */
+ RtlAcquireResourceShared(&This->lock, TRUE);
+
+ if (!(This->device->drvdesc.dwFlags & DSDDESC_DONTNEEDSECONDARYLOCK) && This->hwbuf) {
+ hres = IDsDriverBuffer_Unlock(This->hwbuf, p1, x1, p2, x2);
+ if (hres != DS_OK)
+ WARN("IDsDriverBuffer_Unlock failed\n");
+ }
+
+ RtlReleaseResource(&This->lock);
+ /* **** */
+
if (!p2)
x2 = 0;
- if((p1 && ((BYTE*)p1 < This->buffer->memory || (BYTE*)p1 >= This->buffer->memory + This->buflen)) ||
- (p2 && ((BYTE*)p2 < This->buffer->memory || (BYTE*)p2 >= This->buffer->memory + This->buflen)))
- return DSERR_INVALIDPARAM;
-
- if (x1 || x2)
+ if (!This->hwbuf && (x1 || x2))
{
RtlAcquireResourceShared(&This->device->buffer_list_lock, TRUE);
LIST_FOR_EACH_ENTRY(iter, &This->buffer->buffers, IDirectSoundBufferImpl, entry )
{
if(x1 + (DWORD_PTR)p1 - (DWORD_PTR)iter->buffer->memory > iter->buflen)
hres = DSERR_INVALIDPARAM;
+ else
+ DSOUND_MixToTemporary(iter, (DWORD_PTR)p1 - (DWORD_PTR)iter->buffer->memory, x1, FALSE);
}
+ if (x2)
+ DSOUND_MixToTemporary(iter, 0, x2, FALSE);
RtlReleaseResource(&iter->lock);
}
RtlReleaseResource(&This->device->buffer_list_lock);
}
caps->dwFlags = This->dsbd.dwFlags;
- caps->dwFlags |= DSBCAPS_LOCSOFTWARE;
+ if (This->hwbuf) caps->dwFlags |= DSBCAPS_LOCHARDWARE;
+ else caps->dwFlags |= DSBCAPS_LOCSOFTWARE;
caps->dwBufferBytes = This->buflen;
}
if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) {
- IDirectSoundNotify_AddRef(&This->IDirectSoundNotify_iface);
- *ppobj = &This->IDirectSoundNotify_iface;
- return S_OK;
+ 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->dsbd.dwFlags & DSBCAPS_CTRL3D){
- IDirectSound3DBuffer_AddRef(&This->IDirectSound3DBuffer_iface);
- *ppobj = &This->IDirectSound3DBuffer_iface;
- return S_OK;
- }
- TRACE("app requested IDirectSound3DBuffer on non-3D secondary buffer\n");
- return E_NOINTERFACE;
+ 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 ) ) {
}
if ( IsEqualGUID( &IID_IKsPropertySet, riid ) ) {
- IKsPropertySet_AddRef(&This->IKsPropertySet_iface);
- *ppobj = &This->IKsPropertySet_iface;
- return S_OK;
+ 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 ) );
LPWAVEFORMATEX wfex = dsbd->lpwfxFormat;
HRESULT err = DS_OK;
DWORD capf = 0;
+ int use_hw;
TRACE("(%p,%p,%p)\n",device,pdsb,dsbd);
if (dsbd->dwBufferBytes < DSBSIZE_MIN || dsbd->dwBufferBytes > DSBSIZE_MAX) {
TRACE("Created buffer at %p\n", dsb);
- dsb->ref = 0;
- dsb->refn = 0;
- dsb->ref3D = 0;
- dsb->refiks = 0;
- dsb->numIfaces = 0;
+ dsb->ref = 1;
+ dsb->numIfaces = 1;
dsb->device = device;
- dsb->IDirectSoundBuffer8_iface.lpVtbl = &dsbvt;
- dsb->IDirectSoundNotify_iface.lpVtbl = &dsnvt;
- dsb->IDirectSound3DBuffer_iface.lpVtbl = &ds3dbvt;
- dsb->IKsPropertySet_iface.lpVtbl = &iksbvt;
+ dsb->IDirectSoundBuffer8_iface.lpVtbl = &dsbvt;
+ dsb->iks = NULL;
/* size depends on version */
CopyMemory(&dsb->dsbd, dsbd, dsbd->dwSize);
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;
if (wfex->wBitsPerSample==16) capf |= DSCAPS_SECONDARY16BIT;
else capf |= DSCAPS_SECONDARY8BIT;
- TRACE("capf = 0x%08x, device->drvcaps.dwFlags = 0x%08x\n", capf, device->drvcaps.dwFlags);
+ use_hw = !!(dsbd->dwFlags & DSBCAPS_LOCHARDWARE);
+ TRACE("use_hw = %d, capf = 0x%08x, device->drvcaps.dwFlags = 0x%08x\n", use_hw, capf, device->drvcaps.dwFlags);
+ if (use_hw && ((device->drvcaps.dwFlags & capf) != capf || !device->driver))
+ {
+ if (device->driver)
+ WARN("Format not supported for hardware buffer\n");
+ HeapFree(GetProcessHeap(),0,dsb->pwfx);
+ HeapFree(GetProcessHeap(),0,dsb);
+ *pdsb = NULL;
+ if ((device->drvcaps.dwFlags & capf) != capf)
+ return DSERR_BADFORMAT;
+ return DSERR_GENERIC;
+ }
+
+ /* 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)));
return DSERR_OUTOFMEMORY;
}
- /* Allocate system memory for buffer */
- 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;
+ /* Allocate system memory for buffer if applicable */
+ if ((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;
+ }
+ }
+
+ /* Allocate the hardware buffer */
+ if (use_hw) {
+ err = IDsDriver_CreateSoundBuffer(device->driver,wfex,dsbd->dwFlags,0,
+ &(dsb->buflen),&(dsb->buffer->memory),
+ (LPVOID*)&(dsb->hwbuf));
+ if (FAILED(err))
+ {
+ WARN("Failed to create hardware secondary buffer: %08x\n", err);
+ if (device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY)
+ HeapFree(GetProcessHeap(),0,dsb->buffer->memory);
+ HeapFree(GetProcessHeap(),0,dsb->buffer);
+ HeapFree(GetProcessHeap(),0,dsb->pwfx);
+ HeapFree(GetProcessHeap(),0,dsb);
+ *pdsb = NULL;
+ return DSERR_GENERIC;
+ }
}
dsb->buffer->ref = 1;
/* It's not necessary to initialize values to zero since */
/* we allocated this structure with HEAP_ZERO_MEMORY... */
- dsb->sec_mixpos = 0;
+ dsb->buf_mixpos = dsb->sec_mixpos = 0;
dsb->state = STATE_STOPPED;
- dsb->freqAdjust = dsb->freq / (float)device->pwfx->nSamplesPerSec;
+ dsb->freqAdjust = ((DWORD64)dsb->freq << DSOUND_FREQSHIFT) / device->pwfx->nSamplesPerSec;
dsb->nAvgBytesPerSec = dsb->freq *
dsbd->lpwfxFormat->nBlockAlign;
}
}
- IDirectSoundBuffer8_AddRef(&dsb->IDirectSoundBuffer8_iface);
*pdsb = dsb;
return err;
}
void secondarybuffer_destroy(IDirectSoundBufferImpl *This)
{
- ULONG ref = InterlockedIncrement(&This->numIfaces);
-
- if (ref > 1)
- WARN("Destroying buffer with %u in use interfaces\n", ref - 1);
-
DirectSoundDevice_RemoveBuffer(This->device, This);
RtlDeleteResource(&This->lock);
- This->buffer->ref--;
- list_remove(&This->entry);
- if (This->buffer->ref == 0) {
- HeapFree(GetProcessHeap(), 0, This->buffer->memory);
- HeapFree(GetProcessHeap(), 0, This->buffer);
+ if (This->hwbuf)
+ IDsDriverBuffer_Release(This->hwbuf);
+ if (!This->hwbuf || (This->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY)) {
+ This->buffer->ref--;
+ list_remove(&This->entry);
+ if (This->buffer->ref == 0) {
+ HeapFree(GetProcessHeap(), 0, This->buffer->memory);
+ HeapFree(GetProcessHeap(), 0, This->buffer);
+ }
}
+ HeapFree(GetProcessHeap(), 0, This->tmp_buffer);
HeapFree(GetProcessHeap(), 0, This->notifies);
HeapFree(GetProcessHeap(), 0, This->pwfx);
HeapFree(GetProcessHeap(), 0, This);
TRACE("(%p) released\n", This);
}
+HRESULT IDirectSoundBufferImpl_Destroy(
+ IDirectSoundBufferImpl *pdsb)
+{
+ TRACE("(%p)\n",pdsb);
+
+ /* This keeps the *_Destroy functions from possibly deleting
+ * this object until it is ready to be deleted */
+ InterlockedIncrement(&pdsb->numIfaces);
+
+ if (pdsb->iks) {
+ WARN("iks not NULL\n");
+ IKsBufferPropertySetImpl_Destroy(pdsb->iks);
+ pdsb->iks = NULL;
+ }
+
+ if (pdsb->ds3db) {
+ WARN("ds3db not NULL\n");
+ IDirectSound3DBufferImpl_Destroy(pdsb->ds3db);
+ pdsb->ds3db = NULL;
+ }
+
+ if (pdsb->notify) {
+ WARN("notify not NULL\n");
+ IDirectSoundNotifyImpl_Destroy(pdsb->notify);
+ pdsb->notify = NULL;
+ }
+
+ secondarybuffer_destroy(pdsb);
+
+ return S_OK;
+}
+
HRESULT IDirectSoundBufferImpl_Duplicate(
DirectSoundDevice *device,
IDirectSoundBufferImpl **ppdsb,
*ppdsb = NULL;
return DSERR_OUTOFMEMORY;
}
-
- RtlAcquireResourceShared(&pdsb->lock, TRUE);
-
CopyMemory(dsb, pdsb, sizeof(*dsb));
dsb->pwfx = DSOUND_CopyFormat(pdsb->pwfx);
-
- RtlReleaseResource(&pdsb->lock);
-
if (dsb->pwfx == NULL) {
HeapFree(GetProcessHeap(),0,dsb);
*ppdsb = NULL;
return DSERR_OUTOFMEMORY;
}
+ if (pdsb->hwbuf) {
+ TRACE("duplicating hardware buffer\n");
+
+ hres = IDsDriver_DuplicateSoundBuffer(device->driver, pdsb->hwbuf,
+ (LPVOID *)&dsb->hwbuf);
+ if (FAILED(hres)) {
+ WARN("IDsDriver_DuplicateSoundBuffer failed (%08x)\n", hres);
+ HeapFree(GetProcessHeap(),0,dsb->pwfx);
+ HeapFree(GetProcessHeap(),0,dsb);
+ *ppdsb = NULL;
+ return hres;
+ }
+ }
+
dsb->buffer->ref++;
list_add_head(&dsb->buffer->buffers, &dsb->entry);
- dsb->ref = 0;
- dsb->refn = 0;
- dsb->ref3D = 0;
- dsb->refiks = 0;
- dsb->numIfaces = 0;
+ dsb->ref = 1;
+ dsb->numIfaces = 1;
dsb->state = STATE_STOPPED;
- dsb->sec_mixpos = 0;
+ dsb->buf_mixpos = dsb->sec_mixpos = 0;
+ dsb->notify = NULL;
dsb->notifies = NULL;
dsb->nrofnotifies = 0;
dsb->device = device;
+ dsb->ds3db = NULL;
+ dsb->iks = NULL; /* FIXME? */
+ dsb->tmp_buffer = NULL;
DSOUND_RecalcFormat(dsb);
+ DSOUND_MixToTemporary(dsb, 0, dsb->buflen, FALSE);
RtlInitializeResource(&dsb->lock);
hres = DirectSoundDevice_AddBuffer(device, dsb);
if (hres != DS_OK) {
RtlDeleteResource(&dsb->lock);
+ HeapFree(GetProcessHeap(),0,dsb->tmp_buffer);
list_remove(&dsb->entry);
dsb->buffer->ref--;
HeapFree(GetProcessHeap(),0,dsb->pwfx);
dsb = NULL;
}
- IDirectSoundBuffer8_AddRef(&dsb->IDirectSoundBuffer8_iface);
*ppdsb = dsb;
return hres;
}
/*******************************************************************************
- * IKsPropertySet
+ * IKsBufferPropertySet
*/
-static inline IDirectSoundBufferImpl *impl_from_IKsPropertySet(IKsPropertySet *iface)
-{
- return CONTAINING_RECORD(iface, IDirectSoundBufferImpl, IKsPropertySet_iface);
-}
-
/* IUnknown methods */
-static HRESULT WINAPI IKsPropertySetImpl_QueryInterface(IKsPropertySet *iface, REFIID riid,
- void **ppobj)
+static HRESULT WINAPI IKsBufferPropertySetImpl_QueryInterface(
+ LPKSPROPERTYSET iface,
+ REFIID riid,
+ LPVOID *ppobj )
{
- IDirectSoundBufferImpl *This = impl_from_IKsPropertySet(iface);
-
+ IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
- return IDirectSoundBuffer_QueryInterface(&This->IDirectSoundBuffer8_iface, riid, ppobj);
+ return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb, riid, ppobj);
}
-static ULONG WINAPI IKsPropertySetImpl_AddRef(IKsPropertySet *iface)
+static ULONG WINAPI IKsBufferPropertySetImpl_AddRef(LPKSPROPERTYSET iface)
{
- IDirectSoundBufferImpl *This = impl_from_IKsPropertySet(iface);
- ULONG ref = InterlockedIncrement(&This->refiks);
-
+ IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
+ ULONG ref = InterlockedIncrement(&(This->ref));
TRACE("(%p) ref was %d\n", This, ref - 1);
-
- if(ref == 1)
- InterlockedIncrement(&This->numIfaces);
-
return ref;
}
-static ULONG WINAPI IKsPropertySetImpl_Release(IKsPropertySet *iface)
+static ULONG WINAPI IKsBufferPropertySetImpl_Release(LPKSPROPERTYSET iface)
{
- IDirectSoundBufferImpl *This = impl_from_IKsPropertySet(iface);
- ULONG ref;
-
- if (is_primary_buffer(This)){
- ref = capped_refcount_dec(&This->refiks);
- if(!ref)
- capped_refcount_dec(&This->numIfaces);
- TRACE("(%p) ref is now: %d\n", This, ref);
- return ref;
- }
-
- ref = InterlockedDecrement(&This->refiks);
- if (!ref && !InterlockedDecrement(&This->numIfaces))
- secondarybuffer_destroy(This);
-
- TRACE("(%p) ref is now %d\n", This, ref);
+ IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
+ ULONG ref = InterlockedDecrement(&(This->ref));
+ TRACE("(%p) ref was %d\n", This, ref + 1);
+ if (!ref) {
+ This->dsb->iks = 0;
+ IDirectSoundBuffer_Release((LPDIRECTSOUND3DBUFFER)This->dsb);
+ HeapFree(GetProcessHeap(), 0, This);
+ TRACE("(%p) released\n", This);
+ }
return ref;
}
-static HRESULT WINAPI IKsPropertySetImpl_Get(IKsPropertySet *iface, REFGUID guidPropSet,
- ULONG dwPropID, void *pInstanceData, ULONG cbInstanceData, void *pPropData,
- ULONG cbPropData, ULONG *pcbReturned)
+static HRESULT WINAPI IKsBufferPropertySetImpl_Get(
+ LPKSPROPERTYSET iface,
+ REFGUID guidPropSet,
+ ULONG dwPropID,
+ LPVOID pInstanceData,
+ ULONG cbInstanceData,
+ LPVOID pPropData,
+ ULONG cbPropData,
+ PULONG pcbReturned )
{
- IDirectSoundBufferImpl *This = impl_from_IKsPropertySet(iface);
-
+ IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
+ PIDSDRIVERPROPERTYSET ps;
TRACE("(iface=%p,guidPropSet=%s,dwPropID=%d,pInstanceData=%p,cbInstanceData=%d,pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned);
+ if (This->dsb->hwbuf) {
+ IDsDriver_QueryInterface(This->dsb->hwbuf, &IID_IDsDriverPropertySet, (void **)&ps);
+
+ if (ps) {
+ DSPROPERTY prop;
+ HRESULT hres;
+
+ prop.s.Set = *guidPropSet;
+ prop.s.Id = dwPropID;
+ prop.s.Flags = 0; /* unused */
+ prop.s.InstanceId = (ULONG)This->dsb->device;
+
+
+ hres = IDsDriverPropertySet_Get(ps, &prop, pInstanceData, cbInstanceData, pPropData, cbPropData, pcbReturned);
+
+ IDsDriverPropertySet_Release(ps);
+
+ return hres;
+ }
+ }
+
return E_PROP_ID_UNSUPPORTED;
}
-static HRESULT WINAPI IKsPropertySetImpl_Set(IKsPropertySet *iface, REFGUID guidPropSet,
- ULONG dwPropID, void *pInstanceData, ULONG cbInstanceData, void *pPropData,
- ULONG cbPropData)
+static HRESULT WINAPI IKsBufferPropertySetImpl_Set(
+ LPKSPROPERTYSET iface,
+ REFGUID guidPropSet,
+ ULONG dwPropID,
+ LPVOID pInstanceData,
+ ULONG cbInstanceData,
+ LPVOID pPropData,
+ ULONG cbPropData )
{
- IDirectSoundBufferImpl *This = impl_from_IKsPropertySet(iface);
-
+ IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
+ PIDSDRIVERPROPERTYSET ps;
TRACE("(%p,%s,%d,%p,%d,%p,%d)\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData);
+ if (This->dsb->hwbuf) {
+ IDsDriver_QueryInterface(This->dsb->hwbuf, &IID_IDsDriverPropertySet, (void **)&ps);
+
+ if (ps) {
+ DSPROPERTY prop;
+ HRESULT hres;
+
+ prop.s.Set = *guidPropSet;
+ prop.s.Id = dwPropID;
+ prop.s.Flags = 0; /* unused */
+ prop.s.InstanceId = (ULONG)This->dsb->device;
+ hres = IDsDriverPropertySet_Set(ps,&prop,pInstanceData,cbInstanceData,pPropData,cbPropData);
+
+ IDsDriverPropertySet_Release(ps);
+
+ return hres;
+ }
+ }
+
return E_PROP_ID_UNSUPPORTED;
}
-static HRESULT WINAPI IKsPropertySetImpl_QuerySupport(IKsPropertySet *iface, REFGUID guidPropSet,
- ULONG dwPropID, ULONG *pTypeSupport)
+static HRESULT WINAPI IKsBufferPropertySetImpl_QuerySupport(
+ LPKSPROPERTYSET iface,
+ REFGUID guidPropSet,
+ ULONG dwPropID,
+ PULONG pTypeSupport )
{
- IDirectSoundBufferImpl *This = impl_from_IKsPropertySet(iface);
-
+ IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
+ PIDSDRIVERPROPERTYSET ps;
TRACE("(%p,%s,%d,%p)\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport);
+ if (This->dsb->hwbuf) {
+ IDsDriver_QueryInterface(This->dsb->hwbuf, &IID_IDsDriverPropertySet, (void **)&ps);
+
+ if (ps) {
+ HRESULT hres;
+
+ hres = IDsDriverPropertySet_QuerySupport(ps,guidPropSet, dwPropID,pTypeSupport);
+
+ IDsDriverPropertySet_Release(ps);
+
+ return hres;
+ }
+ }
+
return E_PROP_ID_UNSUPPORTED;
}
-const IKsPropertySetVtbl iksbvt = {
- IKsPropertySetImpl_QueryInterface,
- IKsPropertySetImpl_AddRef,
- IKsPropertySetImpl_Release,
- IKsPropertySetImpl_Get,
- IKsPropertySetImpl_Set,
- IKsPropertySetImpl_QuerySupport
+static const IKsPropertySetVtbl iksbvt = {
+ IKsBufferPropertySetImpl_QueryInterface,
+ IKsBufferPropertySetImpl_AddRef,
+ IKsBufferPropertySetImpl_Release,
+ IKsBufferPropertySetImpl_Get,
+ IKsBufferPropertySetImpl_Set,
+ IKsBufferPropertySetImpl_QuerySupport
};
+
+HRESULT IKsBufferPropertySetImpl_Create(
+ IDirectSoundBufferImpl *dsb,
+ IKsBufferPropertySetImpl **piks)
+{
+ IKsBufferPropertySetImpl *iks;
+ TRACE("(%p,%p)\n",dsb,piks);
+ *piks = NULL;
+
+ iks = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*iks));
+ if (iks == 0) {
+ WARN("out of memory\n");
+ *piks = NULL;
+ return DSERR_OUTOFMEMORY;
+ }
+
+ iks->ref = 0;
+ iks->dsb = dsb;
+ dsb->iks = iks;
+ iks->lpVtbl = &iksbvt;
+
+ IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)dsb);
+
+ *piks = iks;
+ return S_OK;
+}
+
+HRESULT IKsBufferPropertySetImpl_Destroy(
+ IKsBufferPropertySetImpl *piks)
+{
+ TRACE("(%p)\n",piks);
+
+ while (IKsBufferPropertySetImpl_Release((LPKSPROPERTYSET)piks) > 0);
+
+ return S_OK;
+}
#include "dsound_private.h"
-typedef struct DirectSoundCaptureDevice DirectSoundCaptureDevice;
-
-/* IDirectSoundCaptureBuffer implementation structure */
-typedef struct IDirectSoundCaptureBufferImpl
-{
- IDirectSoundCaptureBuffer8 IDirectSoundCaptureBuffer8_iface;
- IDirectSoundNotify IDirectSoundNotify_iface;
- LONG numIfaces; /* "in use interfaces" refcount */
- LONG ref, refn;
- /* IDirectSoundCaptureBuffer fields */
- DirectSoundCaptureDevice *device;
- DSCBUFFERDESC *pdscbd;
- DWORD flags;
- /* IDirectSoundNotify fields */
- DSBPOSITIONNOTIFY *notifies;
- int nrofnotifies;
-} IDirectSoundCaptureBufferImpl;
-
-/* DirectSoundCaptureDevice implementation structure */
-struct DirectSoundCaptureDevice
+/*****************************************************************************
+ * IDirectSoundCaptureNotify implementation structure
+ */
+struct IDirectSoundCaptureNotifyImpl
{
- GUID guid;
- LONG ref;
- DSCCAPS drvcaps;
- BYTE *buffer;
- DWORD buflen, write_pos_bytes;
- WAVEFORMATEX *pwfx;
- IDirectSoundCaptureBufferImpl *capture_buffer;
- DWORD state;
- UINT timerID;
- CRITICAL_SECTION lock;
- IMMDevice *mmdevice;
- IAudioClient *client;
- IAudioCaptureClient *capture;
- struct list entry;
+ /* IUnknown fields */
+ const IDirectSoundNotifyVtbl *lpVtbl;
+ LONG ref;
+ IDirectSoundCaptureBufferImpl* dscb;
};
-
-static void capturebuffer_destroy(IDirectSoundCaptureBufferImpl *This)
-{
- if (This->device->state == STATE_CAPTURING)
- This->device->state = STATE_STOPPING;
-
- HeapFree(GetProcessHeap(),0, This->pdscbd);
-
- if (This->device->client) {
- IAudioClient_Release(This->device->client);
- This->device->client = NULL;
- }
-
- if (This->device->capture) {
- IAudioCaptureClient_Release(This->device->capture);
- This->device->capture = NULL;
- }
-
- /* remove from DirectSoundCaptureDevice */
- This->device->capture_buffer = NULL;
-
- HeapFree(GetProcessHeap(), 0, This->notifies);
- HeapFree(GetProcessHeap(), 0, This);
- TRACE("(%p) released\n", This);
-}
-
/*******************************************************************************
- * IDirectSoundNotify
+ * IDirectSoundCaptureNotify
*/
-static inline struct IDirectSoundCaptureBufferImpl *impl_from_IDirectSoundNotify(IDirectSoundNotify *iface)
-{
- return CONTAINING_RECORD(iface, IDirectSoundCaptureBufferImpl, IDirectSoundNotify_iface);
-}
-
-static HRESULT WINAPI IDirectSoundNotifyImpl_QueryInterface(IDirectSoundNotify *iface, REFIID riid,
- void **ppobj)
+static HRESULT WINAPI IDirectSoundCaptureNotifyImpl_QueryInterface(
+ LPDIRECTSOUNDNOTIFY iface,
+ REFIID riid,
+ LPVOID *ppobj)
{
- IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundNotify(iface);
+ IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface;
+ TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
- TRACE("(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj);
+ if (This->dscb == NULL) {
+ WARN("invalid parameter\n");
+ return E_INVALIDARG;
+ }
- return IDirectSoundCaptureBuffer_QueryInterface(&This->IDirectSoundCaptureBuffer8_iface, riid, ppobj);
+ return IDirectSoundCaptureBuffer_QueryInterface((LPDIRECTSOUNDCAPTUREBUFFER)This->dscb, riid, ppobj);
}
-static ULONG WINAPI IDirectSoundNotifyImpl_AddRef(IDirectSoundNotify *iface)
+static ULONG WINAPI IDirectSoundCaptureNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface)
{
- IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundNotify(iface);
- ULONG ref = InterlockedIncrement(&This->refn);
-
+ IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface;
+ ULONG ref = InterlockedIncrement(&(This->ref));
TRACE("(%p) ref was %d\n", This, ref - 1);
-
- if(ref == 1)
- InterlockedIncrement(&This->numIfaces);
-
return ref;
}
-static ULONG WINAPI IDirectSoundNotifyImpl_Release(IDirectSoundNotify *iface)
+static ULONG WINAPI IDirectSoundCaptureNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface)
{
- IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundNotify(iface);
- ULONG ref = InterlockedDecrement(&This->refn);
-
+ IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface;
+ ULONG ref = InterlockedDecrement(&(This->ref));
TRACE("(%p) ref was %d\n", This, ref + 1);
- if (!ref && !InterlockedDecrement(&This->numIfaces))
- capturebuffer_destroy(This);
-
+ if (!ref) {
+ if (This->dscb->hwnotify)
+ IDsDriverNotify_Release(This->dscb->hwnotify);
+ This->dscb->notify=NULL;
+ IDirectSoundCaptureBuffer_Release((LPDIRECTSOUNDCAPTUREBUFFER)This->dscb);
+ HeapFree(GetProcessHeap(),0,This);
+ TRACE("(%p) released\n", This);
+ }
return ref;
}
-static HRESULT WINAPI IDirectSoundNotifyImpl_SetNotificationPositions(IDirectSoundNotify *iface,
- DWORD howmuch, const DSBPOSITIONNOTIFY *notify)
+static HRESULT WINAPI IDirectSoundCaptureNotifyImpl_SetNotificationPositions(
+ LPDIRECTSOUNDNOTIFY iface,
+ DWORD howmuch,
+ LPCDSBPOSITIONNOTIFY notify)
{
- IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundNotify(iface);
+ IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface;
TRACE("(%p,0x%08x,%p)\n",This,howmuch,notify);
if (howmuch > 0 && notify == NULL) {
notify[i].dwOffset,notify[i].hEventNotify);
}
- if (howmuch > 0) {
+ if (This->dscb->hwnotify) {
+ HRESULT hres;
+ hres = IDsDriverNotify_SetNotificationPositions(This->dscb->hwnotify, howmuch, notify);
+ if (hres != DS_OK)
+ WARN("IDsDriverNotify_SetNotificationPositions failed\n");
+ return hres;
+ } else if (howmuch > 0) {
/* Make an internal copy of the caller-supplied array.
* Replace the existing copy if one is already present. */
- if (This->notifies)
- This->notifies = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->notifies,
- howmuch * sizeof(DSBPOSITIONNOTIFY));
+ if (This->dscb->notifies)
+ This->dscb->notifies = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ This->dscb->notifies, howmuch * sizeof(DSBPOSITIONNOTIFY));
else
- This->notifies = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
- howmuch * sizeof(DSBPOSITIONNOTIFY));
+ This->dscb->notifies = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ howmuch * sizeof(DSBPOSITIONNOTIFY));
- if (!This->notifies) {
+ if (This->dscb->notifies == NULL) {
WARN("out of memory\n");
return DSERR_OUTOFMEMORY;
}
- CopyMemory(This->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY));
- This->nrofnotifies = howmuch;
+ CopyMemory(This->dscb->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY));
+ This->dscb->nrofnotifies = howmuch;
} else {
- HeapFree(GetProcessHeap(), 0, This->notifies);
- This->notifies = NULL;
- This->nrofnotifies = 0;
+ HeapFree(GetProcessHeap(), 0, This->dscb->notifies);
+ This->dscb->notifies = NULL;
+ This->dscb->nrofnotifies = 0;
}
return S_OK;
static const IDirectSoundNotifyVtbl dscnvt =
{
- IDirectSoundNotifyImpl_QueryInterface,
- IDirectSoundNotifyImpl_AddRef,
- IDirectSoundNotifyImpl_Release,
- IDirectSoundNotifyImpl_SetNotificationPositions
+ IDirectSoundCaptureNotifyImpl_QueryInterface,
+ IDirectSoundCaptureNotifyImpl_AddRef,
+ IDirectSoundCaptureNotifyImpl_Release,
+ IDirectSoundCaptureNotifyImpl_SetNotificationPositions,
};
+static HRESULT IDirectSoundCaptureNotifyImpl_Create(
+ IDirectSoundCaptureBufferImpl *dscb,
+ IDirectSoundCaptureNotifyImpl **pdscn)
+{
+ IDirectSoundCaptureNotifyImpl * dscn;
+ TRACE("(%p,%p)\n",dscb,pdscn);
+
+ dscn = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dscn));
+
+ if (dscn == NULL) {
+ WARN("out of memory\n");
+ return DSERR_OUTOFMEMORY;
+ }
+
+ dscn->ref = 0;
+ dscn->lpVtbl = &dscnvt;
+ dscn->dscb = dscb;
+ dscb->notify = dscn;
+ IDirectSoundCaptureBuffer_AddRef((LPDIRECTSOUNDCAPTUREBUFFER)dscb);
+
+ *pdscn = dscn;
+ return DS_OK;
+}
+
static const char * const captureStateString[] = {
"STATE_STOPPED",
/*******************************************************************************
- * IDirectSoundCaptureBuffer
+ * IDirectSoundCaptureBuffer
*/
-static inline IDirectSoundCaptureBufferImpl *impl_from_IDirectSoundCaptureBuffer8(IDirectSoundCaptureBuffer8 *iface)
-{
- return CONTAINING_RECORD(iface, IDirectSoundCaptureBufferImpl, IDirectSoundCaptureBuffer8_iface);
-}
-
-static HRESULT WINAPI IDirectSoundCaptureBufferImpl_QueryInterface(IDirectSoundCaptureBuffer8 *iface,
- REFIID riid, void **ppobj)
+static HRESULT WINAPI
+IDirectSoundCaptureBufferImpl_QueryInterface(
+ LPDIRECTSOUNDCAPTUREBUFFER8 iface,
+ REFIID riid,
+ LPVOID* ppobj )
{
- IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(iface);
-
+ IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
+ HRESULT hres;
TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
if (ppobj == NULL) {
*ppobj = NULL;
+ if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) {
+ if (!This->notify)
+ hres = IDirectSoundCaptureNotifyImpl_Create(This, &This->notify);
+ if (This->notify) {
+ IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY)This->notify);
+ if (This->device->hwbuf && !This->hwnotify) {
+ hres = IDsCaptureDriverBuffer_QueryInterface(This->device->hwbuf,
+ &IID_IDsDriverNotify, (LPVOID*)&(This->hwnotify));
+ if (hres != DS_OK) {
+ WARN("IDsCaptureDriverBuffer_QueryInterface failed\n");
+ IDirectSoundNotify_Release((LPDIRECTSOUNDNOTIFY)This->notify);
+ *ppobj = 0;
+ return hres;
+ }
+ }
+
+ *ppobj = This->notify;
+ return DS_OK;
+ }
+
+ WARN("IID_IDirectSoundNotify\n");
+ return E_FAIL;
+ }
+
if ( IsEqualGUID( &IID_IDirectSoundCaptureBuffer, riid ) ||
IsEqualGUID( &IID_IDirectSoundCaptureBuffer8, riid ) ) {
IDirectSoundCaptureBuffer8_AddRef(iface);
- *ppobj = iface;
- return S_OK;
- }
-
- if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) {
- IDirectSoundNotify_AddRef(&This->IDirectSoundNotify_iface);
- *ppobj = &This->IDirectSoundNotify_iface;
- return S_OK;
+ *ppobj = This;
+ return NO_ERROR;
}
FIXME("(%p,%s,%p) unsupported GUID\n", This, debugstr_guid(riid), ppobj);
return E_NOINTERFACE;
}
-static ULONG WINAPI IDirectSoundCaptureBufferImpl_AddRef(IDirectSoundCaptureBuffer8 *iface)
+static ULONG WINAPI
+IDirectSoundCaptureBufferImpl_AddRef( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
{
- IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(iface);
- ULONG ref = InterlockedIncrement(&This->ref);
-
+ IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
+ ULONG ref = InterlockedIncrement(&(This->ref));
TRACE("(%p) ref was %d\n", This, ref - 1);
-
- if(ref == 1)
- InterlockedIncrement(&This->numIfaces);
-
return ref;
}
-static ULONG WINAPI IDirectSoundCaptureBufferImpl_Release(IDirectSoundCaptureBuffer8 *iface)
+static ULONG WINAPI
+IDirectSoundCaptureBufferImpl_Release( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
{
- IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(iface);
- ULONG ref = InterlockedDecrement(&This->ref);
-
+ IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
+ ULONG ref = InterlockedDecrement(&(This->ref));
TRACE("(%p) ref was %d\n", This, ref + 1);
- if (!ref && !InterlockedDecrement(&This->numIfaces))
- capturebuffer_destroy(This);
+ if (!ref) {
+ TRACE("deleting object\n");
+ if (This->device->state == STATE_CAPTURING)
+ This->device->state = STATE_STOPPING;
+
+ HeapFree(GetProcessHeap(),0, This->pdscbd);
+
+ if (This->device->hwi) {
+ waveInReset(This->device->hwi);
+ waveInClose(This->device->hwi);
+ HeapFree(GetProcessHeap(),0, This->device->pwave);
+ This->device->pwave = 0;
+ This->device->hwi = 0;
+ }
+ if (This->device->hwbuf)
+ IDsCaptureDriverBuffer_Release(This->device->hwbuf);
+
+ /* remove from DirectSoundCaptureDevice */
+ This->device->capture_buffer = NULL;
+
+ if (This->notify)
+ IDirectSoundNotify_Release((LPDIRECTSOUNDNOTIFY)This->notify);
+
+ /* If driver manages its own buffer, IDsCaptureDriverBuffer_Release
+ should have freed the buffer. Prevent freeing it again in
+ IDirectSoundCaptureBufferImpl_Create */
+ if (!(This->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY))
+ This->device->buffer = NULL;
+
+ HeapFree(GetProcessHeap(), 0, This->notifies);
+ HeapFree( GetProcessHeap(), 0, This );
+ TRACE("(%p) released\n", This);
+ }
return ref;
}
-static HRESULT WINAPI IDirectSoundCaptureBufferImpl_GetCaps(IDirectSoundCaptureBuffer8 *iface,
- DSCBCAPS *lpDSCBCaps)
+static HRESULT WINAPI
+IDirectSoundCaptureBufferImpl_GetCaps(
+ LPDIRECTSOUNDCAPTUREBUFFER8 iface,
+ LPDSCBCAPS lpDSCBCaps )
{
- IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(iface);
+ IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
TRACE( "(%p,%p)\n", This, lpDSCBCaps );
if (lpDSCBCaps == NULL) {
return DS_OK;
}
-static HRESULT WINAPI IDirectSoundCaptureBufferImpl_GetCurrentPosition(IDirectSoundCaptureBuffer8 *iface,
- DWORD *lpdwCapturePosition, DWORD *lpdwReadPosition)
+static HRESULT WINAPI
+IDirectSoundCaptureBufferImpl_GetCurrentPosition(
+ LPDIRECTSOUNDCAPTUREBUFFER8 iface,
+ LPDWORD lpdwCapturePosition,
+ LPDWORD lpdwReadPosition )
{
- IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(iface);
-
+ IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
+ HRESULT hres = DS_OK;
TRACE( "(%p,%p,%p)\n", This, lpdwCapturePosition, lpdwReadPosition );
if (This->device == NULL) {
return DSERR_INVALIDPARAM;
}
- EnterCriticalSection(&This->device->lock);
+ if (This->device->driver) {
+ hres = IDsCaptureDriverBuffer_GetPosition(This->device->hwbuf, lpdwCapturePosition, lpdwReadPosition );
+ if (hres != DS_OK)
+ WARN("IDsCaptureDriverBuffer_GetPosition failed\n");
+ } else if (This->device->hwi) {
+ DWORD pos;
- if (!This->device->client) {
+ EnterCriticalSection(&This->device->lock);
+ pos = (DWORD_PTR)This->device->pwave[This->device->index].lpData - (DWORD_PTR)This->device->buffer;
+ if (lpdwCapturePosition)
+ *lpdwCapturePosition = (This->device->pwave[This->device->index].dwBufferLength + pos) % This->device->buflen;
+ if (lpdwReadPosition)
+ *lpdwReadPosition = pos;
LeaveCriticalSection(&This->device->lock);
+
+ } else {
WARN("no driver\n");
- return DSERR_NODRIVER;
+ hres = DSERR_NODRIVER;
}
- if(lpdwCapturePosition)
- *lpdwCapturePosition = This->device->write_pos_bytes;
-
- if(lpdwReadPosition)
- *lpdwReadPosition = This->device->write_pos_bytes;
-
- LeaveCriticalSection(&This->device->lock);
-
TRACE("cappos=%d readpos=%d\n", (lpdwCapturePosition?*lpdwCapturePosition:-1), (lpdwReadPosition?*lpdwReadPosition:-1));
- TRACE("returning DS_OK\n");
-
- return DS_OK;
+ TRACE("returning %08x\n", hres);
+ return hres;
}
-static HRESULT WINAPI IDirectSoundCaptureBufferImpl_GetFormat(IDirectSoundCaptureBuffer8 *iface,
- WAVEFORMATEX *lpwfxFormat, DWORD dwSizeAllocated, DWORD *lpdwSizeWritten)
+static HRESULT WINAPI
+IDirectSoundCaptureBufferImpl_GetFormat(
+ LPDIRECTSOUNDCAPTUREBUFFER8 iface,
+ LPWAVEFORMATEX lpwfxFormat,
+ DWORD dwSizeAllocated,
+ LPDWORD lpdwSizeWritten )
{
- IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(iface);
+ IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
HRESULT hres = DS_OK;
-
- TRACE("(%p,%p,0x%08x,%p)\n", This, lpwfxFormat, dwSizeAllocated, lpdwSizeWritten);
+ TRACE( "(%p,%p,0x%08x,%p)\n", This, lpwfxFormat, dwSizeAllocated,
+ lpdwSizeWritten );
if (This->device == NULL) {
WARN("invalid parameter: This->device == NULL\n");
return hres;
}
-static HRESULT WINAPI IDirectSoundCaptureBufferImpl_GetStatus(IDirectSoundCaptureBuffer8 *iface,
- DWORD *lpdwStatus)
+static HRESULT WINAPI
+IDirectSoundCaptureBufferImpl_GetStatus(
+ LPDIRECTSOUNDCAPTUREBUFFER8 iface,
+ LPDWORD lpdwStatus )
{
- IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(iface);
-
+ IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
TRACE( "(%p, %p), thread is %04x\n", This, lpdwStatus, GetCurrentThreadId() );
if (This->device == NULL) {
return DS_OK;
}
-static HRESULT WINAPI IDirectSoundCaptureBufferImpl_Initialize(IDirectSoundCaptureBuffer8 *iface,
- IDirectSoundCapture *lpDSC, const DSCBUFFERDESC *lpcDSCBDesc)
+static HRESULT WINAPI
+IDirectSoundCaptureBufferImpl_Initialize(
+ LPDIRECTSOUNDCAPTUREBUFFER8 iface,
+ LPDIRECTSOUNDCAPTURE lpDSC,
+ LPCDSCBUFFERDESC lpcDSCBDesc )
{
- IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(iface);
+ IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
FIXME( "(%p,%p,%p): stub\n", This, lpDSC, lpcDSCBDesc );
return DS_OK;
}
-static HRESULT WINAPI IDirectSoundCaptureBufferImpl_Lock(IDirectSoundCaptureBuffer8 *iface,
- DWORD dwReadCusor, DWORD dwReadBytes, void **lplpvAudioPtr1, DWORD *lpdwAudioBytes1,
- void **lplpvAudioPtr2, DWORD *lpdwAudioBytes2, DWORD dwFlags)
+static HRESULT WINAPI
+IDirectSoundCaptureBufferImpl_Lock(
+ LPDIRECTSOUNDCAPTUREBUFFER8 iface,
+ DWORD dwReadCusor,
+ DWORD dwReadBytes,
+ LPVOID* lplpvAudioPtr1,
+ LPDWORD lpdwAudioBytes1,
+ LPVOID* lplpvAudioPtr2,
+ LPDWORD lpdwAudioBytes2,
+ DWORD dwFlags )
{
- IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(iface);
HRESULT hres = DS_OK;
-
+ IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
TRACE( "(%p,%08u,%08u,%p,%p,%p,%p,0x%08x) at %d\n", This, dwReadCusor,
dwReadBytes, lplpvAudioPtr1, lpdwAudioBytes1, lplpvAudioPtr2,
lpdwAudioBytes2, dwFlags, GetTickCount() );
EnterCriticalSection(&(This->device->lock));
- if (This->device->client) {
+ if (This->device->driver) {
+ hres = IDsCaptureDriverBuffer_Lock(This->device->hwbuf, lplpvAudioPtr1,
+ lpdwAudioBytes1, lplpvAudioPtr2,
+ lpdwAudioBytes2, dwReadCusor,
+ dwReadBytes, dwFlags);
+ if (hres != DS_OK)
+ WARN("IDsCaptureDriverBuffer_Lock failed\n");
+ } else if (This->device->hwi) {
*lplpvAudioPtr1 = This->device->buffer + dwReadCusor;
if ( (dwReadCusor + dwReadBytes) > This->device->buflen) {
*lpdwAudioBytes1 = This->device->buflen - dwReadCusor;
return hres;
}
-static HRESULT WINAPI IDirectSoundCaptureBufferImpl_Start(IDirectSoundCaptureBuffer8 *iface,
- DWORD dwFlags)
+static HRESULT WINAPI
+IDirectSoundCaptureBufferImpl_Start(
+ LPDIRECTSOUNDCAPTUREBUFFER8 iface,
+ DWORD dwFlags )
{
- IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(iface);
- HRESULT hres;
-
+ HRESULT hres = DS_OK;
+ IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
TRACE( "(%p,0x%08x)\n", This, dwFlags );
if (This->device == NULL) {
return DSERR_INVALIDPARAM;
}
- if ( !This->device->client ) {
+ if ( (This->device->driver == 0) && (This->device->hwi == 0) ) {
WARN("no driver\n");
return DSERR_NODRIVER;
}
EnterCriticalSection(&(This->device->lock));
+ This->flags = dwFlags;
+ TRACE("old This->state=%s\n",captureStateString[This->device->state]);
if (This->device->state == STATE_STOPPED)
This->device->state = STATE_STARTING;
else if (This->device->state == STATE_STOPPING)
This->device->state = STATE_CAPTURING;
- else
- goto out;
TRACE("new This->device->state=%s\n",captureStateString[This->device->state]);
- This->flags = dwFlags;
- if (This->device->buffer)
- FillMemory(This->device->buffer, This->device->buflen, (This->device->pwfx->wBitsPerSample == 8) ? 128 : 0);
+ LeaveCriticalSection(&(This->device->lock));
- hres = IAudioClient_Start(This->device->client);
- if(FAILED(hres)){
- WARN("Start failed: %08x\n", hres);
- LeaveCriticalSection(&This->device->lock);
- return hres;
- }
+ if (This->device->driver) {
+ hres = IDsCaptureDriverBuffer_Start(This->device->hwbuf, dwFlags);
+ if (hres != DS_OK)
+ WARN("IDsCaptureDriverBuffer_Start failed\n");
+ } else if (This->device->hwi) {
+ DirectSoundCaptureDevice *device = This->device;
+
+ if (device->buffer) {
+ int c;
+ DWORD blocksize = DSOUND_fraglen(device->pwfx->nSamplesPerSec, device->pwfx->nBlockAlign);
+ device->nrofpwaves = device->buflen / blocksize + !!(device->buflen % blocksize);
+ TRACE("nrofpwaves=%d\n", device->nrofpwaves);
+
+ /* prepare headers */
+ if (device->pwave)
+ device->pwave = HeapReAlloc(GetProcessHeap(), 0,device->pwave, device->nrofpwaves*sizeof(WAVEHDR));
+ else
+ device->pwave = HeapAlloc(GetProcessHeap(), 0, device->nrofpwaves*sizeof(WAVEHDR));
+
+ for (c = 0; c < device->nrofpwaves; ++c) {
+ device->pwave[c].lpData = (char *)device->buffer + c * blocksize;
+ if (c + 1 == device->nrofpwaves)
+ device->pwave[c].dwBufferLength = device->buflen - c * blocksize;
+ else
+ device->pwave[c].dwBufferLength = blocksize;
+ device->pwave[c].dwBytesRecorded = 0;
+ device->pwave[c].dwUser = (DWORD_PTR)device;
+ device->pwave[c].dwFlags = 0;
+ device->pwave[c].dwLoops = 0;
+ hres = mmErr(waveInPrepareHeader(device->hwi, &(device->pwave[c]),sizeof(WAVEHDR)));
+ if (hres != DS_OK) {
+ WARN("waveInPrepareHeader failed\n");
+ while (c--)
+ waveInUnprepareHeader(device->hwi, &(device->pwave[c]),sizeof(WAVEHDR));
+ break;
+ }
+
+ hres = mmErr(waveInAddBuffer(device->hwi, &(device->pwave[c]), sizeof(WAVEHDR)));
+ if (hres != DS_OK) {
+ WARN("waveInAddBuffer failed\n");
+ while (c--)
+ waveInUnprepareHeader(device->hwi, &(device->pwave[c]),sizeof(WAVEHDR));
+ break;
+ }
+ }
-out:
- LeaveCriticalSection(&This->device->lock);
+ FillMemory(device->buffer, device->buflen, (device->pwfx->wBitsPerSample == 8) ? 128 : 0);
+ }
- TRACE("returning DS_OK\n");
- return DS_OK;
+ device->index = 0;
+
+ if (hres == DS_OK) {
+ /* start filling the first buffer */
+ hres = mmErr(waveInStart(device->hwi));
+ if (hres != DS_OK)
+ WARN("waveInStart failed\n");
+ }
+
+ if (hres != DS_OK) {
+ WARN("calling waveInClose because of error\n");
+ waveInClose(device->hwi);
+ device->hwi = 0;
+ }
+ } else {
+ WARN("no driver\n");
+ hres = DSERR_NODRIVER;
+ }
+
+ TRACE("returning %08x\n", hres);
+ return hres;
}
-static HRESULT WINAPI IDirectSoundCaptureBufferImpl_Stop(IDirectSoundCaptureBuffer8 *iface)
+static HRESULT WINAPI
+IDirectSoundCaptureBufferImpl_Stop( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
{
- IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(iface);
- HRESULT hres;
-
- TRACE("(%p)\n", This);
+ HRESULT hres = DS_OK;
+ IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
+ TRACE( "(%p)\n", This );
if (This->device == NULL) {
WARN("invalid parameter: This->device == NULL\n");
This->device->state = STATE_STOPPED;
TRACE("new This->device->state=%s\n",captureStateString[This->device->state]);
- if(This->device->client){
- hres = IAudioClient_Stop(This->device->client);
- if(FAILED(hres)){
- LeaveCriticalSection(&This->device->lock);
- return hres;
- }
- }
-
LeaveCriticalSection(&(This->device->lock));
- TRACE("returning DS_OK\n");
- return DS_OK;
+ if (This->device->driver) {
+ hres = IDsCaptureDriverBuffer_Stop(This->device->hwbuf);
+ if (hres != DS_OK)
+ WARN("IDsCaptureDriverBuffer_Stop() failed\n");
+ } else if (This->device->hwi) {
+ hres = mmErr(waveInReset(This->device->hwi));
+ if (hres != DS_OK)
+ WARN("waveInReset() failed\n");
+ } else {
+ WARN("no driver\n");
+ hres = DSERR_NODRIVER;
+ }
+
+ TRACE("returning %08x\n", hres);
+ return hres;
}
-static HRESULT WINAPI IDirectSoundCaptureBufferImpl_Unlock(IDirectSoundCaptureBuffer8 *iface,
- void *lpvAudioPtr1, DWORD dwAudioBytes1, void *lpvAudioPtr2, DWORD dwAudioBytes2)
+static HRESULT WINAPI
+IDirectSoundCaptureBufferImpl_Unlock(
+ LPDIRECTSOUNDCAPTUREBUFFER8 iface,
+ LPVOID lpvAudioPtr1,
+ DWORD dwAudioBytes1,
+ LPVOID lpvAudioPtr2,
+ DWORD dwAudioBytes2 )
{
- IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(iface);
HRESULT hres = DS_OK;
-
+ IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
TRACE( "(%p,%p,%08u,%p,%08u)\n", This, lpvAudioPtr1, dwAudioBytes1,
lpvAudioPtr2, dwAudioBytes2 );
return DSERR_INVALIDPARAM;
}
- if (!This->device->client) {
+ if (This->device->driver) {
+ hres = IDsCaptureDriverBuffer_Unlock(This->device->hwbuf, lpvAudioPtr1,
+ dwAudioBytes1, lpvAudioPtr2, dwAudioBytes2);
+ if (hres != DS_OK)
+ WARN("IDsCaptureDriverBuffer_Unlock failed\n");
+ } else if (!This->device->hwi) {
WARN("invalid call\n");
hres = DSERR_INVALIDCALL;
}
return hres;
}
-static HRESULT WINAPI IDirectSoundCaptureBufferImpl_GetObjectInPath(IDirectSoundCaptureBuffer8 *iface,
- REFGUID rguidObject, DWORD dwIndex, REFGUID rguidInterface, void **ppObject)
+static HRESULT WINAPI
+IDirectSoundCaptureBufferImpl_GetObjectInPath(
+ LPDIRECTSOUNDCAPTUREBUFFER8 iface,
+ REFGUID rguidObject,
+ DWORD dwIndex,
+ REFGUID rguidInterface,
+ LPVOID* ppObject )
{
- IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(iface);
+ IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
FIXME( "(%p,%s,%u,%s,%p): stub\n", This, debugstr_guid(rguidObject),
dwIndex, debugstr_guid(rguidInterface), ppObject );
- if (!ppObject)
- return DSERR_INVALIDPARAM;
-
- *ppObject = NULL;
- return DSERR_CONTROLUNAVAIL;
+ return DS_OK;
}
-static HRESULT WINAPI IDirectSoundCaptureBufferImpl_GetFXStatus(IDirectSoundCaptureBuffer8 *iface,
- DWORD dwFXCount, DWORD *pdwFXStatus)
+static HRESULT WINAPI
+IDirectSoundCaptureBufferImpl_GetFXStatus(
+ LPDIRECTSOUNDCAPTUREBUFFER8 iface,
+ DWORD dwFXCount,
+ LPDWORD pdwFXStatus )
{
- IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(iface);
+ IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
FIXME( "(%p,%u,%p): stub\n", This, dwFXCount, pdwFXStatus );
}
}
+static void CALLBACK
+DSOUND_capture_callback(HWAVEIN hwi, UINT msg, DWORD_PTR dwUser, DWORD_PTR dw1,
+ DWORD_PTR dw2)
+{
+ DirectSoundCaptureDevice * This = (DirectSoundCaptureDevice*)dwUser;
+ IDirectSoundCaptureBufferImpl * Moi = This->capture_buffer;
+ TRACE("(%p,%08x(%s),%08lx,%08lx,%08lx) entering at %d\n",hwi,msg,
+ msg == MM_WIM_OPEN ? "MM_WIM_OPEN" : msg == MM_WIM_CLOSE ? "MM_WIM_CLOSE" :
+ msg == MM_WIM_DATA ? "MM_WIM_DATA" : "UNKNOWN",dwUser,dw1,dw2,GetTickCount());
+
+ if (msg == MM_WIM_DATA) {
+ EnterCriticalSection( &(This->lock) );
+ TRACE("DirectSoundCapture msg=MM_WIM_DATA, old This->state=%s, old This->index=%d\n",
+ captureStateString[This->state],This->index);
+ if (This->state != STATE_STOPPED) {
+ int index = This->index;
+ if (This->state == STATE_STARTING)
+ This->state = STATE_CAPTURING;
+ capture_CheckNotify(Moi, (DWORD_PTR)This->pwave[index].lpData - (DWORD_PTR)This->buffer, This->pwave[index].dwBufferLength);
+ This->index = (This->index + 1) % This->nrofpwaves;
+ if ( (This->index == 0) && !(This->capture_buffer->flags & DSCBSTART_LOOPING) ) {
+ TRACE("end of buffer\n");
+ This->state = STATE_STOPPED;
+ capture_CheckNotify(Moi, 0, 0);
+ } else {
+ if (This->state == STATE_CAPTURING) {
+ waveInUnprepareHeader(hwi, &(This->pwave[index]), sizeof(WAVEHDR));
+ waveInPrepareHeader(hwi, &(This->pwave[index]), sizeof(WAVEHDR));
+ waveInAddBuffer(hwi, &(This->pwave[index]), sizeof(WAVEHDR));
+ } else if (This->state == STATE_STOPPING) {
+ TRACE("stopping\n");
+ This->state = STATE_STOPPED;
+ }
+ }
+ }
+ TRACE("DirectSoundCapture new This->state=%s, new This->index=%d\n",
+ captureStateString[This->state],This->index);
+ LeaveCriticalSection( &(This->lock) );
+ }
+
+ TRACE("completed\n");
+}
+
static HRESULT IDirectSoundCaptureBufferImpl_Create(
DirectSoundCaptureDevice *device,
IDirectSoundCaptureBufferImpl ** ppobj,
LPCDSCBUFFERDESC lpcDSCBufferDesc)
{
LPWAVEFORMATEX wfex;
- IDirectSoundCaptureBufferImpl *This;
TRACE( "(%p,%p,%p)\n", device, ppobj, lpcDSCBufferDesc);
if (ppobj == NULL) {
return DSERR_INVALIDPARAM;
}
- *ppobj = NULL;
-
if (!device) {
WARN("not initialized\n");
+ *ppobj = NULL;
return DSERR_UNINITIALIZED;
}
if (lpcDSCBufferDesc == NULL) {
WARN("invalid parameter: lpcDSCBufferDesc == NULL\n");
+ *ppobj = NULL;
return DSERR_INVALIDPARAM;
}
(lpcDSCBufferDesc->dwBufferBytes == 0) ||
(lpcDSCBufferDesc->lpwfxFormat == NULL) ) { /* FIXME: DSERR_BADFORMAT ? */
WARN("invalid lpcDSCBufferDesc\n");
+ *ppobj = NULL;
return DSERR_INVALIDPARAM;
}
wfex->wBitsPerSample, wfex->cbSize);
device->pwfx = DSOUND_CopyFormat(wfex);
- if ( device->pwfx == NULL )
+ if ( device->pwfx == NULL ) {
+ *ppobj = NULL;
return DSERR_OUTOFMEMORY;
+ }
- This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
+ *ppobj = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
sizeof(IDirectSoundCaptureBufferImpl));
- if ( This == NULL ) {
+ if ( *ppobj == NULL ) {
WARN("out of memory\n");
+ *ppobj = NULL;
return DSERR_OUTOFMEMORY;
} else {
- HRESULT err = DS_OK;
+ HRESULT err = DS_OK;
LPBYTE newbuf;
DWORD buflen;
+ IDirectSoundCaptureBufferImpl *This = *ppobj;
- This->numIfaces = 0;
- This->ref = 0;
- This->refn = 0;
+ This->ref = 1;
This->device = device;
This->device->capture_buffer = This;
- This->nrofnotifies = 0;
+ This->notify = NULL;
+ This->nrofnotifies = 0;
+ This->hwnotify = NULL;
This->pdscbd = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
lpcDSCBufferDesc->dwSize);
WARN("no memory\n");
This->device->capture_buffer = 0;
HeapFree( GetProcessHeap(), 0, This );
+ *ppobj = NULL;
return DSERR_OUTOFMEMORY;
}
- This->IDirectSoundCaptureBuffer8_iface.lpVtbl = &dscbvt;
- This->IDirectSoundNotify_iface.lpVtbl = &dscnvt;
-
- err = IMMDevice_Activate(device->mmdevice, &IID_IAudioClient,
- CLSCTX_INPROC_SERVER, NULL, (void**)&device->client);
- if(FAILED(err)){
- WARN("Activate failed: %08x\n", err);
- HeapFree(GetProcessHeap(), 0, This->pdscbd);
- This->device->capture_buffer = 0;
- HeapFree( GetProcessHeap(), 0, This );
- return err;
- }
-
- err = IAudioClient_Initialize(device->client,
- AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_NOPERSIST,
- 200 * 100000, 50000, device->pwfx, NULL);
- if(FAILED(err)){
- WARN("Initialize failed: %08x\n", err);
- IAudioClient_Release(device->client);
- device->client = NULL;
- HeapFree(GetProcessHeap(), 0, This->pdscbd);
- This->device->capture_buffer = 0;
- HeapFree( GetProcessHeap(), 0, This );
- if(err == AUDCLNT_E_UNSUPPORTED_FORMAT)
- return DSERR_BADFORMAT;
- return err;
- }
+ This->lpVtbl = &dscbvt;
+
+ if (device->driver) {
+ if (This->device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
+ FIXME("DSDDESC_DOMMSYSTEMOPEN not supported\n");
+
+ if (This->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
+ /* allocate buffer from system memory */
+ buflen = lpcDSCBufferDesc->dwBufferBytes;
+ TRACE("desired buflen=%d, old buffer=%p\n", buflen, device->buffer);
+ if (device->buffer)
+ newbuf = HeapReAlloc(GetProcessHeap(),0,device->buffer,buflen);
+ else
+ newbuf = HeapAlloc(GetProcessHeap(),0,buflen);
+
+ if (newbuf == NULL) {
+ WARN("failed to allocate capture buffer\n");
+ err = DSERR_OUTOFMEMORY;
+ /* but the old buffer might still exist and must be re-prepared */
+ } else {
+ device->buffer = newbuf;
+ device->buflen = buflen;
+ }
+ } else {
+ /* let driver allocate memory */
+ device->buflen = lpcDSCBufferDesc->dwBufferBytes;
+ /* FIXME: */
+ HeapFree( GetProcessHeap(), 0, device->buffer);
+ device->buffer = NULL;
+ }
- err = IAudioClient_GetService(device->client, &IID_IAudioCaptureClient,
- (void**)&device->capture);
- if(FAILED(err)){
- WARN("GetService failed: %08x\n", err);
- IAudioClient_Release(device->client);
- device->client = NULL;
- HeapFree(GetProcessHeap(), 0, This->pdscbd);
- This->device->capture_buffer = 0;
- HeapFree( GetProcessHeap(), 0, This );
- return err;
- }
+ err = IDsCaptureDriver_CreateCaptureBuffer(device->driver,
+ device->pwfx,0,0,&(device->buflen),&(device->buffer),(LPVOID*)&(device->hwbuf));
+ if (err != DS_OK) {
+ WARN("IDsCaptureDriver_CreateCaptureBuffer failed\n");
+ This->device->capture_buffer = 0;
+ HeapFree( GetProcessHeap(), 0, This );
+ *ppobj = NULL;
+ return err;
+ }
+ } else {
+ DWORD flags = CALLBACK_FUNCTION | WAVE_MAPPED;
+ err = mmErr(waveInOpen(&(device->hwi),
+ device->drvdesc.dnDevNode, device->pwfx,
+ (DWORD_PTR)DSOUND_capture_callback, (DWORD_PTR)device, flags));
+ if (err != DS_OK) {
+ WARN("waveInOpen failed\n");
+ This->device->capture_buffer = 0;
+ HeapFree( GetProcessHeap(), 0, This );
+ *ppobj = NULL;
+ return err;
+ }
- buflen = lpcDSCBufferDesc->dwBufferBytes;
- TRACE("desired buflen=%d, old buffer=%p\n", buflen, device->buffer);
- if (device->buffer)
- newbuf = HeapReAlloc(GetProcessHeap(),0,device->buffer,buflen);
- else
- newbuf = HeapAlloc(GetProcessHeap(),0,buflen);
- if (newbuf == NULL) {
- IAudioClient_Release(device->client);
- device->client = NULL;
- IAudioCaptureClient_Release(device->capture);
- device->capture = NULL;
- HeapFree(GetProcessHeap(), 0, This->pdscbd);
- This->device->capture_buffer = 0;
- HeapFree( GetProcessHeap(), 0, This );
- return DSERR_OUTOFMEMORY;
- }
- device->buffer = newbuf;
- device->buflen = buflen;
+ buflen = lpcDSCBufferDesc->dwBufferBytes;
+ TRACE("desired buflen=%d, old buffer=%p\n", buflen, device->buffer);
+ if (device->buffer)
+ newbuf = HeapReAlloc(GetProcessHeap(),0,device->buffer,buflen);
+ else
+ newbuf = HeapAlloc(GetProcessHeap(),0,buflen);
+ if (newbuf == NULL) {
+ WARN("failed to allocate capture buffer\n");
+ err = DSERR_OUTOFMEMORY;
+ /* but the old buffer might still exist and must be re-prepared */
+ } else {
+ device->buffer = newbuf;
+ device->buflen = buflen;
+ }
+ }
}
- IDirectSoundCaptureBuffer_AddRef(&This->IDirectSoundCaptureBuffer8_iface);
- *ppobj = This;
-
TRACE("returning DS_OK\n");
return DS_OK;
}
/*******************************************************************************
* DirectSoundCaptureDevice
*/
+DirectSoundCaptureDevice * DSOUND_capture[MAXWAVEDRIVERS];
+
static HRESULT DirectSoundCaptureDevice_Create(
DirectSoundCaptureDevice ** ppDevice)
{
if (!ref) {
TRACE("deleting object\n");
-
- timeKillEvent(device->timerID);
- timeEndPeriod(DS_TIME_RES);
-
- EnterCriticalSection(&DSOUND_capturers_lock);
- list_remove(&device->entry);
- LeaveCriticalSection(&DSOUND_capturers_lock);
-
if (device->capture_buffer)
- IDirectSoundCaptureBufferImpl_Release(&device->capture_buffer->IDirectSoundCaptureBuffer8_iface);
+ IDirectSoundCaptureBufferImpl_Release(
+ (LPDIRECTSOUNDCAPTUREBUFFER8) device->capture_buffer);
+
+ if (device->driver) {
+ IDsCaptureDriver_Close(device->driver);
+ IDsCaptureDriver_Release(device->driver);
+ }
- if(device->mmdevice)
- IMMDevice_Release(device->mmdevice);
HeapFree(GetProcessHeap(), 0, device->pwfx);
device->lock.DebugInfo->Spare[0] = 0;
DeleteCriticalSection( &(device->lock) );
+ DSOUND_capture[device->drvdesc.dnDevNode] = NULL;
HeapFree(GetProcessHeap(), 0, device);
TRACE("(%p) released\n", device);
}
return ref;
}
-static void CALLBACK DSOUND_capture_timer(UINT timerID, UINT msg, DWORD_PTR user,
- DWORD_PTR dw1, DWORD_PTR dw2)
-{
- DirectSoundCaptureDevice *device = (DirectSoundCaptureDevice*)user;
- UINT32 packet_frames, packet_bytes, avail_bytes;
- DWORD flags;
- BYTE *buf;
- HRESULT hr;
-
- if(!device->ref)
- return;
-
- EnterCriticalSection(&device->lock);
-
- if(!device->capture_buffer || device->state == STATE_STOPPED){
- LeaveCriticalSection(&device->lock);
- return;
- }
-
- if(device->state == STATE_STOPPING){
- device->state = STATE_STOPPED;
- LeaveCriticalSection(&device->lock);
- return;
- }
-
- if(device->state == STATE_STARTING)
- device->state = STATE_CAPTURING;
-
- hr = IAudioCaptureClient_GetBuffer(device->capture, &buf, &packet_frames,
- &flags, NULL, NULL);
- if(FAILED(hr)){
- LeaveCriticalSection(&device->lock);
- WARN("GetBuffer failed: %08x\n", hr);
- return;
- }
-
- packet_bytes = packet_frames * device->pwfx->nBlockAlign;
-
- avail_bytes = device->buflen - device->write_pos_bytes;
- if(avail_bytes > packet_bytes)
- avail_bytes = packet_bytes;
-
- memcpy(device->buffer + device->write_pos_bytes, buf, avail_bytes);
- capture_CheckNotify(device->capture_buffer, device->write_pos_bytes, avail_bytes);
-
- packet_bytes -= avail_bytes;
- if(packet_bytes > 0){
- if(device->capture_buffer->flags & DSCBSTART_LOOPING){
- memcpy(device->buffer, buf + avail_bytes, packet_bytes);
- capture_CheckNotify(device->capture_buffer, 0, packet_bytes);
- }else{
- device->state = STATE_STOPPED;
- capture_CheckNotify(device->capture_buffer, 0, 0);
- }
- }
-
- device->write_pos_bytes += avail_bytes + packet_bytes;
- device->write_pos_bytes %= device->buflen;
-
- hr = IAudioCaptureClient_ReleaseBuffer(device->capture, packet_frames);
- if(FAILED(hr)){
- LeaveCriticalSection(&device->lock);
- WARN("ReleaseBuffer failed: %08x\n", hr);
- return;
- }
-
- LeaveCriticalSection(&device->lock);
-}
-
-static struct _TestFormat {
- DWORD flag;
- DWORD rate;
- DWORD depth;
- WORD channels;
-} formats_to_test[] = {
- { WAVE_FORMAT_1M08, 11025, 8, 1 },
- { WAVE_FORMAT_1M16, 11025, 16, 1 },
- { WAVE_FORMAT_1S08, 11025, 8, 2 },
- { WAVE_FORMAT_1S16, 11025, 16, 2 },
- { WAVE_FORMAT_2M08, 22050, 8, 1 },
- { WAVE_FORMAT_2M16, 22050, 16, 1 },
- { WAVE_FORMAT_2S08, 22050, 8, 2 },
- { WAVE_FORMAT_2S16, 22050, 16, 2 },
- { WAVE_FORMAT_4M08, 44100, 8, 1 },
- { WAVE_FORMAT_4M16, 44100, 16, 1 },
- { WAVE_FORMAT_4S08, 44100, 8, 2 },
- { WAVE_FORMAT_4S16, 44100, 16, 2 },
- { WAVE_FORMAT_48M08, 48000, 8, 1 },
- { WAVE_FORMAT_48M16, 48000, 16, 1 },
- { WAVE_FORMAT_48S08, 48000, 8, 2 },
- { WAVE_FORMAT_48S16, 48000, 16, 2 },
- { WAVE_FORMAT_96M08, 96000, 8, 1 },
- { WAVE_FORMAT_96M16, 96000, 16, 1 },
- { WAVE_FORMAT_96S08, 96000, 8, 2 },
- { WAVE_FORMAT_96S16, 96000, 16, 2 },
- {0}
-};
-
static HRESULT DirectSoundCaptureDevice_Initialize(
DirectSoundCaptureDevice ** ppDevice,
LPCGUID lpcGUID)
{
- HRESULT hr;
+ HRESULT err = DSERR_INVALIDPARAM;
+ unsigned wid, widn;
+ BOOLEAN found = FALSE;
GUID devGUID;
- IMMDevice *mmdevice;
- struct _TestFormat *fmt;
- DirectSoundCaptureDevice *device;
- IAudioClient *client;
-
+ DirectSoundCaptureDevice *device = *ppDevice;
TRACE("(%p, %s)\n", ppDevice, debugstr_guid(lpcGUID));
/* Default device? */
if ( !lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL) )
- lpcGUID = &DSDEVID_DefaultCapture;
-
- if(IsEqualGUID(lpcGUID, &DSDEVID_DefaultPlayback) ||
- IsEqualGUID(lpcGUID, &DSDEVID_DefaultVoicePlayback))
- return DSERR_NODRIVER;
+ lpcGUID = &DSDEVID_DefaultCapture;
if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) {
WARN("invalid parameter: lpcGUID\n");
return DSERR_INVALIDPARAM;
}
- hr = get_mmdevice(eCapture, &devGUID, &mmdevice);
- if(FAILED(hr))
- return hr;
+ widn = waveInGetNumDevs();
+ if (!widn) {
+ WARN("no audio devices found\n");
+ return DSERR_NODRIVER;
+ }
- EnterCriticalSection(&DSOUND_capturers_lock);
+ /* enumerate WINMM audio devices and find the one we want */
+ for (wid=0; wid<widn; wid++) {
+ if (IsEqualGUID( &devGUID, &DSOUND_capture_guids[wid]) ) {
+ found = TRUE;
+ break;
+ }
+ }
- LIST_FOR_EACH_ENTRY(device, &DSOUND_capturers, DirectSoundCaptureDevice, entry){
- if(IsEqualGUID(&device->guid, &devGUID)){
- IMMDevice_Release(mmdevice);
- LeaveCriticalSection(&DSOUND_capturers_lock);
- return DSERR_ALLOCATED;
- }
+ if (found == FALSE) {
+ WARN("No device found matching given ID!\n");
+ return DSERR_NODRIVER;
+ }
+
+ if (DSOUND_capture[wid]) {
+ WARN("already in use\n");
+ return DSERR_ALLOCATED;
}
- hr = DirectSoundCaptureDevice_Create(&device);
- if (hr != DS_OK) {
+ err = DirectSoundCaptureDevice_Create(&(device));
+ if (err != DS_OK) {
WARN("DirectSoundCaptureDevice_Create failed\n");
- LeaveCriticalSection(&DSOUND_capturers_lock);
- return hr;
+ return err;
}
+ *ppDevice = device;
device->guid = devGUID;
- device->mmdevice = mmdevice;
-
- device->drvcaps.dwFlags = 0;
-
- device->drvcaps.dwFormats = 0;
- device->drvcaps.dwChannels = 0;
- hr = IMMDevice_Activate(mmdevice, &IID_IAudioClient,
- CLSCTX_INPROC_SERVER, NULL, (void**)&client);
- if(FAILED(hr)){
- device->lock.DebugInfo->Spare[0] = 0;
- DeleteCriticalSection(&device->lock);
- HeapFree(GetProcessHeap(), 0, device);
- LeaveCriticalSection(&DSOUND_capturers_lock);
- return DSERR_NODRIVER;
+ /* Disable the direct sound driver to force emulation if requested. */
+ device->driver = NULL;
+ if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
+ {
+ err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDIFACE,(DWORD_PTR)&device->driver,0));
+ if ( (err != DS_OK) && (err != DSERR_UNSUPPORTED) ) {
+ WARN("waveInMessage failed; err=%x\n",err);
+ return err;
+ }
}
+ err = DS_OK;
- for(fmt = formats_to_test; fmt->flag; ++fmt){
- if(DSOUND_check_supported(client, fmt->rate, fmt->depth, fmt->channels)){
- device->drvcaps.dwFormats |= fmt->flag;
- if(fmt->channels > device->drvcaps.dwChannels)
- device->drvcaps.dwChannels = fmt->channels;
+ /* Get driver description */
+ if (device->driver) {
+ TRACE("using DirectSound driver\n");
+ err = IDsCaptureDriver_GetDriverDesc(device->driver, &(device->drvdesc));
+ if (err != DS_OK) {
+ WARN("IDsCaptureDriver_GetDriverDesc failed\n");
+ return err;
+ }
+ } else {
+ TRACE("using WINMM\n");
+ /* if no DirectSound interface available, use WINMM API instead */
+ device->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN |
+ DSDDESC_DOMMSYSTEMSETFORMAT;
+ }
+
+ device->drvdesc.dnDevNode = wid;
+
+ /* open the DirectSound driver if available */
+ if (device->driver && (err == DS_OK))
+ err = IDsCaptureDriver_Open(device->driver);
+
+ if (err == DS_OK) {
+ *ppDevice = device;
+
+ /* the driver is now open, so it's now allowed to call GetCaps */
+ if (device->driver) {
+ device->drvcaps.dwSize = sizeof(device->drvcaps);
+ err = IDsCaptureDriver_GetCaps(device->driver,&(device->drvcaps));
+ if (err != DS_OK) {
+ WARN("IDsCaptureDriver_GetCaps failed\n");
+ return err;
+ }
+ } else /*if (device->hwi)*/ {
+ WAVEINCAPSA wic;
+ err = mmErr(waveInGetDevCapsA((UINT)device->drvdesc.dnDevNode, &wic, sizeof(wic)));
+
+ if (err == DS_OK) {
+ device->drvcaps.dwFlags = 0;
+ lstrcpynA(device->drvdesc.szDrvname, wic.szPname,
+ sizeof(device->drvdesc.szDrvname));
+
+ device->drvcaps.dwFlags |= DSCCAPS_EMULDRIVER;
+ device->drvcaps.dwFormats = wic.dwFormats;
+ device->drvcaps.dwChannels = wic.wChannels;
+ }
}
}
- IAudioClient_Release(client);
-
- device->timerID = DSOUND_create_timer(DSOUND_capture_timer, (DWORD_PTR)device);
-
- list_add_tail(&DSOUND_capturers, &device->entry);
- *ppDevice = device;
-
- LeaveCriticalSection(&DSOUND_capturers_lock);
-
- return S_OK;
+ return err;
}
/*****************************************************************************
* IDirectSoundCapture implementation structure
*/
-typedef struct IDirectSoundCaptureImpl
-{
- IUnknown IUnknown_inner;
- IDirectSoundCapture IDirectSoundCapture_iface;
- LONG ref, refdsc, numIfaces;
- IUnknown *outer_unk; /* internal */
- DirectSoundCaptureDevice *device;
- BOOL has_dsc8;
-} IDirectSoundCaptureImpl;
-
-static void capture_destroy(IDirectSoundCaptureImpl *This)
-{
- if (This->device)
- DirectSoundCaptureDevice_Release(This->device);
- HeapFree(GetProcessHeap(),0,This);
- TRACE("(%p) released\n", This);
-}
-
-/*******************************************************************************
- * IUnknown Implementation for DirectSoundCapture
- */
-static inline IDirectSoundCaptureImpl *impl_from_IUnknown(IUnknown *iface)
-{
- return CONTAINING_RECORD(iface, IDirectSoundCaptureImpl, IUnknown_inner);
-}
-
-static HRESULT WINAPI IUnknownImpl_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
-{
- IDirectSoundCaptureImpl *This = impl_from_IUnknown(iface);
-
- TRACE("(%p,%s,%p)\n", This, debugstr_guid(riid), ppv);
-
- if (!ppv) {
- WARN("invalid parameter\n");
- return E_INVALIDARG;
- }
- *ppv = NULL;
-
- if (IsEqualIID(riid, &IID_IUnknown))
- *ppv = &This->IUnknown_inner;
- else if (IsEqualIID(riid, &IID_IDirectSoundCapture))
- *ppv = &This->IDirectSoundCapture_iface;
- else {
- WARN("unknown IID %s\n", debugstr_guid(riid));
- return E_NOINTERFACE;
- }
-
- IUnknown_AddRef((IUnknown*)*ppv);
- return S_OK;
-}
-
-static ULONG WINAPI IUnknownImpl_AddRef(IUnknown *iface)
+struct IDirectSoundCaptureImpl
{
- IDirectSoundCaptureImpl *This = impl_from_IUnknown(iface);
- ULONG ref = InterlockedIncrement(&This->ref);
-
- TRACE("(%p) ref=%d\n", This, ref);
-
- if(ref == 1)
- InterlockedIncrement(&This->numIfaces);
- return ref;
-}
+ /* IUnknown fields */
+ const IDirectSoundCaptureVtbl *lpVtbl;
+ LONG ref;
-static ULONG WINAPI IUnknownImpl_Release(IUnknown *iface)
-{
- IDirectSoundCaptureImpl *This = impl_from_IUnknown(iface);
- ULONG ref = InterlockedDecrement(&This->ref);
-
- TRACE("(%p) ref=%d\n", This, ref);
-
- if (!ref && !InterlockedDecrement(&This->numIfaces))
- capture_destroy(This);
- return ref;
-}
-
-static const IUnknownVtbl unk_vtbl =
-{
- IUnknownImpl_QueryInterface,
- IUnknownImpl_AddRef,
- IUnknownImpl_Release
+ DirectSoundCaptureDevice *device;
};
/***************************************************************************
* IDirectSoundCaptureImpl
*/
-static inline struct IDirectSoundCaptureImpl *impl_from_IDirectSoundCapture(IDirectSoundCapture *iface)
+static HRESULT WINAPI
+IDirectSoundCaptureImpl_QueryInterface(
+ LPDIRECTSOUNDCAPTURE iface,
+ REFIID riid,
+ LPVOID* ppobj )
{
- return CONTAINING_RECORD(iface, struct IDirectSoundCaptureImpl, IDirectSoundCapture_iface);
-}
+ IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
+ TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
-static HRESULT WINAPI IDirectSoundCaptureImpl_QueryInterface(IDirectSoundCapture *iface,
- REFIID riid, void **ppv)
-{
- IDirectSoundCaptureImpl *This = impl_from_IDirectSoundCapture(iface);
- TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
- return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
-}
+ if (ppobj == NULL) {
+ WARN("invalid parameter\n");
+ return E_INVALIDARG;
+ }
-static ULONG WINAPI IDirectSoundCaptureImpl_AddRef(IDirectSoundCapture *iface)
-{
- IDirectSoundCaptureImpl *This = impl_from_IDirectSoundCapture(iface);
- ULONG ref = InterlockedIncrement(&This->refdsc);
+ *ppobj = NULL;
- TRACE("(%p) ref=%d\n", This, ref);
+ if (IsEqualIID(riid, &IID_IUnknown)) {
+ IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE)This);
+ *ppobj = This;
+ return DS_OK;
+ } else if (IsEqualIID(riid, &IID_IDirectSoundCapture)) {
+ IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE)This);
+ *ppobj = This;
+ return DS_OK;
+ }
- if(ref == 1)
- InterlockedIncrement(&This->numIfaces);
+ WARN("unsupported riid: %s\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI
+IDirectSoundCaptureImpl_AddRef( LPDIRECTSOUNDCAPTURE iface )
+{
+ IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
+ ULONG ref = InterlockedIncrement(&(This->ref));
+ TRACE("(%p) ref was %d\n", This, ref - 1);
return ref;
}
-static ULONG WINAPI IDirectSoundCaptureImpl_Release(IDirectSoundCapture *iface)
+static ULONG WINAPI
+IDirectSoundCaptureImpl_Release( LPDIRECTSOUNDCAPTURE iface )
{
- IDirectSoundCaptureImpl *This = impl_from_IDirectSoundCapture(iface);
- ULONG ref = InterlockedDecrement(&This->refdsc);
+ IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
+ ULONG ref = InterlockedDecrement(&(This->ref));
+ TRACE("(%p) ref was %d\n", This, ref + 1);
- TRACE("(%p) ref=%d\n", This, ref);
+ if (!ref) {
+ if (This->device)
+ DirectSoundCaptureDevice_Release(This->device);
- if (!ref && !InterlockedDecrement(&This->numIfaces))
- capture_destroy(This);
+ HeapFree( GetProcessHeap(), 0, This );
+ TRACE("(%p) released\n", This);
+ }
return ref;
}
-static HRESULT WINAPI IDirectSoundCaptureImpl_CreateCaptureBuffer(IDirectSoundCapture *iface,
- LPCDSCBUFFERDESC lpcDSCBufferDesc, IDirectSoundCaptureBuffer **lplpDSCaptureBuffer,
- IUnknown *pUnk)
+static HRESULT WINAPI IDirectSoundCaptureImpl_CreateCaptureBuffer(
+ LPDIRECTSOUNDCAPTURE iface,
+ LPCDSCBUFFERDESC lpcDSCBufferDesc,
+ LPDIRECTSOUNDCAPTUREBUFFER* lplpDSCaptureBuffer,
+ LPUNKNOWN pUnk )
{
- IDirectSoundCaptureImpl *This = impl_from_IDirectSoundCapture(iface);
HRESULT hr;
+ IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
TRACE( "(%p,%p,%p,%p)\n",iface,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
- if (pUnk) {
- WARN("invalid parameter: pUnk != NULL\n");
- return DSERR_NOAGGREGATION;
- }
-
if (lpcDSCBufferDesc == NULL) {
WARN("invalid parameter: lpcDSCBufferDesc == NULL)\n");
return DSERR_INVALIDPARAM;
return hr;
}
-static HRESULT WINAPI IDirectSoundCaptureImpl_GetCaps(IDirectSoundCapture *iface,
- LPDSCCAPS lpDSCCaps)
+static HRESULT WINAPI IDirectSoundCaptureImpl_GetCaps(
+ LPDIRECTSOUNDCAPTURE iface,
+ LPDSCCAPS lpDSCCaps )
{
- IDirectSoundCaptureImpl *This = impl_from_IDirectSoundCapture(iface);
-
+ IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
TRACE("(%p,%p)\n",This,lpDSCCaps);
if (This->device == NULL) {
return DS_OK;
}
-static HRESULT WINAPI IDirectSoundCaptureImpl_Initialize(IDirectSoundCapture *iface,
- LPCGUID lpcGUID)
+static HRESULT WINAPI IDirectSoundCaptureImpl_Initialize(
+ LPDIRECTSOUNDCAPTURE iface,
+ LPCGUID lpcGUID )
{
- IDirectSoundCaptureImpl *This = impl_from_IDirectSoundCapture(iface);
-
+ IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
TRACE("(%p,%s)\n", This, debugstr_guid(lpcGUID));
if (This->device != NULL) {
IDirectSoundCaptureImpl_Initialize
};
-HRESULT IDirectSoundCaptureImpl_Create(IUnknown *outer_unk, REFIID riid, void **ppv, BOOL has_dsc8)
+static HRESULT IDirectSoundCaptureImpl_Create(
+ LPDIRECTSOUNDCAPTURE8 * ppDSC)
{
- IDirectSoundCaptureImpl *obj;
- HRESULT hr;
-
- TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
+ IDirectSoundCaptureImpl *pDSC;
+ TRACE("(%p)\n", ppDSC);
- *ppv = NULL;
- obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
- if (obj == NULL) {
+ /* Allocate memory */
+ pDSC = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundCaptureImpl));
+ if (pDSC == NULL) {
WARN("out of memory\n");
+ *ppDSC = NULL;
return DSERR_OUTOFMEMORY;
}
- setup_dsound_options();
+ pDSC->lpVtbl = &dscvt;
+ pDSC->ref = 0;
+ pDSC->device = NULL;
- obj->IUnknown_inner.lpVtbl = &unk_vtbl;
- obj->IDirectSoundCapture_iface.lpVtbl = &dscvt;
- obj->ref = 1;
- obj->refdsc = 0;
- obj->numIfaces = 1;
- obj->device = NULL;
- obj->has_dsc8 = has_dsc8;
+ *ppDSC = (LPDIRECTSOUNDCAPTURE8)pDSC;
- /* COM aggregation supported only internally */
- if (outer_unk)
- obj->outer_unk = outer_unk;
- else
- obj->outer_unk = &obj->IUnknown_inner;
+ return DS_OK;
+}
- hr = IUnknown_QueryInterface(&obj->IUnknown_inner, riid, ppv);
- IUnknown_Release(&obj->IUnknown_inner);
+HRESULT DSOUND_CaptureCreate(
+ REFIID riid,
+ LPDIRECTSOUNDCAPTURE *ppDSC)
+{
+ LPDIRECTSOUNDCAPTURE pDSC;
+ HRESULT hr;
+ TRACE("(%s, %p)\n", debugstr_guid(riid), ppDSC);
+
+ if (!IsEqualIID(riid, &IID_IUnknown) &&
+ !IsEqualIID(riid, &IID_IDirectSoundCapture)) {
+ *ppDSC = 0;
+ return E_NOINTERFACE;
+ }
+
+ /* Get dsound configuration */
+ setup_dsound_options();
+
+ hr = IDirectSoundCaptureImpl_Create(&pDSC);
+ if (hr == DS_OK) {
+ IDirectSoundCapture_AddRef(pDSC);
+ *ppDSC = pDSC;
+ } else {
+ WARN("IDirectSoundCaptureImpl_Create failed\n");
+ *ppDSC = 0;
+ }
return hr;
}
-HRESULT DSOUND_CaptureCreate(REFIID riid, void **ppv)
+HRESULT DSOUND_CaptureCreate8(
+ REFIID riid,
+ LPDIRECTSOUNDCAPTURE8 *ppDSC8)
{
- return IDirectSoundCaptureImpl_Create(NULL, riid, ppv, FALSE);
-}
+ LPDIRECTSOUNDCAPTURE8 pDSC8;
+ HRESULT hr;
+ TRACE("(%s, %p)\n", debugstr_guid(riid), ppDSC8);
-HRESULT DSOUND_CaptureCreate8(REFIID riid, void **ppv)
-{
- return IDirectSoundCaptureImpl_Create(NULL, riid, ppv, TRUE);
+ if (!IsEqualIID(riid, &IID_IUnknown) &&
+ !IsEqualIID(riid, &IID_IDirectSoundCapture8)) {
+ *ppDSC8 = 0;
+ return E_NOINTERFACE;
+ }
+
+ /* Get dsound configuration */
+ setup_dsound_options();
+
+ hr = IDirectSoundCaptureImpl_Create(&pDSC8);
+ if (hr == DS_OK) {
+ IDirectSoundCapture_AddRef(pDSC8);
+ *ppDSC8 = pDSC8;
+ } else {
+ WARN("IDirectSoundCaptureImpl_Create failed\n");
+ *ppDSC8 = 0;
+ }
+
+ return hr;
}
/***************************************************************************
*
* DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
*/
-HRESULT WINAPI DirectSoundCaptureCreate(LPCGUID lpcGUID, IDirectSoundCapture **ppDSC,
- IUnknown *pUnkOuter)
+HRESULT WINAPI DirectSoundCaptureCreate(
+ LPCGUID lpcGUID,
+ LPDIRECTSOUNDCAPTURE *ppDSC,
+ LPUNKNOWN pUnkOuter)
{
HRESULT hr;
- IDirectSoundCapture *pDSC;
-
+ LPDIRECTSOUNDCAPTURE pDSC;
TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID), ppDSC, pUnkOuter);
if (ppDSC == NULL) {
if (pUnkOuter) {
WARN("invalid parameter: pUnkOuter != NULL\n");
+ *ppDSC = NULL;
return DSERR_NOAGGREGATION;
}
- hr = DSOUND_CaptureCreate(&IID_IDirectSoundCapture, (void**)&pDSC);
+ hr = DSOUND_CaptureCreate(&IID_IDirectSoundCapture, &pDSC);
if (hr == DS_OK) {
hr = IDirectSoundCapture_Initialize(pDSC, lpcGUID);
if (hr != DS_OK) {
return DSERR_NOAGGREGATION;
}
- hr = DSOUND_CaptureCreate8(&IID_IDirectSoundCapture8, (void**)&pDSC8);
+ hr = DSOUND_CaptureCreate8(&IID_IDirectSoundCapture8, &pDSC8);
if (hr == DS_OK) {
hr = IDirectSoundCapture_Initialize(pDSC8, lpcGUID);
if (hr != DS_OK) {
#include "dsound_private.h"
-typedef struct IDirectSoundImpl {
- IUnknown IUnknown_inner;
- IDirectSound8 IDirectSound8_iface;
- IUnknown *outer_unk; /* internal */
- LONG ref, refds, numIfaces;
- DirectSoundDevice *device;
- BOOL has_ds8;
-} IDirectSoundImpl;
+/*****************************************************************************
+ * IDirectSound COM components
+ */
+struct IDirectSound_IUnknown {
+ const IUnknownVtbl *lpVtbl;
+ LONG ref;
+ LPDIRECTSOUND8 pds;
+};
+
+static HRESULT IDirectSound_IUnknown_Create(LPDIRECTSOUND8 pds, LPUNKNOWN * ppunk);
+
+struct IDirectSound_IDirectSound {
+ const IDirectSoundVtbl *lpVtbl;
+ LONG ref;
+ LPDIRECTSOUND8 pds;
+};
+
+static HRESULT IDirectSound_IDirectSound_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND * ppds);
+
+/*****************************************************************************
+ * IDirectSound8 COM components
+ */
+struct IDirectSound8_IUnknown {
+ const IUnknownVtbl *lpVtbl;
+ LONG ref;
+ LPDIRECTSOUND8 pds;
+};
+
+static HRESULT IDirectSound8_IUnknown_Create(LPDIRECTSOUND8 pds, LPUNKNOWN * ppunk);
+static ULONG WINAPI IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface);
+
+struct IDirectSound8_IDirectSound {
+ const IDirectSoundVtbl *lpVtbl;
+ LONG ref;
+ LPDIRECTSOUND8 pds;
+};
+
+static HRESULT IDirectSound8_IDirectSound_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND * ppds);
+static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface);
+
+struct IDirectSound8_IDirectSound8 {
+ const IDirectSound8Vtbl *lpVtbl;
+ LONG ref;
+ LPDIRECTSOUND8 pds;
+};
-static const char * dumpCooperativeLevel(DWORD level)
+static HRESULT IDirectSound8_IDirectSound8_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND8 * ppds);
+static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface);
+
+/*****************************************************************************
+ * IDirectSound implementation structure
+ */
+struct IDirectSoundImpl
+{
+ LONG ref;
+
+ DirectSoundDevice *device;
+ LPUNKNOWN pUnknown;
+ LPDIRECTSOUND pDS;
+ LPDIRECTSOUND8 pDS8;
+};
+
+static HRESULT IDirectSoundImpl_Create(LPDIRECTSOUND8 * ppds);
+
+static ULONG WINAPI IDirectSound_IUnknown_AddRef(LPUNKNOWN iface);
+static ULONG WINAPI IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface);
+
+const char * dumpCooperativeLevel(DWORD level)
{
#define LE(x) case x: return #x
switch (level) {
TRACE("%s ",flags[i].name);
}
-static void directsound_destroy(IDirectSoundImpl *This)
-{
- if (This->device)
- DirectSoundDevice_Release(This->device);
- HeapFree(GetProcessHeap(),0,This);
- TRACE("(%p) released\n", This);
-}
-
/*******************************************************************************
- * IUnknown Implementation for DirectSound
+ * IDirectSoundImpl_DirectSound
*/
-static inline IDirectSoundImpl *impl_from_IUnknown(IUnknown *iface)
+static HRESULT DSOUND_QueryInterface(
+ LPDIRECTSOUND8 iface,
+ REFIID riid,
+ LPVOID * ppobj)
{
- return CONTAINING_RECORD(iface, IDirectSoundImpl, IUnknown_inner);
+ IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
+ TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+
+ if (ppobj == NULL) {
+ WARN("invalid parameter\n");
+ return E_INVALIDARG;
+ }
+
+ if (IsEqualIID(riid, &IID_IUnknown)) {
+ if (!This->pUnknown) {
+ IDirectSound_IUnknown_Create(iface, &This->pUnknown);
+ if (!This->pUnknown) {
+ WARN("IDirectSound_IUnknown_Create() failed\n");
+ *ppobj = NULL;
+ return E_NOINTERFACE;
+ }
+ }
+ IDirectSound_IUnknown_AddRef(This->pUnknown);
+ *ppobj = This->pUnknown;
+ return S_OK;
+ } else if (IsEqualIID(riid, &IID_IDirectSound)) {
+ if (!This->pDS) {
+ IDirectSound_IDirectSound_Create(iface, &This->pDS);
+ if (!This->pDS) {
+ WARN("IDirectSound_IDirectSound_Create() failed\n");
+ *ppobj = NULL;
+ return E_NOINTERFACE;
+ }
+ }
+ IDirectSound_IDirectSound_AddRef(This->pDS);
+ *ppobj = This->pDS;
+ return S_OK;
+ }
+
+ *ppobj = NULL;
+ WARN("Unknown IID %s\n",debugstr_guid(riid));
+ return E_NOINTERFACE;
}
-static HRESULT WINAPI IUnknownImpl_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
+static HRESULT DSOUND_QueryInterface8(
+ LPDIRECTSOUND8 iface,
+ REFIID riid,
+ LPVOID * ppobj)
{
- IDirectSoundImpl *This = impl_from_IUnknown(iface);
-
- TRACE("(%p,%s,%p)\n", This, debugstr_guid(riid), ppv);
+ IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
+ TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
- if (!ppv) {
+ if (ppobj == NULL) {
WARN("invalid parameter\n");
return E_INVALIDARG;
}
- *ppv = NULL;
- if (IsEqualIID(riid, &IID_IUnknown))
- *ppv = &This->IUnknown_inner;
- else if (IsEqualIID(riid, &IID_IDirectSound) ||
- (IsEqualIID(riid, &IID_IDirectSound8) && This->has_ds8))
- *ppv = &This->IDirectSound8_iface;
- else {
- WARN("unknown IID %s\n", debugstr_guid(riid));
- return E_NOINTERFACE;
+ if (IsEqualIID(riid, &IID_IUnknown)) {
+ if (!This->pUnknown) {
+ IDirectSound8_IUnknown_Create(iface, &This->pUnknown);
+ if (!This->pUnknown) {
+ WARN("IDirectSound8_IUnknown_Create() failed\n");
+ *ppobj = NULL;
+ return E_NOINTERFACE;
+ }
+ }
+ IDirectSound8_IUnknown_AddRef(This->pUnknown);
+ *ppobj = This->pUnknown;
+ return S_OK;
+ } else if (IsEqualIID(riid, &IID_IDirectSound)) {
+ if (!This->pDS) {
+ IDirectSound8_IDirectSound_Create(iface, &This->pDS);
+ if (!This->pDS) {
+ WARN("IDirectSound8_IDirectSound_Create() failed\n");
+ *ppobj = NULL;
+ return E_NOINTERFACE;
+ }
+ }
+ IDirectSound8_IDirectSound_AddRef(This->pDS);
+ *ppobj = This->pDS;
+ return S_OK;
+ } else if (IsEqualIID(riid, &IID_IDirectSound8)) {
+ if (!This->pDS8) {
+ IDirectSound8_IDirectSound8_Create(iface, &This->pDS8);
+ if (!This->pDS8) {
+ WARN("IDirectSound8_IDirectSound8_Create() failed\n");
+ *ppobj = NULL;
+ return E_NOINTERFACE;
+ }
+ }
+ IDirectSound8_IDirectSound8_AddRef(This->pDS8);
+ *ppobj = This->pDS8;
+ return S_OK;
}
- IUnknown_AddRef((IUnknown*)*ppv);
- return S_OK;
+ *ppobj = NULL;
+ WARN("Unknown IID %s\n",debugstr_guid(riid));
+ return E_NOINTERFACE;
}
-static ULONG WINAPI IUnknownImpl_AddRef(IUnknown *iface)
+static ULONG IDirectSoundImpl_AddRef(
+ LPDIRECTSOUND8 iface)
{
- IDirectSoundImpl *This = impl_from_IUnknown(iface);
- ULONG ref = InterlockedIncrement(&This->ref);
-
- TRACE("(%p) ref=%d\n", This, ref);
+ IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
+ ULONG ref = InterlockedIncrement(&(This->ref));
+ TRACE("(%p) ref was %d\n", This, ref - 1);
+ return ref;
+}
- if(ref == 1)
- InterlockedIncrement(&This->numIfaces);
+static ULONG IDirectSoundImpl_Release(
+ LPDIRECTSOUND8 iface)
+{
+ IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
+ ULONG ref = InterlockedDecrement(&(This->ref));
+ TRACE("(%p) ref was %d\n", This, ref + 1);
+ if (!ref) {
+ if (This->device)
+ DirectSoundDevice_Release(This->device);
+ HeapFree(GetProcessHeap(),0,This);
+ TRACE("(%p) released\n", This);
+ }
return ref;
}
-static ULONG WINAPI IUnknownImpl_Release(IUnknown *iface)
+static HRESULT IDirectSoundImpl_Create(
+ LPDIRECTSOUND8 * ppDS)
{
- IDirectSoundImpl *This = impl_from_IUnknown(iface);
- ULONG ref = InterlockedDecrement(&This->ref);
+ IDirectSoundImpl* pDS;
+ TRACE("(%p)\n",ppDS);
- TRACE("(%p) ref=%d\n", This, ref);
+ /* Allocate memory */
+ pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
+ if (pDS == NULL) {
+ WARN("out of memory\n");
+ *ppDS = NULL;
+ return DSERR_OUTOFMEMORY;
+ }
+
+ pDS->ref = 0;
+ pDS->device = NULL;
- if (!ref && !InterlockedDecrement(&This->numIfaces))
- directsound_destroy(This);
+ *ppDS = (LPDIRECTSOUND8)pDS;
+ return DS_OK;
+}
+
+/*******************************************************************************
+ * IDirectSound_IUnknown
+ */
+static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
+ LPUNKNOWN iface,
+ REFIID riid,
+ LPVOID * ppobj)
+{
+ IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
+ TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+ return DSOUND_QueryInterface(This->pds, riid, ppobj);
+}
+
+static ULONG WINAPI IDirectSound_IUnknown_AddRef(
+ LPUNKNOWN iface)
+{
+ IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
+ ULONG ref = InterlockedIncrement(&(This->ref));
+ TRACE("(%p) ref was %d\n", This, ref - 1);
+ return ref;
+}
+
+static ULONG WINAPI IDirectSound_IUnknown_Release(
+ LPUNKNOWN iface)
+{
+ IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
+ ULONG ref = InterlockedDecrement(&(This->ref));
+ TRACE("(%p) ref was %d\n", This, ref + 1);
+ if (!ref) {
+ ((IDirectSoundImpl*)This->pds)->pUnknown = NULL;
+ IDirectSoundImpl_Release(This->pds);
+ HeapFree(GetProcessHeap(), 0, This);
+ TRACE("(%p) released\n", This);
+ }
return ref;
}
-static const IUnknownVtbl unk_vtbl =
+static const IUnknownVtbl DirectSound_Unknown_Vtbl =
{
- IUnknownImpl_QueryInterface,
- IUnknownImpl_AddRef,
- IUnknownImpl_Release
+ IDirectSound_IUnknown_QueryInterface,
+ IDirectSound_IUnknown_AddRef,
+ IDirectSound_IUnknown_Release
};
+static HRESULT IDirectSound_IUnknown_Create(
+ LPDIRECTSOUND8 pds,
+ LPUNKNOWN * ppunk)
+{
+ IDirectSound_IUnknown * pdsunk;
+ TRACE("(%p,%p)\n",pds,ppunk);
+
+ if (ppunk == NULL) {
+ ERR("invalid parameter: ppunk == NULL\n");
+ return DSERR_INVALIDPARAM;
+ }
+
+ if (pds == NULL) {
+ ERR("invalid parameter: pds == NULL\n");
+ *ppunk = NULL;
+ return DSERR_INVALIDPARAM;
+ }
+
+ pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
+ if (pdsunk == NULL) {
+ WARN("out of memory\n");
+ *ppunk = NULL;
+ return DSERR_OUTOFMEMORY;
+ }
+
+ pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl;
+ pdsunk->ref = 0;
+ pdsunk->pds = pds;
+
+ IDirectSoundImpl_AddRef(pds);
+ *ppunk = (LPUNKNOWN)pdsunk;
+
+ return DS_OK;
+}
+
/*******************************************************************************
- * IDirectSound and IDirectSound8 Implementation
+ * IDirectSound_IDirectSound
*/
-static inline IDirectSoundImpl *impl_from_IDirectSound8(IDirectSound8 *iface)
+static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface(
+ LPDIRECTSOUND iface,
+ REFIID riid,
+ LPVOID * ppobj)
{
- return CONTAINING_RECORD(iface, IDirectSoundImpl, IDirectSound8_iface);
+ IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
+ TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+ return DSOUND_QueryInterface(This->pds, riid, ppobj);
}
-static HRESULT WINAPI IDirectSound8Impl_QueryInterface(IDirectSound8 *iface, REFIID riid,
- void **ppv)
+static ULONG WINAPI IDirectSound_IDirectSound_AddRef(
+ LPDIRECTSOUND iface)
{
- IDirectSoundImpl *This = impl_from_IDirectSound8(iface);
- TRACE("(%p,%s,%p)\n", This, debugstr_guid(riid), ppv);
- return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
+ IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
+ ULONG ref = InterlockedIncrement(&(This->ref));
+ TRACE("(%p) ref was %d\n", This, ref - 1);
+ return ref;
}
-static ULONG WINAPI IDirectSound8Impl_AddRef(IDirectSound8 *iface)
+static ULONG WINAPI IDirectSound_IDirectSound_Release(
+ LPDIRECTSOUND iface)
{
- IDirectSoundImpl *This = impl_from_IDirectSound8(iface);
- ULONG ref = InterlockedIncrement(&This->refds);
+ IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
+ ULONG ref = InterlockedDecrement(&(This->ref));
+ TRACE("(%p) ref was %d\n", This, ref + 1);
+ if (!ref) {
+ ((IDirectSoundImpl*)This->pds)->pDS = NULL;
+ IDirectSoundImpl_Release(This->pds);
+ HeapFree(GetProcessHeap(), 0, This);
+ TRACE("(%p) released\n", This);
+ }
+ return ref;
+}
- TRACE("(%p) refds=%d\n", This, ref);
+static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer(
+ LPDIRECTSOUND iface,
+ LPCDSBUFFERDESC dsbd,
+ LPLPDIRECTSOUNDBUFFER ppdsb,
+ LPUNKNOWN lpunk)
+{
+ IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
+ TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
+ return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,FALSE);
+}
- if(ref == 1)
- InterlockedIncrement(&This->numIfaces);
+static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps(
+ LPDIRECTSOUND iface,
+ LPDSCAPS lpDSCaps)
+{
+ IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
+ TRACE("(%p,%p)\n",This,lpDSCaps);
+ return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
+}
- return ref;
+static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer(
+ LPDIRECTSOUND iface,
+ LPDIRECTSOUNDBUFFER psb,
+ LPLPDIRECTSOUNDBUFFER ppdsb)
+{
+ IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
+ TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
+ return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
}
-static ULONG WINAPI IDirectSound8Impl_Release(IDirectSound8 *iface)
+static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel(
+ LPDIRECTSOUND iface,
+ HWND hwnd,
+ DWORD level)
{
- IDirectSoundImpl *This = impl_from_IDirectSound8(iface);
- ULONG ref = InterlockedDecrement(&(This->refds));
+ IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
+ TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
+ return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
+}
- TRACE("(%p) refds=%d\n", This, ref);
+static HRESULT WINAPI IDirectSound_IDirectSound_Compact(
+ LPDIRECTSOUND iface)
+{
+ IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
+ TRACE("(%p)\n", This);
+ return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
+}
- if (!ref && !InterlockedDecrement(&This->numIfaces))
- directsound_destroy(This);
+static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig(
+ LPDIRECTSOUND iface,
+ LPDWORD lpdwSpeakerConfig)
+{
+ IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
+ TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
+ return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
+}
- return ref;
+static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig(
+ LPDIRECTSOUND iface,
+ DWORD config)
+{
+ IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
+ TRACE("(%p,0x%08x)\n",This,config);
+ return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
}
-static HRESULT WINAPI IDirectSound8Impl_CreateSoundBuffer(IDirectSound8 *iface,
- const DSBUFFERDESC *dsbd, IDirectSoundBuffer **ppdsb, IUnknown *lpunk)
+static HRESULT WINAPI IDirectSound_IDirectSound_Initialize(
+ LPDIRECTSOUND iface,
+ LPCGUID lpcGuid)
{
- IDirectSoundImpl *This = impl_from_IDirectSound8(iface);
- TRACE("(%p,%p,%p,%p)\n", This, dsbd, ppdsb, lpunk);
- return DirectSoundDevice_CreateSoundBuffer(This->device, dsbd, ppdsb, lpunk, This->has_ds8);
+ IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
+ TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
+ return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
}
-static HRESULT WINAPI IDirectSound8Impl_GetCaps(IDirectSound8 *iface, DSCAPS *dscaps)
+static const IDirectSoundVtbl DirectSound_DirectSound_Vtbl =
{
- IDirectSoundImpl *This = impl_from_IDirectSound8(iface);
+ IDirectSound_IDirectSound_QueryInterface,
+ IDirectSound_IDirectSound_AddRef,
+ IDirectSound_IDirectSound_Release,
+ IDirectSound_IDirectSound_CreateSoundBuffer,
+ IDirectSound_IDirectSound_GetCaps,
+ IDirectSound_IDirectSound_DuplicateSoundBuffer,
+ IDirectSound_IDirectSound_SetCooperativeLevel,
+ IDirectSound_IDirectSound_Compact,
+ IDirectSound_IDirectSound_GetSpeakerConfig,
+ IDirectSound_IDirectSound_SetSpeakerConfig,
+ IDirectSound_IDirectSound_Initialize
+};
- TRACE("(%p, %p)\n", This, dscaps);
+static HRESULT IDirectSound_IDirectSound_Create(
+ LPDIRECTSOUND8 pds,
+ LPDIRECTSOUND * ppds)
+{
+ IDirectSound_IDirectSound * pdsds;
+ TRACE("(%p,%p)\n",pds,ppds);
- if (!This->device) {
- WARN("not initialized\n");
- return DSERR_UNINITIALIZED;
- }
- if (!dscaps) {
- WARN("invalid parameter: dscaps = NULL\n");
+ if (ppds == NULL) {
+ ERR("invalid parameter: ppds == NULL\n");
return DSERR_INVALIDPARAM;
}
- if (dscaps->dwSize < sizeof(*dscaps)) {
- WARN("invalid parameter: dscaps->dwSize = %d\n", dscaps->dwSize);
+
+ if (pds == NULL) {
+ ERR("invalid parameter: pds == NULL\n");
+ *ppds = NULL;
return DSERR_INVALIDPARAM;
}
- dscaps->dwFlags = This->device->drvcaps.dwFlags;
- dscaps->dwMinSecondarySampleRate = This->device->drvcaps.dwMinSecondarySampleRate;
- dscaps->dwMaxSecondarySampleRate = This->device->drvcaps.dwMaxSecondarySampleRate;
- dscaps->dwPrimaryBuffers = This->device->drvcaps.dwPrimaryBuffers;
- dscaps->dwMaxHwMixingAllBuffers = This->device->drvcaps.dwMaxHwMixingAllBuffers;
- dscaps->dwMaxHwMixingStaticBuffers = This->device->drvcaps.dwMaxHwMixingStaticBuffers;
- dscaps->dwMaxHwMixingStreamingBuffers = This->device->drvcaps.dwMaxHwMixingStreamingBuffers;
- dscaps->dwFreeHwMixingAllBuffers = This->device->drvcaps.dwFreeHwMixingAllBuffers;
- dscaps->dwFreeHwMixingStaticBuffers = This->device->drvcaps.dwFreeHwMixingStaticBuffers;
- dscaps->dwFreeHwMixingStreamingBuffers = This->device->drvcaps.dwFreeHwMixingStreamingBuffers;
- dscaps->dwMaxHw3DAllBuffers = This->device->drvcaps.dwMaxHw3DAllBuffers;
- dscaps->dwMaxHw3DStaticBuffers = This->device->drvcaps.dwMaxHw3DStaticBuffers;
- dscaps->dwMaxHw3DStreamingBuffers = This->device->drvcaps.dwMaxHw3DStreamingBuffers;
- dscaps->dwFreeHw3DAllBuffers = This->device->drvcaps.dwFreeHw3DAllBuffers;
- dscaps->dwFreeHw3DStaticBuffers = This->device->drvcaps.dwFreeHw3DStaticBuffers;
- dscaps->dwFreeHw3DStreamingBuffers = This->device->drvcaps.dwFreeHw3DStreamingBuffers;
- dscaps->dwTotalHwMemBytes = This->device->drvcaps.dwTotalHwMemBytes;
- dscaps->dwFreeHwMemBytes = This->device->drvcaps.dwFreeHwMemBytes;
- dscaps->dwMaxContigFreeHwMemBytes = This->device->drvcaps.dwMaxContigFreeHwMemBytes;
- dscaps->dwUnlockTransferRateHwBuffers = This->device->drvcaps.dwUnlockTransferRateHwBuffers;
- dscaps->dwPlayCpuOverheadSwBuffers = This->device->drvcaps.dwPlayCpuOverheadSwBuffers;
-
- if (TRACE_ON(dsound)) {
- TRACE("(flags=0x%08x:\n", dscaps->dwFlags);
- _dump_DSCAPS(dscaps->dwFlags);
- TRACE(")\n");
+ pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
+ if (pdsds == NULL) {
+ WARN("out of memory\n");
+ *ppds = NULL;
+ return DSERR_OUTOFMEMORY;
}
+ pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl;
+ pdsds->ref = 0;
+ pdsds->pds = pds;
+
+ IDirectSoundImpl_AddRef(pds);
+ *ppds = (LPDIRECTSOUND)pdsds;
+
return DS_OK;
}
-static HRESULT WINAPI IDirectSound8Impl_DuplicateSoundBuffer(IDirectSound8 *iface,
- IDirectSoundBuffer *psb, IDirectSoundBuffer **ppdsb)
+/*******************************************************************************
+ * IDirectSound8_IUnknown
+ */
+static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface(
+ LPUNKNOWN iface,
+ REFIID riid,
+ LPVOID * ppobj)
{
- IDirectSoundImpl *This = impl_from_IDirectSound8(iface);
- TRACE("(%p,%p,%p)\n", This, psb, ppdsb);
- return DirectSoundDevice_DuplicateSoundBuffer(This->device, psb, ppdsb);
+ IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
+ TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+ return DSOUND_QueryInterface8(This->pds, riid, ppobj);
}
-static HRESULT WINAPI IDirectSound8Impl_SetCooperativeLevel(IDirectSound8 *iface, HWND hwnd,
- DWORD level)
+static ULONG WINAPI IDirectSound8_IUnknown_AddRef(
+ LPUNKNOWN iface)
{
- IDirectSoundImpl *This = impl_from_IDirectSound8(iface);
- DirectSoundDevice *device = This->device;
- DWORD oldlevel;
- HRESULT hr = S_OK;
+ IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
+ ULONG ref = InterlockedIncrement(&(This->ref));
+ TRACE("(%p) ref was %d\n", This, ref - 1);
+ return ref;
+}
- TRACE("(%p,%p,%s)\n", This, hwnd, dumpCooperativeLevel(level));
+static ULONG WINAPI IDirectSound8_IUnknown_Release(
+ LPUNKNOWN iface)
+{
+ IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
+ ULONG ref = InterlockedDecrement(&(This->ref));
+ TRACE("(%p) ref was %d\n", This, ref + 1);
+ if (!ref) {
+ ((IDirectSoundImpl*)This->pds)->pUnknown = NULL;
+ IDirectSoundImpl_Release(This->pds);
+ HeapFree(GetProcessHeap(), 0, This);
+ TRACE("(%p) released\n", This);
+ }
+ return ref;
+}
- if (!device) {
- WARN("not initialized\n");
- return DSERR_UNINITIALIZED;
+static const IUnknownVtbl DirectSound8_Unknown_Vtbl =
+{
+ IDirectSound8_IUnknown_QueryInterface,
+ IDirectSound8_IUnknown_AddRef,
+ IDirectSound8_IUnknown_Release
+};
+
+static HRESULT IDirectSound8_IUnknown_Create(
+ LPDIRECTSOUND8 pds,
+ LPUNKNOWN * ppunk)
+{
+ IDirectSound8_IUnknown * pdsunk;
+ TRACE("(%p,%p)\n",pds,ppunk);
+
+ if (ppunk == NULL) {
+ ERR("invalid parameter: ppunk == NULL\n");
+ return DSERR_INVALIDPARAM;
}
- if (level == DSSCL_PRIORITY || level == DSSCL_EXCLUSIVE) {
- WARN("level=%s not fully supported\n",
- level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
+ if (pds == NULL) {
+ ERR("invalid parameter: pds == NULL\n");
+ *ppunk = NULL;
+ return DSERR_INVALIDPARAM;
}
- RtlAcquireResourceExclusive(&device->buffer_list_lock, TRUE);
- EnterCriticalSection(&device->mixlock);
- oldlevel = device->priolevel;
- device->priolevel = level;
- if ((level == DSSCL_WRITEPRIMARY) != (oldlevel == DSSCL_WRITEPRIMARY)) {
- hr = DSOUND_ReopenDevice(device, level == DSSCL_WRITEPRIMARY);
- if (FAILED(hr))
- device->priolevel = oldlevel;
- else
- DSOUND_PrimaryOpen(device);
+ pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
+ if (pdsunk == NULL) {
+ WARN("out of memory\n");
+ *ppunk = NULL;
+ return DSERR_OUTOFMEMORY;
}
- LeaveCriticalSection(&device->mixlock);
- RtlReleaseResource(&device->buffer_list_lock);
- return hr;
+
+ pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl;
+ pdsunk->ref = 0;
+ pdsunk->pds = pds;
+
+ IDirectSoundImpl_AddRef(pds);
+ *ppunk = (LPUNKNOWN)pdsunk;
+
+ return DS_OK;
}
-static HRESULT WINAPI IDirectSound8Impl_Compact(IDirectSound8 *iface)
+/*******************************************************************************
+ * IDirectSound8_IDirectSound
+ */
+static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface(
+ LPDIRECTSOUND iface,
+ REFIID riid,
+ LPVOID * ppobj)
{
- IDirectSoundImpl *This = impl_from_IDirectSound8(iface);
+ IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
+ TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+ return DSOUND_QueryInterface8(This->pds, riid, ppobj);
+}
- TRACE("(%p)\n", This);
+static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
+ LPDIRECTSOUND iface)
+{
+ IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
+ ULONG ref = InterlockedIncrement(&(This->ref));
+ TRACE("(%p) ref was %d\n", This, ref - 1);
+ return ref;
+}
- if (!This->device) {
- WARN("not initialized\n");
- return DSERR_UNINITIALIZED;
+static ULONG WINAPI IDirectSound8_IDirectSound_Release(
+ LPDIRECTSOUND iface)
+{
+ IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
+ ULONG ref = InterlockedDecrement(&(This->ref));
+ TRACE("(%p) ref was %d\n", This, ref + 1);
+ if (!ref) {
+ ((IDirectSoundImpl*)This->pds)->pDS = NULL;
+ IDirectSoundImpl_Release(This->pds);
+ HeapFree(GetProcessHeap(), 0, This);
+ TRACE("(%p) released\n", This);
}
+ return ref;
+}
- if (This->device->priolevel < DSSCL_PRIORITY) {
- WARN("incorrect priority level\n");
- return DSERR_PRIOLEVELNEEDED;
- }
- return DS_OK;
+static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
+ LPDIRECTSOUND iface,
+ LPCDSBUFFERDESC dsbd,
+ LPLPDIRECTSOUNDBUFFER ppdsb,
+ LPUNKNOWN lpunk)
+{
+ IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
+ TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
+ return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,TRUE);
+}
+
+static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
+ LPDIRECTSOUND iface,
+ LPDSCAPS lpDSCaps)
+{
+ IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
+ TRACE("(%p,%p)\n",This,lpDSCaps);
+ return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
}
-static HRESULT WINAPI IDirectSound8Impl_GetSpeakerConfig(IDirectSound8 *iface, DWORD *config)
+static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
+ LPDIRECTSOUND iface,
+ LPDIRECTSOUNDBUFFER psb,
+ LPLPDIRECTSOUNDBUFFER ppdsb)
{
- IDirectSoundImpl *This = impl_from_IDirectSound8(iface);
+ IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
+ TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
+ return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
+}
- TRACE("(%p, %p)\n", This, config);
+static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
+ LPDIRECTSOUND iface,
+ HWND hwnd,
+ DWORD level)
+{
+ IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
+ TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
+ return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
+}
- if (!This->device) {
- WARN("not initialized\n");
- return DSERR_UNINITIALIZED;
+static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
+ LPDIRECTSOUND iface)
+{
+ IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
+ TRACE("(%p)\n", This);
+ return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
+}
+
+static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
+ LPDIRECTSOUND iface,
+ LPDWORD lpdwSpeakerConfig)
+{
+ IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
+ TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
+ return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
+}
+
+static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
+ LPDIRECTSOUND iface,
+ DWORD config)
+{
+ IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
+ TRACE("(%p,0x%08x)\n",This,config);
+ return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
+}
+
+static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
+ LPDIRECTSOUND iface,
+ LPCGUID lpcGuid)
+{
+ IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
+ TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
+ return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
+}
+
+static const IDirectSoundVtbl DirectSound8_DirectSound_Vtbl =
+{
+ IDirectSound8_IDirectSound_QueryInterface,
+ IDirectSound8_IDirectSound_AddRef,
+ IDirectSound8_IDirectSound_Release,
+ IDirectSound8_IDirectSound_CreateSoundBuffer,
+ IDirectSound8_IDirectSound_GetCaps,
+ IDirectSound8_IDirectSound_DuplicateSoundBuffer,
+ IDirectSound8_IDirectSound_SetCooperativeLevel,
+ IDirectSound8_IDirectSound_Compact,
+ IDirectSound8_IDirectSound_GetSpeakerConfig,
+ IDirectSound8_IDirectSound_SetSpeakerConfig,
+ IDirectSound8_IDirectSound_Initialize
+};
+
+static HRESULT IDirectSound8_IDirectSound_Create(
+ LPDIRECTSOUND8 pds,
+ LPDIRECTSOUND * ppds)
+{
+ IDirectSound8_IDirectSound * pdsds;
+ TRACE("(%p,%p)\n",pds,ppds);
+
+ if (ppds == NULL) {
+ ERR("invalid parameter: ppds == NULL\n");
+ return DSERR_INVALIDPARAM;
}
- if (!config) {
- WARN("invalid parameter: config == NULL\n");
+
+ if (pds == NULL) {
+ ERR("invalid parameter: pds == NULL\n");
+ *ppds = NULL;
return DSERR_INVALIDPARAM;
}
- WARN("not fully functional\n");
- *config = This->device->speaker_config;
+ pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
+ if (pdsds == NULL) {
+ WARN("out of memory\n");
+ *ppds = NULL;
+ return DSERR_OUTOFMEMORY;
+ }
+
+ pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl;
+ pdsds->ref = 0;
+ pdsds->pds = pds;
+
+ IDirectSoundImpl_AddRef(pds);
+ *ppds = (LPDIRECTSOUND)pdsds;
+
return DS_OK;
}
-static HRESULT WINAPI IDirectSound8Impl_SetSpeakerConfig(IDirectSound8 *iface, DWORD config)
+/*******************************************************************************
+ * IDirectSound8_IDirectSound8
+ */
+static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface(
+ LPDIRECTSOUND8 iface,
+ REFIID riid,
+ LPVOID * ppobj)
{
- IDirectSoundImpl *This = impl_from_IDirectSound8(iface);
+ IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
+ TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+ return DSOUND_QueryInterface8(This->pds, riid, ppobj);
+}
- TRACE("(%p,0x%08x)\n", This, config);
+static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
+ LPDIRECTSOUND8 iface)
+{
+ IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
+ ULONG ref = InterlockedIncrement(&(This->ref));
+ TRACE("(%p) ref was %d\n", This, ref - 1);
+ return ref;
+}
- if (!This->device) {
- WARN("not initialized\n");
- return DSERR_UNINITIALIZED;
+static ULONG WINAPI IDirectSound8_IDirectSound8_Release(
+ LPDIRECTSOUND8 iface)
+{
+ IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
+ ULONG ref = InterlockedDecrement(&(This->ref));
+ TRACE("(%p) ref was %d\n", This, ref + 1);
+ if (!ref) {
+ ((IDirectSoundImpl*)This->pds)->pDS8 = NULL;
+ IDirectSoundImpl_Release(This->pds);
+ HeapFree(GetProcessHeap(), 0, This);
+ TRACE("(%p) released\n", This);
}
+ return ref;
+}
- This->device->speaker_config = config;
- WARN("not fully functional\n");
- return DS_OK;
+static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
+ LPDIRECTSOUND8 iface,
+ LPCDSBUFFERDESC dsbd,
+ LPLPDIRECTSOUNDBUFFER ppdsb,
+ LPUNKNOWN lpunk)
+{
+ IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
+ TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
+ return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,TRUE);
}
-static HRESULT WINAPI IDirectSound8Impl_Initialize(IDirectSound8 *iface, const GUID *lpcGuid)
+static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
+ LPDIRECTSOUND8 iface,
+ LPDSCAPS lpDSCaps)
{
- IDirectSoundImpl *This = impl_from_IDirectSound8(iface);
- TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
- return DirectSoundDevice_Initialize(&This->device, lpcGuid);
+ IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
+ TRACE("(%p,%p)\n",This,lpDSCaps);
+ return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
}
-static HRESULT WINAPI IDirectSound8Impl_VerifyCertification(IDirectSound8 *iface, DWORD *certified)
+static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
+ LPDIRECTSOUND8 iface,
+ LPDIRECTSOUNDBUFFER psb,
+ LPLPDIRECTSOUNDBUFFER ppdsb)
{
- IDirectSoundImpl *This = impl_from_IDirectSound8(iface);
+ IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
+ TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
+ return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
+}
- TRACE("(%p, %p)\n", This, certified);
+static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
+ LPDIRECTSOUND8 iface,
+ HWND hwnd,
+ DWORD level)
+{
+ IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
+ TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
+ return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
+}
- if (!This->device) {
- WARN("not initialized\n");
- return DSERR_UNINITIALIZED;
- }
+static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
+ LPDIRECTSOUND8 iface)
+{
+ IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
+ TRACE("(%p)\n", This);
+ return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
+}
- if (This->device->drvcaps.dwFlags & DSCAPS_CERTIFIED)
- *certified = DS_CERTIFIED;
- else
- *certified = DS_UNCERTIFIED;
+static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
+ LPDIRECTSOUND8 iface,
+ LPDWORD lpdwSpeakerConfig)
+{
+ IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
+ TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
+ return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
+}
- return DS_OK;
+static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
+ LPDIRECTSOUND8 iface,
+ DWORD config)
+{
+ IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
+ TRACE("(%p,0x%08x)\n",This,config);
+ return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
+}
+
+static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
+ LPDIRECTSOUND8 iface,
+ LPCGUID lpcGuid)
+{
+ IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
+ TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
+ return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
}
-static const IDirectSound8Vtbl ds8_vtbl =
-{
- IDirectSound8Impl_QueryInterface,
- IDirectSound8Impl_AddRef,
- IDirectSound8Impl_Release,
- IDirectSound8Impl_CreateSoundBuffer,
- IDirectSound8Impl_GetCaps,
- IDirectSound8Impl_DuplicateSoundBuffer,
- IDirectSound8Impl_SetCooperativeLevel,
- IDirectSound8Impl_Compact,
- IDirectSound8Impl_GetSpeakerConfig,
- IDirectSound8Impl_SetSpeakerConfig,
- IDirectSound8Impl_Initialize,
- IDirectSound8Impl_VerifyCertification
+static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
+ LPDIRECTSOUND8 iface,
+ LPDWORD pdwCertified)
+{
+ IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
+ TRACE("(%p, %p)\n", This, pdwCertified);
+ return DirectSoundDevice_VerifyCertification(((IDirectSoundImpl *)This->pds)->device,pdwCertified);
+}
+
+static const IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl =
+{
+ IDirectSound8_IDirectSound8_QueryInterface,
+ IDirectSound8_IDirectSound8_AddRef,
+ IDirectSound8_IDirectSound8_Release,
+ IDirectSound8_IDirectSound8_CreateSoundBuffer,
+ IDirectSound8_IDirectSound8_GetCaps,
+ IDirectSound8_IDirectSound8_DuplicateSoundBuffer,
+ IDirectSound8_IDirectSound8_SetCooperativeLevel,
+ IDirectSound8_IDirectSound8_Compact,
+ IDirectSound8_IDirectSound8_GetSpeakerConfig,
+ IDirectSound8_IDirectSound8_SetSpeakerConfig,
+ IDirectSound8_IDirectSound8_Initialize,
+ IDirectSound8_IDirectSound8_VerifyCertification
};
-HRESULT IDirectSoundImpl_Create(IUnknown *outer_unk, REFIID riid, void **ppv, BOOL has_ds8)
+static HRESULT IDirectSound8_IDirectSound8_Create(
+ LPDIRECTSOUND8 pds,
+ LPDIRECTSOUND8 * ppds)
{
- IDirectSoundImpl *obj;
- HRESULT hr;
+ IDirectSound8_IDirectSound8 * pdsds;
+ TRACE("(%p,%p)\n",pds,ppds);
- TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
+ if (ppds == NULL) {
+ ERR("invalid parameter: ppds == NULL\n");
+ return DSERR_INVALIDPARAM;
+ }
- *ppv = NULL;
- obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*obj));
- if (!obj) {
+ if (pds == NULL) {
+ ERR("invalid parameter: pds == NULL\n");
+ *ppds = NULL;
+ return DSERR_INVALIDPARAM;
+ }
+
+ pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
+ if (pdsds == NULL) {
WARN("out of memory\n");
+ *ppds = NULL;
return DSERR_OUTOFMEMORY;
}
- setup_dsound_options();
-
- obj->IUnknown_inner.lpVtbl = &unk_vtbl;
- obj->IDirectSound8_iface.lpVtbl = &ds8_vtbl;
- obj->ref = 1;
- obj->refds = 0;
- obj->numIfaces = 1;
- obj->device = NULL;
- obj->has_ds8 = has_ds8;
-
- /* COM aggregation supported only internally */
- if (outer_unk)
- obj->outer_unk = outer_unk;
- else
- obj->outer_unk = &obj->IUnknown_inner;
+ pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl;
+ pdsds->ref = 0;
+ pdsds->pds = pds;
- hr = IUnknown_QueryInterface(&obj->IUnknown_inner, riid, ppv);
- IUnknown_Release(&obj->IUnknown_inner);
+ IDirectSoundImpl_AddRef(pds);
+ *ppds = (LPDIRECTSOUND8)pdsds;
- return hr;
+ return DS_OK;
}
-HRESULT DSOUND_Create(REFIID riid, void **ppv)
+HRESULT DSOUND_Create(
+ REFIID riid,
+ LPDIRECTSOUND *ppDS)
{
- return IDirectSoundImpl_Create(NULL, riid, ppv, FALSE);
-}
+ LPDIRECTSOUND8 pDS;
+ HRESULT hr;
+ TRACE("(%s, %p)\n", debugstr_guid(riid), ppDS);
-HRESULT DSOUND_Create8(REFIID riid, void **ppv)
-{
- return IDirectSoundImpl_Create(NULL, riid, ppv, TRUE);
+ if (!IsEqualIID(riid, &IID_IUnknown) &&
+ !IsEqualIID(riid, &IID_IDirectSound)) {
+ *ppDS = 0;
+ return E_NOINTERFACE;
+ }
+
+ /* Get dsound configuration */
+ setup_dsound_options();
+
+ hr = IDirectSoundImpl_Create(&pDS);
+ if (hr == DS_OK) {
+ hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
+ if (*ppDS)
+ IDirectSound_IDirectSound_AddRef(*ppDS);
+ else {
+ WARN("IDirectSound_IDirectSound_Create failed\n");
+ IDirectSound8_Release(pDS);
+ }
+ } else {
+ WARN("IDirectSoundImpl_Create failed\n");
+ *ppDS = 0;
+ }
+
+ return hr;
}
/*******************************************************************************
return DSERR_INVALIDPARAM;
}
- hr = DSOUND_Create(&IID_IDirectSound, (void **)&pDS);
+ hr = DSOUND_Create(&IID_IDirectSound, &pDS);
if (hr == DS_OK) {
hr = IDirectSound_Initialize(pDS, lpcGUID);
if (hr != DS_OK) {
return hr;
}
+HRESULT DSOUND_Create8(
+ REFIID riid,
+ LPDIRECTSOUND8 *ppDS)
+{
+ LPDIRECTSOUND8 pDS;
+ HRESULT hr;
+ TRACE("(%s, %p)\n", debugstr_guid(riid), ppDS);
+
+ if (!IsEqualIID(riid, &IID_IUnknown) &&
+ !IsEqualIID(riid, &IID_IDirectSound) &&
+ !IsEqualIID(riid, &IID_IDirectSound8)) {
+ *ppDS = 0;
+ return E_NOINTERFACE;
+ }
+
+ /* Get dsound configuration */
+ setup_dsound_options();
+
+ hr = IDirectSoundImpl_Create(&pDS);
+ if (hr == DS_OK) {
+ hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
+ if (*ppDS)
+ IDirectSound8_IDirectSound8_AddRef(*ppDS);
+ else {
+ WARN("IDirectSound8_IDirectSound8_Create failed\n");
+ IDirectSound8_Release(pDS);
+ }
+ } else {
+ WARN("IDirectSoundImpl_Create failed\n");
+ *ppDS = 0;
+ }
+
+ return hr;
+}
+
/*******************************************************************************
* DirectSoundCreate8 (DSOUND.11)
*
return DSERR_INVALIDPARAM;
}
- hr = DSOUND_Create8(&IID_IDirectSound8, (void **)&pDS);
+ hr = DSOUND_Create8(&IID_IDirectSound8, &pDS);
if (hr == DS_OK) {
hr = IDirectSound8_Initialize(pDS, lpcGUID);
if (hr != DS_OK) {
device->ref = 1;
device->priolevel = DSSCL_NORMAL;
device->state = STATE_STOPPED;
- device->speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO, DSSPEAKER_GEOMETRY_WIDE);
+ device->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
/* 3D listener initial parameters */
device->ds3dl.dwSize = sizeof(DS3DLISTENER);
device->guid = GUID_NULL;
/* Set default wave format (may need it for waveOutOpen) */
- device->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEXTENSIBLE));
- device->primary_pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEXTENSIBLE));
- if (!device->pwfx || !device->primary_pwfx) {
+ device->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
+ if (device->pwfx == NULL) {
WARN("out of memory\n");
- HeapFree(GetProcessHeap(),0,device->primary_pwfx);
- HeapFree(GetProcessHeap(),0,device->pwfx);
HeapFree(GetProcessHeap(),0,device);
return DSERR_OUTOFMEMORY;
}
+ /* We rely on the sound driver to return the actual sound format of
+ * the device if it does not support 22050x8x2 and is given the
+ * WAVE_DIRECTSOUND flag.
+ */
device->pwfx->wFormatTag = WAVE_FORMAT_PCM;
- device->pwfx->nSamplesPerSec = 22050;
- device->pwfx->wBitsPerSample = 8;
+ device->pwfx->nSamplesPerSec = ds_default_sample_rate;
+ device->pwfx->wBitsPerSample = ds_default_bits_per_sample;
device->pwfx->nChannels = 2;
device->pwfx->nBlockAlign = device->pwfx->wBitsPerSample * device->pwfx->nChannels / 8;
device->pwfx->nAvgBytesPerSec = device->pwfx->nSamplesPerSec * device->pwfx->nBlockAlign;
device->pwfx->cbSize = 0;
- memcpy(device->primary_pwfx, device->pwfx, sizeof(*device->pwfx));
InitializeCriticalSection(&(device->mixlock));
device->mixlock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DirectSoundDevice.mixlock");
TRACE("(%p) ref was %u\n", device, ref + 1);
if (!ref) {
int i;
+ timeKillEvent(device->timerID);
+ timeEndPeriod(DS_TIME_RES);
- SetEvent(device->sleepev);
- if (device->thread) {
- WaitForSingleObject(device->thread, INFINITE);
- CloseHandle(device->thread);
- }
- CloseHandle(device->sleepev);
-
- EnterCriticalSection(&DSOUND_renderers_lock);
- list_remove(&device->entry);
- LeaveCriticalSection(&DSOUND_renderers_lock);
+ /* The kill event should have allowed the timer process to expire
+ * but try to grab the lock just in case. Can't hold lock because
+ * IDirectSoundBufferImpl_Destroy also grabs the lock */
+ RtlAcquireResourceShared(&(device->buffer_list_lock), TRUE);
+ RtlReleaseResource(&(device->buffer_list_lock));
/* It is allowed to release this object even when buffers are playing */
if (device->buffers) {
WARN("%d secondary buffers not released\n", device->nrofbuffers);
for( i=0;i<device->nrofbuffers;i++)
- secondarybuffer_destroy(device->buffers[i]);
+ IDirectSoundBufferImpl_Destroy(device->buffers[i]);
+ }
+
+ if (device->primary) {
+ WARN("primary buffer not released\n");
+ IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)device->primary);
}
hr = DSOUND_PrimaryDestroy(device);
if (hr != DS_OK)
WARN("DSOUND_PrimaryDestroy failed\n");
- if(device->client)
- IAudioClient_Release(device->client);
- if(device->render)
- IAudioRenderClient_Release(device->render);
- if(device->clock)
- IAudioClock_Release(device->clock);
- if(device->volume)
- IAudioStreamVolume_Release(device->volume);
+ if (device->driver)
+ IDsDriver_Close(device->driver);
+
+ if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
+ waveOutClose(device->hwo);
+
+ if (device->driver)
+ IDsDriver_Release(device->driver);
+
+ DSOUND_renderer[device->drvdesc.dnDevNode] = NULL;
HeapFree(GetProcessHeap(), 0, device->tmp_buffer);
HeapFree(GetProcessHeap(), 0, device->mix_buffer);
- HeapFree(GetProcessHeap(), 0, device->buffer);
+ if (device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY)
+ HeapFree(GetProcessHeap(), 0, device->buffer);
RtlDeleteResource(&device->buffer_list_lock);
device->mixlock.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&device->mixlock);
return ref;
}
-BOOL DSOUND_check_supported(IAudioClient *client, DWORD rate,
- DWORD depth, WORD channels)
+HRESULT DirectSoundDevice_GetCaps(
+ DirectSoundDevice * device,
+ LPDSCAPS lpDSCaps)
{
- WAVEFORMATEX fmt, *junk;
- HRESULT hr;
+ TRACE("(%p,%p)\n",device,lpDSCaps);
- fmt.wFormatTag = WAVE_FORMAT_PCM;
- fmt.nChannels = channels;
- fmt.nSamplesPerSec = rate;
- fmt.wBitsPerSample = depth;
- fmt.nBlockAlign = (channels * depth) / 8;
- fmt.nAvgBytesPerSec = rate * fmt.nBlockAlign;
- fmt.cbSize = 0;
-
- hr = IAudioClient_IsFormatSupported(client, AUDCLNT_SHAREMODE_SHARED, &fmt, &junk);
- if(SUCCEEDED(hr))
- CoTaskMemFree(junk);
+ if (device == NULL) {
+ WARN("not initialized\n");
+ return DSERR_UNINITIALIZED;
+ }
- return hr == S_OK;
-}
+ if (lpDSCaps == NULL) {
+ WARN("invalid parameter: lpDSCaps = NULL\n");
+ return DSERR_INVALIDPARAM;
+ }
-UINT DSOUND_create_timer(LPTIMECALLBACK cb, DWORD_PTR user)
-{
- UINT triggertime = DS_TIME_DEL, res = DS_TIME_RES, id;
- TIMECAPS time;
+ /* check if there is enough room */
+ if (lpDSCaps->dwSize < sizeof(*lpDSCaps)) {
+ WARN("invalid parameter: lpDSCaps->dwSize = %d\n", lpDSCaps->dwSize);
+ return DSERR_INVALIDPARAM;
+ }
- timeGetDevCaps(&time, sizeof(TIMECAPS));
- TRACE("Minimum timer resolution: %u, max timer: %u\n", time.wPeriodMin, time.wPeriodMax);
- if (triggertime < time.wPeriodMin)
- triggertime = time.wPeriodMin;
- if (res < time.wPeriodMin)
- res = time.wPeriodMin;
- if (timeBeginPeriod(res) == TIMERR_NOCANDO)
- WARN("Could not set minimum resolution, don't expect sound\n");
- id = timeSetEvent(triggertime, res, cb, user, TIME_PERIODIC | TIME_KILL_SYNCHRONOUS);
- if (!id)
- {
- WARN("Timer not created! Retrying without TIME_KILL_SYNCHRONOUS\n");
- id = timeSetEvent(triggertime, res, cb, user, TIME_PERIODIC);
- if (!id)
- ERR("Could not create timer, sound playback will not occur\n");
+ lpDSCaps->dwFlags = device->drvcaps.dwFlags;
+ if (TRACE_ON(dsound)) {
+ TRACE("(flags=0x%08x:\n",lpDSCaps->dwFlags);
+ _dump_DSCAPS(lpDSCaps->dwFlags);
+ TRACE(")\n");
}
- return id;
+ lpDSCaps->dwMinSecondarySampleRate = device->drvcaps.dwMinSecondarySampleRate;
+ lpDSCaps->dwMaxSecondarySampleRate = device->drvcaps.dwMaxSecondarySampleRate;
+ lpDSCaps->dwPrimaryBuffers = device->drvcaps.dwPrimaryBuffers;
+ lpDSCaps->dwMaxHwMixingAllBuffers = device->drvcaps.dwMaxHwMixingAllBuffers;
+ lpDSCaps->dwMaxHwMixingStaticBuffers = device->drvcaps.dwMaxHwMixingStaticBuffers;
+ lpDSCaps->dwMaxHwMixingStreamingBuffers = device->drvcaps.dwMaxHwMixingStreamingBuffers;
+ lpDSCaps->dwFreeHwMixingAllBuffers = device->drvcaps.dwFreeHwMixingAllBuffers;
+ lpDSCaps->dwFreeHwMixingStaticBuffers = device->drvcaps.dwFreeHwMixingStaticBuffers;
+ lpDSCaps->dwFreeHwMixingStreamingBuffers = device->drvcaps.dwFreeHwMixingStreamingBuffers;
+ lpDSCaps->dwMaxHw3DAllBuffers = device->drvcaps.dwMaxHw3DAllBuffers;
+ lpDSCaps->dwMaxHw3DStaticBuffers = device->drvcaps.dwMaxHw3DStaticBuffers;
+ lpDSCaps->dwMaxHw3DStreamingBuffers = device->drvcaps.dwMaxHw3DStreamingBuffers;
+ lpDSCaps->dwFreeHw3DAllBuffers = device->drvcaps.dwFreeHw3DAllBuffers;
+ lpDSCaps->dwFreeHw3DStaticBuffers = device->drvcaps.dwFreeHw3DStaticBuffers;
+ lpDSCaps->dwFreeHw3DStreamingBuffers = device->drvcaps.dwFreeHw3DStreamingBuffers;
+ lpDSCaps->dwTotalHwMemBytes = device->drvcaps.dwTotalHwMemBytes;
+ lpDSCaps->dwFreeHwMemBytes = device->drvcaps.dwFreeHwMemBytes;
+ lpDSCaps->dwMaxContigFreeHwMemBytes = device->drvcaps.dwMaxContigFreeHwMemBytes;
+
+ /* driver doesn't have these */
+ lpDSCaps->dwUnlockTransferRateHwBuffers = 4096; /* But we have none... */
+ lpDSCaps->dwPlayCpuOverheadSwBuffers = 1; /* 1% */
+
+ return DS_OK;
}
HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcGUID)
{
HRESULT hr = DS_OK;
+ unsigned wod, wodn;
+ BOOLEAN found = FALSE;
GUID devGUID;
- DirectSoundDevice *device;
- IMMDevice *mmdevice;
-
+ DirectSoundDevice * device = *ppDevice;
TRACE("(%p,%s)\n",ppDevice,debugstr_guid(lpcGUID));
if (*ppDevice != NULL) {
if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
lpcGUID = &DSDEVID_DefaultPlayback;
- if(IsEqualGUID(lpcGUID, &DSDEVID_DefaultCapture) ||
- IsEqualGUID(lpcGUID, &DSDEVID_DefaultVoiceCapture))
- return DSERR_NODRIVER;
-
if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) {
WARN("invalid parameter: lpcGUID\n");
return DSERR_INVALIDPARAM;
}
- hr = get_mmdevice(eRender, &devGUID, &mmdevice);
- if(FAILED(hr))
- return hr;
+ /* Enumerate WINMM audio devices and find the one we want */
+ wodn = waveOutGetNumDevs();
+ if (!wodn) {
+ WARN("no driver\n");
+ return DSERR_NODRIVER;
+ }
- EnterCriticalSection(&DSOUND_renderers_lock);
+ for (wod=0; wod<wodn; wod++) {
+ if (IsEqualGUID( &devGUID, &DSOUND_renderer_guids[wod])) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (found == FALSE) {
+ WARN("No device found matching given ID!\n");
+ return DSERR_NODRIVER;
+ }
- LIST_FOR_EACH_ENTRY(device, &DSOUND_renderers, DirectSoundDevice, entry){
- if(IsEqualGUID(&device->guid, &devGUID)){
- IMMDevice_Release(mmdevice);
+ if (DSOUND_renderer[wod]) {
+ if (IsEqualGUID(&devGUID, &DSOUND_renderer[wod]->guid)) {
+ device = DSOUND_renderer[wod];
DirectSoundDevice_AddRef(device);
*ppDevice = device;
- LeaveCriticalSection(&DSOUND_renderers_lock);
return DS_OK;
+ } else {
+ ERR("device GUID doesn't match\n");
+ hr = DSERR_GENERIC;
+ return hr;
+ }
+ } else {
+ hr = DirectSoundDevice_Create(&device);
+ if (hr != DS_OK) {
+ WARN("DirectSoundDevice_Create failed\n");
+ return hr;
}
}
- hr = DirectSoundDevice_Create(&device);
- if(FAILED(hr)){
- WARN("DirectSoundDevice_Create failed\n");
- IMMDevice_Release(mmdevice);
- LeaveCriticalSection(&DSOUND_renderers_lock);
- return hr;
- }
-
- device->mmdevice = mmdevice;
+ *ppDevice = device;
device->guid = devGUID;
- device->sleepev = CreateEventW(0, 0, 0, 0);
+ device->driver = NULL;
+ device->drvdesc.dnDevNode = wod;
hr = DSOUND_ReopenDevice(device, FALSE);
if (FAILED(hr))
{
- HeapFree(GetProcessHeap(), 0, device);
- LeaveCriticalSection(&DSOUND_renderers_lock);
- IMMDevice_Release(mmdevice);
WARN("DSOUND_ReopenDevice failed: %08x\n", hr);
return hr;
}
- ZeroMemory(&device->drvcaps, sizeof(device->drvcaps));
-
- if(DSOUND_check_supported(device->client, 11025, 8, 1) ||
- DSOUND_check_supported(device->client, 22050, 8, 1) ||
- DSOUND_check_supported(device->client, 44100, 8, 1) ||
- DSOUND_check_supported(device->client, 48000, 8, 1) ||
- DSOUND_check_supported(device->client, 96000, 8, 1))
- device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT | DSCAPS_PRIMARYMONO;
-
- if(DSOUND_check_supported(device->client, 11025, 16, 1) ||
- DSOUND_check_supported(device->client, 22050, 16, 1) ||
- DSOUND_check_supported(device->client, 44100, 16, 1) ||
- DSOUND_check_supported(device->client, 48000, 16, 1) ||
- DSOUND_check_supported(device->client, 96000, 16, 1))
- device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT | DSCAPS_PRIMARYMONO;
-
- if(DSOUND_check_supported(device->client, 11025, 8, 2) ||
- DSOUND_check_supported(device->client, 22050, 8, 2) ||
- DSOUND_check_supported(device->client, 44100, 8, 2) ||
- DSOUND_check_supported(device->client, 48000, 8, 2) ||
- DSOUND_check_supported(device->client, 96000, 8, 2))
- device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT | DSCAPS_PRIMARYSTEREO;
-
- if(DSOUND_check_supported(device->client, 11025, 16, 2) ||
- DSOUND_check_supported(device->client, 22050, 16, 2) ||
- DSOUND_check_supported(device->client, 44100, 16, 2) ||
- DSOUND_check_supported(device->client, 48000, 16, 2) ||
- DSOUND_check_supported(device->client, 96000, 16, 2))
- device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT | DSCAPS_PRIMARYSTEREO;
-
- /* the dsound mixer supports all of the following */
- device->drvcaps.dwFlags |= DSCAPS_SECONDARY8BIT | DSCAPS_SECONDARY16BIT;
- device->drvcaps.dwFlags |= DSCAPS_SECONDARYMONO | DSCAPS_SECONDARYSTEREO;
- device->drvcaps.dwFlags |= DSCAPS_CONTINUOUSRATE;
-
- device->drvcaps.dwPrimaryBuffers = 1;
- device->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
- device->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
- device->drvcaps.dwMaxHwMixingAllBuffers = 1;
- device->drvcaps.dwMaxHwMixingStaticBuffers = 1;
- device->drvcaps.dwMaxHwMixingStreamingBuffers = 1;
-
- ZeroMemory(&device->volpan, sizeof(device->volpan));
+ if (device->driver) {
+ /* the driver is now open, so it's now allowed to call GetCaps */
+ hr = IDsDriver_GetCaps(device->driver,&(device->drvcaps));
+ if (hr != DS_OK) {
+ WARN("IDsDriver_GetCaps failed\n");
+ return hr;
+ }
+ } else {
+ WAVEOUTCAPSA woc;
+ hr = mmErr(waveOutGetDevCapsA(device->drvdesc.dnDevNode, &woc, sizeof(woc)));
+ if (hr != DS_OK) {
+ WARN("waveOutGetDevCaps failed\n");
+ return hr;
+ }
+ ZeroMemory(&device->drvcaps, sizeof(device->drvcaps));
+ if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
+ (woc.dwFormats & WAVE_FORMAT_2M08) ||
+ (woc.dwFormats & WAVE_FORMAT_4M08) ||
+ (woc.dwFormats & WAVE_FORMAT_48M08) ||
+ (woc.dwFormats & WAVE_FORMAT_96M08)) {
+ device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
+ device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
+ }
+ if ((woc.dwFormats & WAVE_FORMAT_1M16) ||
+ (woc.dwFormats & WAVE_FORMAT_2M16) ||
+ (woc.dwFormats & WAVE_FORMAT_4M16) ||
+ (woc.dwFormats & WAVE_FORMAT_48M16) ||
+ (woc.dwFormats & WAVE_FORMAT_96M16)) {
+ device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
+ device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
+ }
+ if ((woc.dwFormats & WAVE_FORMAT_1S08) ||
+ (woc.dwFormats & WAVE_FORMAT_2S08) ||
+ (woc.dwFormats & WAVE_FORMAT_4S08) ||
+ (woc.dwFormats & WAVE_FORMAT_48S08) ||
+ (woc.dwFormats & WAVE_FORMAT_96S08)) {
+ device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
+ device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
+ }
+ if ((woc.dwFormats & WAVE_FORMAT_1S16) ||
+ (woc.dwFormats & WAVE_FORMAT_2S16) ||
+ (woc.dwFormats & WAVE_FORMAT_4S16) ||
+ (woc.dwFormats & WAVE_FORMAT_48S16) ||
+ (woc.dwFormats & WAVE_FORMAT_96S16)) {
+ device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
+ device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
+ }
+ if (ds_emuldriver)
+ device->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
+ device->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
+ device->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
+ ZeroMemory(&device->volpan, sizeof(device->volpan));
+ }
hr = DSOUND_PrimaryCreate(device);
if (hr == DS_OK) {
- device->thread = CreateThread(0, 0, DSOUND_mixthread, device, 0, 0);
- SetThreadPriority(device->thread, THREAD_PRIORITY_TIME_CRITICAL);
- } else
- WARN("DSOUND_PrimaryCreate failed: %08x\n", hr);
-
- *ppDevice = device;
- list_add_tail(&DSOUND_renderers, &device->entry);
-
- LeaveCriticalSection(&DSOUND_renderers_lock);
+ UINT triggertime = DS_TIME_DEL, res = DS_TIME_RES, id;
+ TIMECAPS time;
+
+ DSOUND_renderer[device->drvdesc.dnDevNode] = device;
+ timeGetDevCaps(&time, sizeof(TIMECAPS));
+ TRACE("Minimum timer resolution: %u, max timer: %u\n", time.wPeriodMin, time.wPeriodMax);
+ if (triggertime < time.wPeriodMin)
+ triggertime = time.wPeriodMin;
+ if (res < time.wPeriodMin)
+ res = time.wPeriodMin;
+ if (timeBeginPeriod(res) == TIMERR_NOCANDO)
+ WARN("Could not set minimum resolution, don't expect sound\n");
+ id = timeSetEvent(triggertime, res, DSOUND_timer, (DWORD_PTR)device, TIME_PERIODIC | TIME_KILL_SYNCHRONOUS);
+ if (!id)
+ {
+ WARN("Timer not created! Retrying without TIME_KILL_SYNCHRONOUS\n");
+ id = timeSetEvent(triggertime, res, DSOUND_timer, (DWORD_PTR)device, TIME_PERIODIC);
+ if (!id) ERR("Could not create timer, sound playback will not occur\n");
+ }
+ DSOUND_renderer[device->drvdesc.dnDevNode]->timerID = id;
+ } else {
+ WARN("DSOUND_PrimaryCreate failed\n");
+ }
return hr;
}
TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat);
}
- if (dsbd->dwFlags & DSBCAPS_LOCHARDWARE &&
- !(dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER)) {
- TRACE("LOCHARDWARE is not supported, returning E_NOTIMPL\n");
- return E_NOTIMPL;
- }
-
if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
if (dsbd->lpwfxFormat != NULL) {
WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
if (device->primary) {
*ppdsb = (IDirectSoundBuffer*)&device->primary->IDirectSoundBuffer8_iface;
device->primary->dsbd.dwFlags &= ~(DSBCAPS_LOCHARDWARE | DSBCAPS_LOCSOFTWARE);
- device->primary->dsbd.dwFlags |= DSBCAPS_LOCSOFTWARE;
+ if (device->hwbuf)
+ device->primary->dsbd.dwFlags |= DSBCAPS_LOCHARDWARE;
+ else
+ device->primary->dsbd.dwFlags |= DSBCAPS_LOCSOFTWARE;
} else
WARN("primarybuffer_create() failed\n");
}
}
pwfxe = (WAVEFORMATEXTENSIBLE*)dsbd->lpwfxFormat;
+ if (pwfxe->Format.wBitsPerSample != 16 && pwfxe->Format.wBitsPerSample != 8 && pwfxe->Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE)
+ {
+ WARN("wBitsPerSample=%d needs a WAVEFORMATEXTENSIBLE\n", dsbd->lpwfxFormat->wBitsPerSample);
+ return DSERR_CONTROLUNAVAIL;
+ }
if (pwfxe->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE)
{
/* check if cbSize is at least 22 bytes */
return hres;
}
+HRESULT DirectSoundDevice_SetCooperativeLevel(
+ DirectSoundDevice * device,
+ HWND hwnd,
+ DWORD level)
+{
+ TRACE("(%p,%p,%s)\n",device,hwnd,dumpCooperativeLevel(level));
+
+ if (device == NULL) {
+ WARN("not initialized\n");
+ return DSERR_UNINITIALIZED;
+ }
+
+ if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) {
+ WARN("level=%s not fully supported\n",
+ level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
+ }
+
+ device->priolevel = level;
+ return DS_OK;
+}
+
+HRESULT DirectSoundDevice_Compact(
+ DirectSoundDevice * device)
+{
+ TRACE("(%p)\n", device);
+
+ if (device == NULL) {
+ WARN("not initialized\n");
+ return DSERR_UNINITIALIZED;
+ }
+
+ if (device->priolevel < DSSCL_PRIORITY) {
+ WARN("incorrect priority level\n");
+ return DSERR_PRIOLEVELNEEDED;
+ }
+
+ return DS_OK;
+}
+
+HRESULT DirectSoundDevice_GetSpeakerConfig(
+ DirectSoundDevice * device,
+ LPDWORD lpdwSpeakerConfig)
+{
+ TRACE("(%p, %p)\n", device, lpdwSpeakerConfig);
+
+ if (device == NULL) {
+ WARN("not initialized\n");
+ return DSERR_UNINITIALIZED;
+ }
+
+ if (lpdwSpeakerConfig == NULL) {
+ WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
+ return DSERR_INVALIDPARAM;
+ }
+
+ WARN("not fully functional\n");
+ *lpdwSpeakerConfig = device->speaker_config;
+ return DS_OK;
+}
+
+HRESULT DirectSoundDevice_SetSpeakerConfig(
+ DirectSoundDevice * device,
+ DWORD config)
+{
+ TRACE("(%p,0x%08x)\n",device,config);
+
+ if (device == NULL) {
+ WARN("not initialized\n");
+ return DSERR_UNINITIALIZED;
+ }
+
+ device->speaker_config = config;
+ WARN("not fully functional\n");
+ return DS_OK;
+}
+
+HRESULT DirectSoundDevice_VerifyCertification(
+ DirectSoundDevice * device,
+ LPDWORD pdwCertified)
+{
+ TRACE("(%p, %p)\n",device,pdwCertified);
+
+ if (device == NULL) {
+ WARN("not initialized\n");
+ return DSERR_UNINITIALIZED;
+ }
+
+ if (device->drvcaps.dwFlags & DSCAPS_CERTIFIED)
+ *pdwCertified = DS_CERTIFIED;
+ else
+ *pdwCertified = DS_UNCERTIFIED;
+
+ return DS_OK;
+}
+
/*
* Add secondary buffer to buffer list.
* Gets exclusive access to buffer for writing.
* Remove secondary buffer from buffer list.
* Gets exclusive access to buffer for writing.
*/
-void DirectSoundDevice_RemoveBuffer(DirectSoundDevice * device, IDirectSoundBufferImpl * pDSB)
+HRESULT DirectSoundDevice_RemoveBuffer(
+ DirectSoundDevice * device,
+ IDirectSoundBufferImpl * pDSB)
{
int i;
+ HRESULT hr = DS_OK;
TRACE("(%p, %p)\n", device, pDSB);
RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE);
- if (device->nrofbuffers == 1) {
- assert(device->buffers[0] == pDSB);
- HeapFree(GetProcessHeap(), 0, device->buffers);
+ for (i = 0; i < device->nrofbuffers; i++)
+ if (device->buffers[i] == pDSB)
+ break;
+
+ if (i < device->nrofbuffers) {
+ /* Put the last buffer of the list in the (now empty) position */
+ device->buffers[i] = device->buffers[device->nrofbuffers - 1];
+ device->nrofbuffers--;
+ device->buffers = HeapReAlloc(GetProcessHeap(),0,device->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*device->nrofbuffers);
+ TRACE("buffer count is now %d\n", device->nrofbuffers);
+ }
+
+ if (device->nrofbuffers == 0) {
+ HeapFree(GetProcessHeap(),0,device->buffers);
device->buffers = NULL;
- } else {
- for (i = 0; i < device->nrofbuffers; i++) {
- if (device->buffers[i] == pDSB) {
- /* Put the last buffer of the list in the (now empty) position */
- device->buffers[i] = device->buffers[device->nrofbuffers - 1];
- break;
- }
- }
}
- device->nrofbuffers--;
- TRACE("buffer count is now %d\n", device->nrofbuffers);
RtlReleaseResource(&(device->buffer_list_lock));
+
+ return hr;
}
#define le32(x) (x)
#endif
-/* This is an inlined version of lrintf. */
-#if defined(_MSC_VER)
-#if defined(_M_AMD64)
-#include <xmmintrin.h>
-#endif
+static inline void src_advance(const void **src, UINT stride, INT *count, UINT *freqAcc, UINT adj)
+{
+ *freqAcc += adj;
+ if (*freqAcc >= (1 << DSOUND_FREQSHIFT))
+ {
+ ULONG adv = (*freqAcc >> DSOUND_FREQSHIFT);
+ *freqAcc &= (1 << DSOUND_FREQSHIFT) - 1;
+ *(const char **)src += adv * stride;
+ *count -= adv;
+ }
+}
-FORCEINLINE
-int
-lrintf(float f)
+static void convert_8_to_8 (const void *src, void *dst, UINT src_stride,
+ UINT dst_stride, INT count, UINT freqAcc, UINT adj)
{
-#if defined(_M_IX86)
- int result;
- __asm
+ while (count > 0)
{
- fld f;
- fistp result;
+ *(BYTE *)dst = *(const BYTE *)src;
+
+ dst = (char *)dst + dst_stride;
+ src_advance(&src, src_stride, &count, &freqAcc, adj);
}
- return result;
-#elif defined(_M_AMD64)
- return _mm_cvtss_si32(_mm_load_ss(&f));
-#endif
}
-#endif
-static float get8(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel)
+static void convert_8_to_16 (const void *src, void *dst, UINT src_stride,
+ UINT dst_stride, INT count, UINT freqAcc, UINT adj)
{
- const BYTE* buf = dsb->buffer->memory;
- buf += pos + channel;
- return (buf[0] - 0x80) / (float)0x80;
+ while (count > 0)
+ {
+ WORD dest = *(const BYTE *)src, *dest16 = dst;
+ *dest16 = le16(dest * 257 - 32768);
+
+ dst = (char *)dst + dst_stride;
+ src_advance(&src, src_stride, &count, &freqAcc, adj);
+ }
}
-static float get16(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel)
+static void convert_8_to_24 (const void *src, void *dst, UINT src_stride,
+ UINT dst_stride, INT count, UINT freqAcc, UINT adj)
{
- const BYTE* buf = dsb->buffer->memory;
- const SHORT *sbuf = (const SHORT*)(buf + pos + 2 * channel);
- SHORT sample = (SHORT)le16(*sbuf);
- return sample / (float)0x8000;
+ while (count > 0)
+ {
+ BYTE dest = *(const BYTE *)src;
+ BYTE *dest24 = dst;
+ dest24[0] = dest;
+ dest24[1] = dest;
+ dest24[2] = dest - 0x80;
+
+ dst = (char *)dst + dst_stride;
+ src_advance(&src, src_stride, &count, &freqAcc, adj);
+ }
}
-static float get24(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel)
+static void convert_8_to_32 (const void *src, void *dst, UINT src_stride,
+ UINT dst_stride, INT count, UINT freqAcc, UINT adj)
{
- LONG sample;
- const BYTE* buf = dsb->buffer->memory;
- buf += pos + 3 * channel;
- /* The next expression deliberately has an overflow for buf[2] >= 0x80,
- this is how negative values are made.
- */
- sample = (buf[0] << 8) | (buf[1] << 16) | (buf[2] << 24);
- return sample / (float)0x80000000U;
+ while (count > 0)
+ {
+ DWORD dest = *(const BYTE *)src, *dest32 = dst;
+ *dest32 = le32(dest * 16843009 - 2147483648U);
+
+ dst = (char *)dst + dst_stride;
+ src_advance(&src, src_stride, &count, &freqAcc, adj);
+ }
}
-static float get32(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel)
+static void convert_16_to_8 (const void *src, void *dst, UINT src_stride,
+ UINT dst_stride, INT count, UINT freqAcc, UINT adj)
{
- const BYTE* buf = dsb->buffer->memory;
- const LONG *sbuf = (const LONG*)(buf + pos + 4 * channel);
- LONG sample = le32(*sbuf);
- return sample / (float)0x80000000U;
+ while (count > 0)
+ {
+ BYTE *dst8 = dst;
+ *dst8 = (le16(*(const WORD *)src)) / 256;
+ *dst8 -= 0x80;
+
+ dst = (char *)dst + dst_stride;
+ src_advance(&src, src_stride, &count, &freqAcc, adj);
+ }
}
-static float getieee32(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel)
+static void convert_16_to_16 (const void *src, void *dst, UINT src_stride,
+ UINT dst_stride, INT count, UINT freqAcc, UINT adj)
{
- const BYTE* buf = dsb->buffer->memory;
- const float *sbuf = (const float*)(buf + pos + 4 * channel);
- /* The value will be clipped later, when put into some non-float buffer */
- return *sbuf;
+ while (count > 0)
+ {
+ *(WORD *)dst = *(const WORD *)src;
+
+ dst = (char *)dst + dst_stride;
+ src_advance(&src, src_stride, &count, &freqAcc, adj);
+ }
}
-const bitsgetfunc getbpp[5] = {get8, get16, get24, get32, getieee32};
+static void convert_16_to_24 (const void *src, void *dst, UINT src_stride,
+ UINT dst_stride, INT count, UINT freqAcc, UINT adj)
+{
+ while (count > 0)
+ {
+ WORD dest = le16(*(const WORD *)src);
+ BYTE *dest24 = dst;
+
+ dest24[0] = dest / 256;
+ dest24[1] = dest;
+ dest24[2] = dest / 256;
+
+ dst = (char *)dst + dst_stride;
+ src_advance(&src, src_stride, &count, &freqAcc, adj);
+ }
+}
-float get_mono(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel)
+static void convert_16_to_32 (const void *src, void *dst, UINT src_stride,
+ UINT dst_stride, INT count, UINT freqAcc, UINT adj)
{
- DWORD channels = dsb->pwfx->nChannels;
- DWORD c;
- float val = 0;
- /* XXX: does Windows include LFE into the mix? */
- for (c = 0; c < channels; c++)
- val += dsb->get_aux(dsb, pos, c);
- val /= channels;
- return val;
+ while (count > 0)
+ {
+ DWORD dest = *(const WORD *)src, *dest32 = dst;
+ *dest32 = dest * 65537;
+
+ dst = (char *)dst + dst_stride;
+ src_advance(&src, src_stride, &count, &freqAcc, adj);
+ }
}
-static inline unsigned char f_to_8(float value)
+static void convert_24_to_8 (const void *src, void *dst, UINT src_stride,
+ UINT dst_stride, INT count, UINT freqAcc, UINT adj)
{
- if(value <= -1.f)
- return 0;
- if(value >= 1.f * 0x7f / 0x80)
- return 0xFF;
- return lrintf((value + 1.f) * 0x80);
+ while (count > 0)
+ {
+ BYTE *dst8 = dst;
+ *dst8 = ((const BYTE *)src)[2];
+
+ dst = (char *)dst + dst_stride;
+ src_advance(&src, src_stride, &count, &freqAcc, adj);
+ }
+}
+
+static void convert_24_to_16 (const void *src, void *dst, UINT src_stride,
+ UINT dst_stride, INT count, UINT freqAcc, UINT adj)
+{
+ while (count > 0)
+ {
+ WORD *dest16 = dst;
+ const BYTE *source = src;
+ *dest16 = le16(source[2] * 256 + source[1]);
+
+ dst = (char *)dst + dst_stride;
+ src_advance(&src, src_stride, &count, &freqAcc, adj);
+ }
}
-static inline SHORT f_to_16(float value)
+static void convert_24_to_24 (const void *src, void *dst, UINT src_stride,
+ UINT dst_stride, INT count, UINT freqAcc, UINT adj)
{
- if(value <= -1.f)
- return 0x8000;
- if(value >= 1.f * 0x7FFF / 0x8000)
- return 0x7FFF;
- return le16(lrintf(value * 0x8000));
+ while (count > 0)
+ {
+ BYTE *dest24 = dst;
+ const BYTE *src24 = src;
+
+ dest24[0] = src24[0];
+ dest24[1] = src24[1];
+ dest24[2] = src24[2];
+
+ dst = (char *)dst + dst_stride;
+ src_advance(&src, src_stride, &count, &freqAcc, adj);
+ }
}
-static LONG f_to_24(float value)
+static void convert_24_to_32 (const void *src, void *dst, UINT src_stride,
+ UINT dst_stride, INT count, UINT freqAcc, UINT adj)
{
- if(value <= -1.f)
- return 0x80000000;
- if(value >= 1.f * 0x7FFFFF / 0x800000)
- return 0x7FFFFF00;
- return lrintf(value * 0x80000000U);
+ while (count > 0)
+ {
+ DWORD *dest32 = dst;
+ const BYTE *source = src;
+ *dest32 = le32(source[2] * 16777217 + source[1] * 65536 + source[0] * 256);
+
+ dst = (char *)dst + dst_stride;
+ src_advance(&src, src_stride, &count, &freqAcc, adj);
+ }
}
-static inline LONG f_to_32(float value)
+static void convert_32_to_8 (const void *src, void *dst, UINT src_stride,
+ UINT dst_stride, INT count, UINT freqAcc, UINT adj)
{
- if(value <= -1.f)
- return 0x80000000;
- if(value >= 1.f * 0x7FFFFFFF / 0x80000000U) /* this rounds to 1.f */
- return 0x7FFFFFFF;
- return le32(lrintf(value * 0x80000000U));
+ while (count > 0)
+ {
+ BYTE *dst8 = dst;
+ *dst8 = (le32(*(const DWORD *)src) / 16777216);
+ *dst8 -= 0x80;
+
+ dst = (char *)dst + dst_stride;
+ src_advance(&src, src_stride, &count, &freqAcc, adj);
+ }
}
-void putieee32(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value)
+static void convert_32_to_16 (const void *src, void *dst, UINT src_stride,
+ UINT dst_stride, INT count, UINT freqAcc, UINT adj)
{
- BYTE *buf = (BYTE *)dsb->device->tmp_buffer;
- float *fbuf = (float*)(buf + pos + sizeof(float) * channel);
- *fbuf = value;
+ while (count > 0)
+ {
+ WORD *dest16 = dst;
+ *dest16 = le16(le32(*(const DWORD *)src) / 65536);
+
+ dst = (char *)dst + dst_stride;
+ src_advance(&src, src_stride, &count, &freqAcc, adj);
+ }
}
-void put_mono2stereo(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value)
+static void convert_32_to_24 (const void *src, void *dst, UINT src_stride,
+ UINT dst_stride, INT count, UINT freqAcc, UINT adj)
{
- dsb->put_aux(dsb, pos, 0, value);
- dsb->put_aux(dsb, pos, 1, value);
+ while (count > 0)
+ {
+ DWORD dest = le32(*(const DWORD *)src);
+ BYTE *dest24 = dst;
+
+ dest24[0] = dest / 256;
+ dest24[1] = dest / 65536;
+ dest24[2] = dest / 16777216;
+
+ dst = (char *)dst + dst_stride;
+ src_advance(&src, src_stride, &count, &freqAcc, adj);
+ }
}
-void mixieee32(float *src, float *dst, unsigned samples)
+static void convert_32_to_32 (const void *src, void *dst, UINT src_stride,
+ UINT dst_stride, INT count, UINT freqAcc, UINT adj)
{
- TRACE("%p - %p %d\n", src, dst, samples);
- while (samples--)
- *(dst++) += *(src++);
+ while (count > 0)
+ {
+ DWORD *dest = dst;
+ *dest = *(const DWORD *)src;
+
+ dst = (char *)dst + dst_stride;
+ src_advance(&src, src_stride, &count, &freqAcc, adj);
+ }
}
-static void norm8(float *src, unsigned char *dst, unsigned len)
+static void convert_ieee_32_to_8 (const void *src, void *dst, UINT src_stride,
+ UINT dst_stride, INT count, UINT freqAcc, UINT adj)
+{
+ while (count > 0)
+ {
+ DWORD src_le = le32(*(DWORD *) src);
+ float v = *((float *) &src_le);
+ INT8 d = 0;
+
+ if (v < -1.0f)
+ d = -128;
+ else if (v > 1.0f)
+ d = 127;
+ else
+ d = v * 127.5f - 0.5f;
+
+ *(BYTE *) dst = d ^ 0x80;
+
+ dst = (char *)dst + dst_stride;
+ src_advance(&src, src_stride, &count, &freqAcc, adj);
+ }
+}
+
+static void convert_ieee_32_to_16 (const void *src, void *dst, UINT src_stride,
+ UINT dst_stride, INT count, UINT freqAcc, UINT adj)
+{
+ while (count > 0)
+ {
+ DWORD src_le = le32(*(DWORD *) src);
+ float v = *((float *) &src_le);
+
+ INT16 *d = (INT16 *) dst;
+
+ if (v < -1.0f)
+ *d = -32768;
+ else if (v > 1.0f)
+ *d = 32767;
+ else
+ *d = v * 32767.5f - 0.5f;
+
+ *d = le16(*d);
+
+ dst = (char *)dst + dst_stride;
+ src_advance(&src, src_stride, &count, &freqAcc, adj);
+ }
+}
+
+static void convert_ieee_32_to_24 (const void *src, void *dst, UINT src_stride,
+ UINT dst_stride, INT count, UINT freqAcc, UINT adj)
+{
+ while (count > 0)
+ {
+ DWORD src_le = le32(*(DWORD *) src);
+ float v = *((float *) &src_le);
+ BYTE *dest24 = dst;
+
+ if (v < -1.0f)
+ {
+ dest24[0] = 0;
+ dest24[1] = 0;
+ dest24[2] = 0x80;
+ }
+ else if (v > 1.0f)
+ {
+ dest24[0] = 0xff;
+ dest24[1] = 0xff;
+ dest24[2] = 0x7f;
+ }
+ else if (v < 0.0f)
+ {
+ dest24[0] = v * 8388608.0f;
+ dest24[1] = v * 32768.0f;
+ dest24[2] = v * 128.0f;
+ }
+ else if (v >= 0.0f)
+ {
+ dest24[0] = v * 8388608.0f;
+ dest24[1] = v * 32768.0f;
+ dest24[2] = v * 127.0f;
+ }
+
+ dst = (char *)dst + dst_stride;
+ src_advance(&src, src_stride, &count, &freqAcc, adj);
+ }
+}
+
+static void convert_ieee_32_to_32 (const void *src, void *dst, UINT src_stride,
+ UINT dst_stride, INT count, UINT freqAcc, UINT adj)
+{
+ while (count > 0)
+ {
+ DWORD src_le = le32(*(DWORD *) src);
+ float v = *((float *) &src_le);
+ INT32 *d = (INT32 *) dst;
+
+ if (v < -1.0f)
+ *d = -2147483647 - 1; /* silence warning */
+ else if (v > 1.0f)
+ *d = 2147483647;
+ else
+ *d = v * 2147483647.5f - 0.5f;
+
+ *d = le32(*d);
+
+ dst = (char *)dst + dst_stride;
+ src_advance(&src, src_stride, &count, &freqAcc, adj);
+ }
+}
+
+const bitsconvertfunc convertbpp[5][4] = {
+ { convert_8_to_8, convert_8_to_16, convert_8_to_24, convert_8_to_32 },
+ { convert_16_to_8, convert_16_to_16, convert_16_to_24, convert_16_to_32 },
+ { convert_24_to_8, convert_24_to_16, convert_24_to_24, convert_24_to_32 },
+ { convert_32_to_8, convert_32_to_16, convert_32_to_24, convert_32_to_32 },
+ { convert_ieee_32_to_8, convert_ieee_32_to_16, convert_ieee_32_to_24, convert_ieee_32_to_32 },
+};
+
+static void mix8(signed char *src, INT *dst, unsigned len)
+{
+ TRACE("%p - %p %d\n", src, dst, len);
+ while (len--)
+ /* 8-bit WAV is unsigned, it's here converted to signed, normalize function will convert it back again */
+ *(dst++) += (signed char)((BYTE)*(src++) - (BYTE)0x80);
+}
+
+static void mix16(SHORT *src, INT *dst, unsigned len)
{
TRACE("%p - %p %d\n", src, dst, len);
+ len /= 2;
while (len--)
{
- *dst = f_to_8(*src);
- ++dst;
+ *dst += le16(*src);
+ ++dst; ++src;
+ }
+}
+
+static void mix24(BYTE *src, INT *dst, unsigned len)
+{
+ TRACE("%p - %p %d\n", src, dst, len);
+ len /= 3;
+ while (len--)
+ {
+ DWORD field;
+ field = ((DWORD)src[2] << 16) + ((DWORD)src[1] << 8) + (DWORD)src[0];
+ if (src[2] & 0x80)
+ field |= 0xFF000000U;
+ *(dst++) += field;
++src;
}
}
-static void norm16(float *src, SHORT *dst, unsigned len)
+static void mix32(INT *src, LONGLONG *dst, unsigned len)
+{
+ TRACE("%p - %p %d\n", src, dst, len);
+ len /= 4;
+ while (len--)
+ *(dst++) += le32(*(src++));
+}
+
+const mixfunc mixfunctions[4] = {
+ (mixfunc)mix8,
+ (mixfunc)mix16,
+ (mixfunc)mix24,
+ (mixfunc)mix32
+};
+
+static void norm8(INT *src, signed char *dst, unsigned len)
{
TRACE("%p - %p %d\n", src, dst, len);
- len /= 2;
while (len--)
{
- *dst = f_to_16(*src);
+ *dst = (*src) + 0x80;
+ if (*src < -0x80)
+ *dst = 0;
+ else if (*src > 0x7f)
+ *dst = 0xff;
++dst;
++src;
}
}
-static void norm24(float *src, BYTE *dst, unsigned len)
+static void norm16(INT *src, SHORT *dst, unsigned len)
{
TRACE("%p - %p %d\n", src, dst, len);
- len /= 3;
+ len /= 2;
while (len--)
{
- LONG t = f_to_24(*src);
- dst[0] = (t >> 8) & 0xFF;
- dst[1] = (t >> 16) & 0xFF;
- dst[2] = t >> 24;
- dst += 3;
+ *dst = le16(*src);
+ if (*src <= -0x8000)
+ *dst = le16(0x8000);
+ else if (*src > 0x7fff)
+ *dst = le16(0x7fff);
+ ++dst;
++src;
}
}
-static void norm32(float *src, INT *dst, unsigned len)
+static void norm24(INT *src, BYTE *dst, unsigned len)
{
TRACE("%p - %p %d\n", src, dst, len);
- len /= 4;
+ len /= 3;
while (len--)
{
- *dst = f_to_32(*src);
+ if (*src <= -0x800000)
+ {
+ dst[0] = 0;
+ dst[1] = 0;
+ dst[2] = 0x80;
+ }
+ else if (*src > 0x7fffff)
+ {
+ dst[0] = 0xff;
+ dst[1] = 0xff;
+ dst[2] = 0x7f;
+ }
+ else
+ {
+ dst[0] = *src;
+ dst[1] = *src >> 8;
+ dst[2] = *src >> 16;
+ }
++dst;
++src;
}
}
-static void normieee32(float *src, float *dst, unsigned len)
+static void norm32(LONGLONG *src, INT *dst, unsigned len)
{
TRACE("%p - %p %d\n", src, dst, len);
len /= 4;
while (len--)
{
- if(*src > 1)
- *dst = 1;
- else if(*src < -1)
- *dst = -1;
- else
- *dst = *src;
+ *dst = le32(*src);
+ if (*src <= -(LONGLONG)0x80000000)
+ *dst = le32(0x80000000);
+ else if (*src > 0x7fffffff)
+ *dst = le32(0x7fffffff);
++dst;
++src;
}
}
-const normfunc normfunctions[5] = {
+const normfunc normfunctions[4] = {
(normfunc)norm8,
(normfunc)norm16,
(normfunc)norm24,
(normfunc)norm32,
- (normfunc)normieee32
};
#include <winreg.h>
#include <rpcproxy.h>
-struct list DSOUND_renderers = LIST_INIT(DSOUND_renderers);
-CRITICAL_SECTION DSOUND_renderers_lock;
-static CRITICAL_SECTION_DEBUG DSOUND_renderers_lock_debug =
-{
- 0, 0, &DSOUND_renderers_lock,
- { &DSOUND_renderers_lock_debug.ProcessLocksList, &DSOUND_renderers_lock_debug.ProcessLocksList },
- 0, 0, { (DWORD_PTR)(__FILE__ ": DSOUND_renderers_lock") }
-};
-CRITICAL_SECTION DSOUND_renderers_lock = { &DSOUND_renderers_lock_debug, -1, 0, 0, 0, 0 };
-
-struct list DSOUND_capturers = LIST_INIT(DSOUND_capturers);
-CRITICAL_SECTION DSOUND_capturers_lock;
-static CRITICAL_SECTION_DEBUG DSOUND_capturers_lock_debug =
-{
- 0, 0, &DSOUND_capturers_lock,
- { &DSOUND_capturers_lock_debug.ProcessLocksList, &DSOUND_capturers_lock_debug.ProcessLocksList },
- 0, 0, { (DWORD_PTR)(__FILE__ ": DSOUND_capturers_lock") }
-};
-CRITICAL_SECTION DSOUND_capturers_lock = { &DSOUND_capturers_lock_debug, -1, 0, 0, 0, 0 };
-
+DirectSoundDevice* DSOUND_renderer[MAXWAVEDRIVERS];
GUID DSOUND_renderer_guids[MAXWAVEDRIVERS];
GUID DSOUND_capture_guids[MAXWAVEDRIVERS];
-WCHAR wine_vxd_drv[] = { 'w','i','n','e','m','m','.','v','x','d', 0 };
+HRESULT mmErr(UINT err)
+{
+ switch(err) {
+ case MMSYSERR_NOERROR:
+ return DS_OK;
+ case MMSYSERR_ALLOCATED:
+ return DSERR_ALLOCATED;
+ case MMSYSERR_ERROR:
+ case MMSYSERR_INVALHANDLE:
+ case WAVERR_STILLPLAYING:
+ return DSERR_GENERIC; /* FIXME */
+ case MMSYSERR_NODRIVER:
+ return DSERR_NODRIVER;
+ case MMSYSERR_NOMEM:
+ return DSERR_OUTOFMEMORY;
+ case MMSYSERR_INVALPARAM:
+ case WAVERR_BADFORMAT:
+ case WAVERR_UNPREPARED:
+ return DSERR_INVALIDPARAM;
+ case MMSYSERR_NOTSUPPORTED:
+ return DSERR_UNSUPPORTED;
+ default:
+ FIXME("Unknown MMSYS error %d\n",err);
+ return DSERR_GENERIC;
+ }
+}
/* All default settings, you most likely don't want to touch these, see wiki on UsefulRegistryKeys */
+int ds_emuldriver = 0;
int ds_hel_buflen = 32768 * 2;
int ds_snd_queue_max = 10;
+int ds_snd_queue_min = 6;
+int ds_snd_shadow_maxsize = 2;
+int ds_hw_accel = DS_HW_ACCEL_FULL;
+int ds_default_sample_rate = 44100;
+int ds_default_bits_per_sample = 16;
+static int ds_default_playback;
+static int ds_default_capture;
static HINSTANCE instance;
/*
/* get options */
+ if (!get_config_key( hkey, appkey, "EmulDriver", buffer, MAX_PATH ))
+ ds_emuldriver = strcmp(buffer, "N");
+
if (!get_config_key( hkey, appkey, "HelBuflen", buffer, MAX_PATH ))
ds_hel_buflen = atoi(buffer);
if (!get_config_key( hkey, appkey, "SndQueueMax", buffer, MAX_PATH ))
ds_snd_queue_max = atoi(buffer);
+ if (!get_config_key( hkey, appkey, "SndQueueMin", buffer, MAX_PATH ))
+ ds_snd_queue_min = atoi(buffer);
+
+ if (!get_config_key( hkey, appkey, "HardwareAcceleration", buffer, MAX_PATH )) {
+ if (strcmp(buffer, "Full") == 0)
+ ds_hw_accel = DS_HW_ACCEL_FULL;
+ else if (strcmp(buffer, "Standard") == 0)
+ ds_hw_accel = DS_HW_ACCEL_STANDARD;
+ else if (strcmp(buffer, "Basic") == 0)
+ ds_hw_accel = DS_HW_ACCEL_BASIC;
+ else if (strcmp(buffer, "Emulation") == 0)
+ ds_hw_accel = DS_HW_ACCEL_EMULATION;
+ }
+
+ if (!get_config_key( hkey, appkey, "DefaultPlayback", buffer, MAX_PATH ))
+ ds_default_playback = atoi(buffer);
+
+ if (!get_config_key( hkey, appkey, "MaxShadowSize", buffer, MAX_PATH ))
+ ds_snd_shadow_maxsize = atoi(buffer);
+
+ if (!get_config_key( hkey, appkey, "DefaultCapture", buffer, MAX_PATH ))
+ ds_default_capture = atoi(buffer);
+
+ if (!get_config_key( hkey, appkey, "DefaultSampleRate", buffer, MAX_PATH ))
+ ds_default_sample_rate = atoi(buffer);
+
+ if (!get_config_key( hkey, appkey, "DefaultBitsPerSample", buffer, MAX_PATH ))
+ ds_default_bits_per_sample = atoi(buffer);
if (appkey) RegCloseKey( appkey );
if (hkey) RegCloseKey( hkey );
+ TRACE("ds_emuldriver = %d\n", ds_emuldriver);
TRACE("ds_hel_buflen = %d\n", ds_hel_buflen);
TRACE("ds_snd_queue_max = %d\n", ds_snd_queue_max);
+ TRACE("ds_snd_queue_min = %d\n", ds_snd_queue_min);
+ TRACE("ds_hw_accel = %s\n",
+ ds_hw_accel==DS_HW_ACCEL_FULL ? "Full" :
+ ds_hw_accel==DS_HW_ACCEL_STANDARD ? "Standard" :
+ ds_hw_accel==DS_HW_ACCEL_BASIC ? "Basic" :
+ ds_hw_accel==DS_HW_ACCEL_EMULATION ? "Emulation" :
+ "Unknown");
+ TRACE("ds_default_playback = %d\n", ds_default_playback);
+ TRACE("ds_default_capture = %d\n", ds_default_playback);
+ TRACE("ds_default_sample_rate = %d\n", ds_default_sample_rate);
+ TRACE("ds_default_bits_per_sample = %d\n", ds_default_bits_per_sample);
+ TRACE("ds_snd_shadow_maxsize = %d\n", ds_snd_shadow_maxsize);
}
static const char * get_device_id(LPCGUID pGuid)
return debugstr_guid(pGuid);
}
-static HRESULT get_mmdevenum(IMMDeviceEnumerator **devenum)
-{
- HRESULT hr, init_hr;
-
- init_hr = CoInitialize(NULL);
-
- hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL,
- CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)devenum);
- if(FAILED(hr)){
- if(SUCCEEDED(init_hr))
- CoUninitialize();
- *devenum = NULL;
- ERR("CoCreateInstance failed: %08x\n", hr);
- return hr;
- }
-
- return init_hr;
-}
-
-static void release_mmdevenum(IMMDeviceEnumerator *devenum, HRESULT init_hr)
-{
- IMMDeviceEnumerator_Release(devenum);
- if(SUCCEEDED(init_hr))
- CoUninitialize();
-}
-
-static HRESULT get_mmdevice_guid(IMMDevice *device, IPropertyStore *ps,
- GUID *guid)
-{
- PROPVARIANT pv;
- HRESULT hr;
-
- if(!ps){
- hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &ps);
- if(FAILED(hr)){
- WARN("OpenPropertyStore failed: %08x\n", hr);
- return hr;
- }
- }else
- IPropertyStore_AddRef(ps);
-
- PropVariantInit(&pv);
-
- hr = IPropertyStore_GetValue(ps, &PKEY_AudioEndpoint_GUID, &pv);
- if(FAILED(hr)){
- IPropertyStore_Release(ps);
- WARN("GetValue(GUID) failed: %08x\n", hr);
- return hr;
- }
-
- CLSIDFromString(pv.u.pwszVal, guid);
-
- PropVariantClear(&pv);
- IPropertyStore_Release(ps);
-
- return S_OK;
-}
-
/***************************************************************************
* GetDeviceID [DSOUND.9]
*
*/
HRESULT WINAPI GetDeviceID(LPCGUID pGuidSrc, LPGUID pGuidDest)
{
- IMMDeviceEnumerator *devenum;
- EDataFlow flow = (EDataFlow)-1;
- ERole role = (ERole)-1;
- HRESULT hr, init_hr;
-
TRACE("(%s,%p)\n", get_device_id(pGuidSrc),pGuidDest);
- if(!pGuidSrc || !pGuidDest)
- return DSERR_INVALIDPARAM;
-
- init_hr = get_mmdevenum(&devenum);
- if(!devenum)
- return init_hr;
-
- if(IsEqualGUID(&DSDEVID_DefaultPlayback, pGuidSrc)){
- role = eMultimedia;
- flow = eRender;
- }else if(IsEqualGUID(&DSDEVID_DefaultVoicePlayback, pGuidSrc)){
- role = eCommunications;
- flow = eRender;
- }else if(IsEqualGUID(&DSDEVID_DefaultCapture, pGuidSrc)){
- role = eMultimedia;
- flow = eCapture;
- }else if(IsEqualGUID(&DSDEVID_DefaultVoiceCapture, pGuidSrc)){
- role = eCommunications;
- flow = eCapture;
+ if ( pGuidSrc == NULL) {
+ WARN("invalid parameter: pGuidSrc == NULL\n");
+ return DSERR_INVALIDPARAM;
}
- if(role != (ERole)-1 && flow != (EDataFlow)-1){
- IMMDevice *device;
-
- hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(devenum,
- flow, role, &device);
- if(FAILED(hr)){
- WARN("GetDefaultAudioEndpoint failed: %08x\n", hr);
- release_mmdevenum(devenum, init_hr);
- return DSERR_NODRIVER;
- }
-
- hr = get_mmdevice_guid(device, NULL, pGuidDest);
- IMMDevice_Release(device);
-
- release_mmdevenum(devenum, init_hr);
+ if ( pGuidDest == NULL ) {
+ WARN("invalid parameter: pGuidDest == NULL\n");
+ return DSERR_INVALIDPARAM;
+ }
- return (hr == S_OK) ? DS_OK : hr;
+ if ( IsEqualGUID( &DSDEVID_DefaultPlayback, pGuidSrc ) ||
+ IsEqualGUID( &DSDEVID_DefaultVoicePlayback, pGuidSrc ) ) {
+ *pGuidDest = DSOUND_renderer_guids[ds_default_playback];
+ TRACE("returns %s\n", get_device_id(pGuidDest));
+ return DS_OK;
}
- release_mmdevenum(devenum, init_hr);
+ if ( IsEqualGUID( &DSDEVID_DefaultCapture, pGuidSrc ) ||
+ IsEqualGUID( &DSDEVID_DefaultVoiceCapture, pGuidSrc ) ) {
+ *pGuidDest = DSOUND_capture_guids[ds_default_capture];
+ TRACE("returns %s\n", get_device_id(pGuidDest));
+ return DS_OK;
+ }
*pGuidDest = *pGuidSrc;
+ TRACE("returns %s\n", get_device_id(pGuidDest));
return DS_OK;
}
return DirectSoundEnumerateW(a_to_w_callback, &context);
}
-HRESULT get_mmdevice(EDataFlow flow, const GUID *tgt, IMMDevice **device)
-{
- IMMDeviceEnumerator *devenum;
- IMMDeviceCollection *coll;
- UINT count, i;
- HRESULT hr, init_hr;
-
- init_hr = get_mmdevenum(&devenum);
- if(!devenum)
- return init_hr;
-
- hr = IMMDeviceEnumerator_EnumAudioEndpoints(devenum, flow,
- DEVICE_STATE_ACTIVE, &coll);
- if(FAILED(hr)){
- WARN("EnumAudioEndpoints failed: %08x\n", hr);
- release_mmdevenum(devenum, init_hr);
- return hr;
- }
-
- hr = IMMDeviceCollection_GetCount(coll, &count);
- if(FAILED(hr)){
- IMMDeviceCollection_Release(coll);
- release_mmdevenum(devenum, init_hr);
- WARN("GetCount failed: %08x\n", hr);
- return hr;
- }
-
- for(i = 0; i < count; ++i){
- GUID guid;
-
- hr = IMMDeviceCollection_Item(coll, i, device);
- if(FAILED(hr))
- continue;
-
- hr = get_mmdevice_guid(*device, NULL, &guid);
- if(FAILED(hr)){
- IMMDevice_Release(*device);
- continue;
- }
-
- if(IsEqualGUID(&guid, tgt)){
- IMMDeviceCollection_Release(coll);
- release_mmdevenum(devenum, init_hr);
- return DS_OK;
- }
-
- IMMDevice_Release(*device);
- }
-
- WARN("No device with GUID %s found!\n", wine_dbgstr_guid(tgt));
-
- IMMDeviceCollection_Release(coll);
- release_mmdevenum(devenum, init_hr);
-
- return DSERR_INVALIDPARAM;
-}
-
-static BOOL send_device(IMMDevice *device, GUID *guid,
- LPDSENUMCALLBACKW cb, void *user)
-{
- IPropertyStore *ps;
- PROPVARIANT pv;
- BOOL keep_going;
- HRESULT hr;
-
- PropVariantInit(&pv);
-
- hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &ps);
- if(FAILED(hr)){
- WARN("OpenPropertyStore failed: %08x\n", hr);
- return TRUE;
- }
-
- hr = get_mmdevice_guid(device, ps, guid);
- if(FAILED(hr)){
- IPropertyStore_Release(ps);
- return TRUE;
- }
-
- hr = IPropertyStore_GetValue(ps,
- (const PROPERTYKEY *)&DEVPKEY_Device_FriendlyName, &pv);
- if(FAILED(hr)){
- IPropertyStore_Release(ps);
- WARN("GetValue(FriendlyName) failed: %08x\n", hr);
- return TRUE;
- }
-
- TRACE("Calling back with %s (%s)\n", wine_dbgstr_guid(guid),
- wine_dbgstr_w(pv.u.pwszVal));
-
- keep_going = cb(guid, pv.u.pwszVal, wine_vxd_drv, user);
-
- PropVariantClear(&pv);
- IPropertyStore_Release(ps);
-
- return keep_going;
-}
-
-/* S_FALSE means the callback returned FALSE at some point
- * S_OK means the callback always returned TRUE */
-HRESULT enumerate_mmdevices(EDataFlow flow, GUID *guids,
- LPDSENUMCALLBACKW cb, void *user)
-{
- IMMDeviceEnumerator *devenum;
- IMMDeviceCollection *coll;
- IMMDevice *defdev = NULL;
- UINT count, i, n;
- BOOL keep_going;
- HRESULT hr, init_hr;
-
- static const WCHAR primary_desc[] = {'P','r','i','m','a','r','y',' ',
- 'S','o','u','n','d',' ','D','r','i','v','e','r',0};
- static const WCHAR empty_drv[] = {0};
-
- init_hr = get_mmdevenum(&devenum);
- if(!devenum)
- return init_hr;
-
- hr = IMMDeviceEnumerator_EnumAudioEndpoints(devenum, flow,
- DEVICE_STATE_ACTIVE, &coll);
- if(FAILED(hr)){
- release_mmdevenum(devenum, init_hr);
- WARN("EnumAudioEndpoints failed: %08x\n", hr);
- return DS_OK;
- }
-
- hr = IMMDeviceCollection_GetCount(coll, &count);
- if(FAILED(hr)){
- IMMDeviceCollection_Release(coll);
- release_mmdevenum(devenum, init_hr);
- WARN("GetCount failed: %08x\n", hr);
- return DS_OK;
- }
-
- if(count == 0){
- release_mmdevenum(devenum, init_hr);
- return DS_OK;
- }
-
- TRACE("Calling back with NULL (%s)\n", wine_dbgstr_w(primary_desc));
- keep_going = cb(NULL, primary_desc, empty_drv, user);
-
- /* always send the default device first */
- if(keep_going){
- hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(devenum, flow,
- eMultimedia, &defdev);
- if(FAILED(hr)){
- defdev = NULL;
- n = 0;
- }else{
- keep_going = send_device(defdev, &guids[0], cb, user);
- n = 1;
- }
- }
-
- for(i = 0; keep_going && i < count; ++i){
- IMMDevice *device;
-
- hr = IMMDeviceCollection_Item(coll, i, &device);
- if(FAILED(hr)){
- WARN("Item failed: %08x\n", hr);
- continue;
- }
-
- if(device != defdev){
- send_device(device, &guids[n], cb, user);
- ++n;
- }
-
- IMMDevice_Release(device);
- }
-
- if(defdev)
- IMMDevice_Release(defdev);
- IMMDeviceCollection_Release(coll);
-
- release_mmdevenum(devenum, init_hr);
-
- return (keep_going == TRUE) ? S_OK : S_FALSE;
-}
-
/***************************************************************************
* DirectSoundEnumerateW [DSOUND.3]
*
LPDSENUMCALLBACKW lpDSEnumCallback,
LPVOID lpContext )
{
- HRESULT hr;
+ unsigned devs, wod;
+ DSDRIVERDESC desc;
+ GUID guid;
+ int err;
+ WCHAR wDesc[MAXPNAMELEN];
+ WCHAR wName[MAXPNAMELEN];
- TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext);
+ TRACE("lpDSEnumCallback = %p, lpContext = %p\n",
+ lpDSEnumCallback, lpContext);
if (lpDSEnumCallback == NULL) {
- WARN("invalid parameter: lpDSEnumCallback == NULL\n");
- return DSERR_INVALIDPARAM;
+ WARN("invalid parameter: lpDSEnumCallback == NULL\n");
+ return DSERR_INVALIDPARAM;
}
setup_dsound_options();
- hr = enumerate_mmdevices(eRender, DSOUND_renderer_guids,
- lpDSEnumCallback, lpContext);
- return SUCCEEDED(hr) ? DS_OK : hr;
+ devs = waveOutGetNumDevs();
+ if (devs > 0) {
+ if (GetDeviceID(&DSDEVID_DefaultPlayback, &guid) == DS_OK) {
+ static const WCHAR empty[] = { 0 };
+ for (wod = 0; wod < devs; ++wod) {
+ if (IsEqualGUID( &guid, &DSOUND_renderer_guids[wod] ) ) {
+ err = mmErr(waveOutMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,ds_hw_accel));
+ if (err == DS_OK) {
+ TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
+ "Primary Sound Driver",desc.szDrvname,lpContext);
+ MultiByteToWideChar( CP_ACP, 0, "Primary Sound Driver", -1,
+ wDesc, sizeof(wDesc)/sizeof(WCHAR) );
+ if (lpDSEnumCallback(NULL, wDesc, empty, lpContext) == FALSE)
+ return DS_OK;
+ }
+ }
+ }
+ }
+ }
+
+ for (wod = 0; wod < devs; ++wod) {
+ err = mmErr(waveOutMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,ds_hw_accel));
+ if (err == DS_OK) {
+ TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
+ debugstr_guid(&DSOUND_renderer_guids[wod]),desc.szDesc,desc.szDrvname,lpContext);
+ MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1,
+ wDesc, sizeof(wDesc)/sizeof(WCHAR) );
+ wDesc[(sizeof(wDesc)/sizeof(WCHAR)) - 1] = '\0';
+
+ MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1,
+ wName, sizeof(wName)/sizeof(WCHAR) );
+ wName[(sizeof(wName)/sizeof(WCHAR)) - 1] = '\0';
+
+ if (lpDSEnumCallback(&DSOUND_renderer_guids[wod], wDesc, wName, lpContext) == FALSE)
+ return DS_OK;
+ }
+ }
+ return DS_OK;
}
/***************************************************************************
LPDSENUMCALLBACKW lpDSEnumCallback,
LPVOID lpContext)
{
- HRESULT hr;
+ unsigned devs, wid;
+ DSDRIVERDESC desc;
+ GUID guid;
+ int err;
+ WCHAR wDesc[MAXPNAMELEN];
+ WCHAR wName[MAXPNAMELEN];
TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext );
if (lpDSEnumCallback == NULL) {
- WARN("invalid parameter: lpDSEnumCallback == NULL\n");
+ WARN("invalid parameter: lpDSEnumCallback == NULL\n");
return DSERR_INVALIDPARAM;
}
setup_dsound_options();
- hr = enumerate_mmdevices(eCapture, DSOUND_capture_guids,
- lpDSEnumCallback, lpContext);
- return SUCCEEDED(hr) ? DS_OK : hr;
+ devs = waveInGetNumDevs();
+ if (devs > 0) {
+ if (GetDeviceID(&DSDEVID_DefaultCapture, &guid) == DS_OK) {
+ for (wid = 0; wid < devs; ++wid) {
+ if (IsEqualGUID( &guid, &DSOUND_capture_guids[wid] ) ) {
+ err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,ds_hw_accel));
+ if (err == DS_OK) {
+ TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
+ "Primary Sound Capture Driver",desc.szDrvname,lpContext);
+ MultiByteToWideChar( CP_ACP, 0, "Primary Sound Capture Driver", -1,
+ wDesc, sizeof(wDesc)/sizeof(WCHAR) );
+ MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1,
+ wName, sizeof(wName)/sizeof(WCHAR) );
+ wName[(sizeof(wName)/sizeof(WCHAR)) - 1] = '\0';
+
+ if (lpDSEnumCallback(NULL, wDesc, wName, lpContext) == FALSE)
+ return DS_OK;
+ }
+ }
+ }
+ }
+ }
+
+ for (wid = 0; wid < devs; ++wid) {
+ err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,ds_hw_accel));
+ if (err == DS_OK) {
+ TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
+ debugstr_guid(&DSOUND_capture_guids[wid]),desc.szDesc,desc.szDrvname,lpContext);
+ MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1,
+ wDesc, sizeof(wDesc)/sizeof(WCHAR) );
+ wDesc[(sizeof(wDesc)/sizeof(WCHAR)) - 1] = '\0';
+
+ MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1,
+ wName, sizeof(wName)/sizeof(WCHAR) );
+ wName[(sizeof(wName)/sizeof(WCHAR)) - 1] = '\0';
+
+ if (lpDSEnumCallback(&DSOUND_capture_guids[wid], wDesc, wName, lpContext) == FALSE)
+ return DS_OK;
+ }
+ }
+
+ return DS_OK;
}
/*******************************************************************************
}
static HRESULT WINAPI
-DSCF_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppobj)
+DSCF_QueryInterface(LPCLASSFACTORY iface, REFIID riid, LPVOID *ppobj)
{
IClassFactoryImpl *This = impl_from_IClassFactory(iface);
TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppobj);
IsEqualIID(riid, &IID_IClassFactory))
{
*ppobj = iface;
- IClassFactory_AddRef(iface);
+ IUnknown_AddRef(iface);
return S_OK;
}
*ppobj = NULL;
};
static IClassFactoryImpl DSOUND_CF[] = {
- { { &DSCF_Vtbl }, &CLSID_DirectSound, DSOUND_Create },
- { { &DSCF_Vtbl }, &CLSID_DirectSound8, DSOUND_Create8 },
- { { &DSCF_Vtbl }, &CLSID_DirectSoundCapture, DSOUND_CaptureCreate },
- { { &DSCF_Vtbl }, &CLSID_DirectSoundCapture8, DSOUND_CaptureCreate8 },
- { { &DSCF_Vtbl }, &CLSID_DirectSoundFullDuplex, DSOUND_FullDuplexCreate },
- { { &DSCF_Vtbl }, &CLSID_DirectSoundPrivate, IKsPrivatePropertySetImpl_Create },
+ { { &DSCF_Vtbl }, &CLSID_DirectSound, (FnCreateInstance)DSOUND_Create },
+ { { &DSCF_Vtbl }, &CLSID_DirectSound8, (FnCreateInstance)DSOUND_Create8 },
+ { { &DSCF_Vtbl }, &CLSID_DirectSoundCapture, (FnCreateInstance)DSOUND_CaptureCreate },
+ { { &DSCF_Vtbl }, &CLSID_DirectSoundCapture8, (FnCreateInstance)DSOUND_CaptureCreate8 },
+ { { &DSCF_Vtbl }, &CLSID_DirectSoundFullDuplex, (FnCreateInstance)DSOUND_FullDuplexCreate },
+ { { &DSCF_Vtbl }, &CLSID_DirectSoundPrivate, (FnCreateInstance)IKsPrivatePropertySetImpl_Create },
{ { NULL }, NULL, NULL }
};
*/
BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
+ int i;
TRACE("(%p %d %p)\n", hInstDLL, fdwReason, lpvReserved);
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
TRACE("DLL_PROCESS_ATTACH\n");
+ for (i = 0; i < MAXWAVEDRIVERS; i++) {
+ DSOUND_renderer[i] = NULL;
+ DSOUND_capture[i] = NULL;
+ INIT_GUID(DSOUND_renderer_guids[i], 0xbd6dd71a, 0x3deb, 0x11d1, 0xb1, 0x71, 0x00, 0xc0, 0x4f, 0xc2, 0x00, 0x00 + i);
+ INIT_GUID(DSOUND_capture_guids[i], 0xbd6dd71b, 0x3deb, 0x11d1, 0xb1, 0x71, 0x00, 0xc0, 0x4f, 0xc2, 0x00, 0x00 + i);
+ }
instance = hInstDLL;
DisableThreadLibraryCalls(hInstDLL);
/* Increase refcount on dsound by 1 */
break;
case DLL_PROCESS_DETACH:
TRACE("DLL_PROCESS_DETACH\n");
- DeleteCriticalSection(&DSOUND_renderers_lock);
- DeleteCriticalSection(&DSOUND_capturers_lock);
break;
default:
TRACE("UNKNOWN REASON\n");
#include <wingdi.h>
#include <winternl.h>
#include <objbase.h>
-#include <mmdeviceapi.h>
#include <audioclient.h>
-#include <mmsystem.h>
+#include <mmddk.h>
#include <dsound.h>
#include <dsconf.h>
+#include <dsdriver.h>
#include <vfwmsgs.h>
-#include <devpkey.h>
#include <wine/debug.h>
#include <wine/list.h>
#define DS_TIME_RES 2 /* Resolution of multimedia timer */
#define DS_TIME_DEL 10 /* Delay of multimedia timer callback, and duration of HEL fragment */
+/* direct sound hardware acceleration levels */
+#define DS_HW_ACCEL_FULL 0 /* default on Windows 98 */
+#define DS_HW_ACCEL_STANDARD 1 /* default on Windows 2000 */
+#define DS_HW_ACCEL_BASIC 2
+#define DS_HW_ACCEL_EMULATION 3
+
+extern int ds_emuldriver DECLSPEC_HIDDEN;
extern int ds_hel_buflen DECLSPEC_HIDDEN;
extern int ds_snd_queue_max DECLSPEC_HIDDEN;
+extern int ds_snd_queue_min DECLSPEC_HIDDEN;
+extern int ds_snd_shadow_maxsize DECLSPEC_HIDDEN;
+extern int ds_hw_accel DECLSPEC_HIDDEN;
+extern int ds_default_sample_rate DECLSPEC_HIDDEN;
+extern int ds_default_bits_per_sample DECLSPEC_HIDDEN;
/*****************************************************************************
* Predeclare the interface implementation structures
*/
+typedef struct IDirectSoundImpl IDirectSoundImpl;
+typedef struct IDirectSound_IUnknown IDirectSound_IUnknown;
+typedef struct IDirectSound_IDirectSound IDirectSound_IDirectSound;
+typedef struct IDirectSound8_IUnknown IDirectSound8_IUnknown;
+typedef struct IDirectSound8_IDirectSound IDirectSound8_IDirectSound;
+typedef struct IDirectSound8_IDirectSound8 IDirectSound8_IDirectSound8;
typedef struct IDirectSoundBufferImpl IDirectSoundBufferImpl;
+typedef struct IDirectSoundCaptureImpl IDirectSoundCaptureImpl;
+typedef struct IDirectSoundCaptureBufferImpl IDirectSoundCaptureBufferImpl;
+typedef struct IDirectSoundNotifyImpl IDirectSoundNotifyImpl;
+typedef struct IDirectSoundCaptureNotifyImpl IDirectSoundCaptureNotifyImpl;
+typedef struct IDirectSound3DListenerImpl IDirectSound3DListenerImpl;
+typedef struct IDirectSound3DBufferImpl IDirectSound3DBufferImpl;
+typedef struct IKsBufferPropertySetImpl IKsBufferPropertySetImpl;
typedef struct DirectSoundDevice DirectSoundDevice;
+typedef struct DirectSoundCaptureDevice DirectSoundCaptureDevice;
/* dsound_convert.h */
-typedef float (*bitsgetfunc)(const IDirectSoundBufferImpl *, DWORD, DWORD);
-typedef void (*bitsputfunc)(const IDirectSoundBufferImpl *, DWORD, DWORD, float);
-extern const bitsgetfunc getbpp[5] DECLSPEC_HIDDEN;
-void putieee32(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value) DECLSPEC_HIDDEN;
-void mixieee32(float *src, float *dst, unsigned samples) DECLSPEC_HIDDEN;
+typedef void (*bitsconvertfunc)(const void *, void *, UINT, UINT, INT, UINT, UINT);
+extern const bitsconvertfunc convertbpp[5][4] DECLSPEC_HIDDEN;
+typedef void (*mixfunc)(const void *, void *, unsigned);
+extern const mixfunc mixfunctions[4] DECLSPEC_HIDDEN;
typedef void (*normfunc)(const void *, void *, unsigned);
-extern const normfunc normfunctions[5] DECLSPEC_HIDDEN;
-
-typedef struct _DSVOLUMEPAN
-{
- DWORD dwTotalLeftAmpFactor;
- DWORD dwTotalRightAmpFactor;
- LONG lVolume;
- DWORD dwVolAmpFactor;
- LONG lPan;
- DWORD dwPanLeftAmpFactor;
- DWORD dwPanRightAmpFactor;
-} DSVOLUMEPAN,*PDSVOLUMEPAN;
+extern const normfunc normfunctions[4] DECLSPEC_HIDDEN;
/*****************************************************************************
* IDirectSoundDevice implementation structure
LONG ref;
GUID guid;
- DSCAPS drvcaps;
- DWORD priolevel, sleeptime;
- PWAVEFORMATEX pwfx, primary_pwfx;
- UINT playing_offs_bytes, in_mmdev_bytes, prebuf;
+ PIDSDRIVER driver;
+ DSDRIVERDESC drvdesc;
+ DSDRIVERCAPS drvcaps;
+ DWORD priolevel;
+ PWAVEFORMATEX pwfx;
+ HWAVEOUT hwo;
+ LPWAVEHDR pwave;
+ UINT timerID, pwplay, pwqueue, prebuf, helfrags;
DWORD fraglen;
+ PIDSDRIVERBUFFER hwbuf;
LPBYTE buffer;
DWORD writelead, buflen, state, playpos, mixpos;
int nrofbuffers;
CRITICAL_SECTION mixlock;
IDirectSoundBufferImpl *primary;
DWORD speaker_config;
- float *mix_buffer, *tmp_buffer;
+ LPBYTE tmp_buffer, mix_buffer;
DWORD tmp_buffer_len, mix_buffer_len;
DSVOLUMEPAN volpan;
+ mixfunc mixfunction;
normfunc normfunction;
/* DirectSound3DListener fields */
+ IDirectSound3DListenerImpl* listener;
DS3DLISTENER ds3dl;
BOOL ds3dl_need_recalc;
-
- IMMDevice *mmdevice;
- IAudioClient *client;
- IAudioClock *clock;
- IAudioStreamVolume *volume;
- IAudioRenderClient *render;
-
- HANDLE sleepev, thread;
- struct list entry;
};
/* reference counted buffer memory for duplicated buffer memory */
HRESULT DirectSoundDevice_AddBuffer(
DirectSoundDevice * device,
IDirectSoundBufferImpl * pDSB) DECLSPEC_HIDDEN;
-void DirectSoundDevice_RemoveBuffer(DirectSoundDevice * device, IDirectSoundBufferImpl * pDSB) DECLSPEC_HIDDEN;
+HRESULT DirectSoundDevice_RemoveBuffer(
+ DirectSoundDevice * device,
+ IDirectSoundBufferImpl * pDSB) DECLSPEC_HIDDEN;
+HRESULT DirectSoundDevice_GetCaps(DirectSoundDevice * device, LPDSCAPS lpDSCaps) DECLSPEC_HIDDEN;
HRESULT DirectSoundDevice_CreateSoundBuffer(
DirectSoundDevice * device,
LPCDSBUFFERDESC dsbd,
DirectSoundDevice * device,
LPDIRECTSOUNDBUFFER psb,
LPLPDIRECTSOUNDBUFFER ppdsb) DECLSPEC_HIDDEN;
+HRESULT DirectSoundDevice_SetCooperativeLevel(
+ DirectSoundDevice * devcie,
+ HWND hwnd,
+ DWORD level) DECLSPEC_HIDDEN;
+HRESULT DirectSoundDevice_Compact(DirectSoundDevice * device) DECLSPEC_HIDDEN;
+HRESULT DirectSoundDevice_GetSpeakerConfig(
+ DirectSoundDevice * device,
+ LPDWORD lpdwSpeakerConfig) DECLSPEC_HIDDEN;
+HRESULT DirectSoundDevice_SetSpeakerConfig(
+ DirectSoundDevice * device,
+ DWORD config) DECLSPEC_HIDDEN;
+HRESULT DirectSoundDevice_VerifyCertification(DirectSoundDevice * device,
+ LPDWORD pdwCertified) DECLSPEC_HIDDEN;
/*****************************************************************************
* IDirectSoundBuffer implementation structure
struct IDirectSoundBufferImpl
{
IDirectSoundBuffer8 IDirectSoundBuffer8_iface;
- IDirectSoundNotify IDirectSoundNotify_iface;
- IDirectSound3DListener IDirectSound3DListener_iface; /* only primary buffer */
- IDirectSound3DBuffer IDirectSound3DBuffer_iface; /* only secondary buffer */
- IKsPropertySet IKsPropertySet_iface;
LONG numIfaces; /* "in use interfaces" refcount */
- LONG ref, refn, ref3D, refiks;
+ LONG ref;
/* IDirectSoundBufferImpl fields */
DirectSoundDevice* device;
RTL_RWLOCK lock;
+ PIDSDRIVERBUFFER hwbuf;
PWAVEFORMATEX pwfx;
BufferMemory* buffer;
+ LPBYTE tmp_buffer;
DWORD playflags,state,leadin;
DWORD writelead,buflen;
DWORD nAvgBytesPerSec;
- DWORD freq;
+ DWORD freq, tmp_buffer_len, max_buffer_len;
DSVOLUMEPAN volpan;
DSBUFFERDESC dsbd;
/* used for frequency conversion (PerfectPitch) */
- ULONG freqneeded;
- DWORD firstep;
- float freqAcc, freqAdjust, firgain;
+ ULONG freqneeded, freqAdjust, freqAcc, freqAccNext, resampleinmixer;
/* used for mixing */
- DWORD sec_mixpos;
+ DWORD primary_mixpos, buf_mixpos, sec_mixpos;
- /* IDirectSoundNotify fields */
+ /* IDirectSoundNotifyImpl fields */
+ IDirectSoundNotifyImpl* notify;
LPDSBPOSITIONNOTIFY notifies;
int nrofnotifies;
+ PIDSDRIVERNOTIFY hwnotify;
+
/* DirectSound3DBuffer fields */
+ IDirectSound3DBufferImpl* ds3db;
DS3DBUFFER ds3db_ds3db;
LONG ds3db_lVolume;
BOOL ds3db_need_recalc;
- /* Used for bit depth conversion */
- int mix_channels;
- bitsgetfunc get, get_aux;
- bitsputfunc put, put_aux;
+ /* IKsPropertySet fields */
+ IKsBufferPropertySetImpl* iks;
+ bitsconvertfunc convert;
struct list entry;
};
-float get_mono(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel) DECLSPEC_HIDDEN;
-void put_mono2stereo(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value) DECLSPEC_HIDDEN;
-
HRESULT IDirectSoundBufferImpl_Create(
DirectSoundDevice *device,
IDirectSoundBufferImpl **ppdsb,
LPCDSBUFFERDESC dsbd) DECLSPEC_HIDDEN;
+HRESULT IDirectSoundBufferImpl_Destroy(
+ IDirectSoundBufferImpl *pdsb) DECLSPEC_HIDDEN;
HRESULT IDirectSoundBufferImpl_Duplicate(
DirectSoundDevice *device,
IDirectSoundBufferImpl **ppdsb,
IDirectSoundBufferImpl *pdsb) DECLSPEC_HIDDEN;
void secondarybuffer_destroy(IDirectSoundBufferImpl *This) DECLSPEC_HIDDEN;
-const IDirectSound3DListenerVtbl ds3dlvt DECLSPEC_HIDDEN;
-const IDirectSound3DBufferVtbl ds3dbvt DECLSPEC_HIDDEN;
-const IKsPropertySetVtbl iksbvt DECLSPEC_HIDDEN;
-HRESULT IKsPrivatePropertySetImpl_Create(REFIID riid, void **ppv) DECLSPEC_HIDDEN;
+/*****************************************************************************
+ * DirectSoundCaptureDevice implementation structure
+ */
+struct DirectSoundCaptureDevice
+{
+ /* IDirectSoundCaptureImpl fields */
+ GUID guid;
+ LONG ref;
+
+ /* DirectSound driver stuff */
+ PIDSCDRIVER driver;
+ DSDRIVERDESC drvdesc;
+ DSCDRIVERCAPS drvcaps;
+ PIDSCDRIVERBUFFER hwbuf;
+
+ /* wave driver info */
+ HWAVEIN hwi;
+
+ /* more stuff */
+ LPBYTE buffer;
+ DWORD buflen;
+
+ PWAVEFORMATEX pwfx;
+
+ IDirectSoundCaptureBufferImpl* capture_buffer;
+ DWORD state;
+ LPWAVEHDR pwave;
+ int nrofpwaves;
+ int index;
+ CRITICAL_SECTION lock;
+};
+
+/*****************************************************************************
+ * IDirectSoundCaptureBuffer implementation structure
+ */
+struct IDirectSoundCaptureBufferImpl
+{
+ /* IUnknown fields */
+ const IDirectSoundCaptureBuffer8Vtbl *lpVtbl;
+ LONG ref;
+
+ /* IDirectSoundCaptureBufferImpl fields */
+ DirectSoundCaptureDevice* device;
+ /* FIXME: don't need this */
+ LPDSCBUFFERDESC pdscbd;
+ DWORD flags;
+
+ /* IDirectSoundCaptureNotifyImpl fields */
+ IDirectSoundCaptureNotifyImpl* notify;
+ LPDSBPOSITIONNOTIFY notifies;
+ int nrofnotifies;
+ PIDSDRIVERNOTIFY hwnotify;
+};
+
+/*****************************************************************************
+ * IDirectSound3DListener implementation structure
+ */
+struct IDirectSound3DListenerImpl
+{
+ /* IUnknown fields */
+ const IDirectSound3DListenerVtbl *lpVtbl;
+ LONG ref;
+ /* IDirectSound3DListenerImpl fields */
+ DirectSoundDevice* device;
+};
+
+HRESULT IDirectSound3DListenerImpl_Create(
+ DirectSoundDevice *device,
+ IDirectSound3DListenerImpl **pdsl) DECLSPEC_HIDDEN;
+
+/*****************************************************************************
+ * IKsBufferPropertySet implementation structure
+ */
+struct IKsBufferPropertySetImpl
+{
+ /* IUnknown fields */
+ const IKsPropertySetVtbl *lpVtbl;
+ LONG ref;
+ /* IKsPropertySetImpl fields */
+ IDirectSoundBufferImpl* dsb;
+};
+
+HRESULT IKsBufferPropertySetImpl_Create(
+ IDirectSoundBufferImpl *dsb,
+ IKsBufferPropertySetImpl **piks) DECLSPEC_HIDDEN;
+HRESULT IKsBufferPropertySetImpl_Destroy(
+ IKsBufferPropertySetImpl *piks) DECLSPEC_HIDDEN;
+
+HRESULT IKsPrivatePropertySetImpl_Create(REFIID riid, IKsPropertySet **piks) DECLSPEC_HIDDEN;
+
+/*****************************************************************************
+ * IDirectSound3DBuffer implementation structure
+ */
+struct IDirectSound3DBufferImpl
+{
+ /* IUnknown fields */
+ const IDirectSound3DBufferVtbl *lpVtbl;
+ LONG ref;
+ /* IDirectSound3DBufferImpl fields */
+ IDirectSoundBufferImpl* dsb;
+};
+
+HRESULT IDirectSound3DBufferImpl_Create(
+ IDirectSoundBufferImpl *dsb,
+ IDirectSound3DBufferImpl **pds3db) DECLSPEC_HIDDEN;
+HRESULT IDirectSound3DBufferImpl_Destroy(
+ IDirectSound3DBufferImpl *pds3db) DECLSPEC_HIDDEN;
/*******************************************************************************
*/
/* dsound.c */
-HRESULT DSOUND_Create(REFIID riid, void **ppv) DECLSPEC_HIDDEN;
-HRESULT DSOUND_Create8(REFIID riid, void **ppv) DECLSPEC_HIDDEN;
-HRESULT IDirectSoundImpl_Create(IUnknown *outer_unk, REFIID riid, void **ppv, BOOL has_ds8) DECLSPEC_HIDDEN;
+HRESULT DSOUND_Create(REFIID riid, LPDIRECTSOUND *ppDS) DECLSPEC_HIDDEN;
+HRESULT DSOUND_Create8(REFIID riid, LPDIRECTSOUND8 *ppDS) DECLSPEC_HIDDEN;
/* primary.c */
+DWORD DSOUND_fraglen(DWORD nSamplesPerSec, DWORD nBlockAlign) DECLSPEC_HIDDEN;
HRESULT DSOUND_PrimaryCreate(DirectSoundDevice *device) DECLSPEC_HIDDEN;
HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *device) DECLSPEC_HIDDEN;
HRESULT DSOUND_PrimaryPlay(DirectSoundDevice *device) DECLSPEC_HIDDEN;
HRESULT DSOUND_PrimaryGetPosition(DirectSoundDevice *device, LPDWORD playpos, LPDWORD writepos) DECLSPEC_HIDDEN;
LPWAVEFORMATEX DSOUND_CopyFormat(LPCWAVEFORMATEX wfex) DECLSPEC_HIDDEN;
HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave) DECLSPEC_HIDDEN;
-HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device) DECLSPEC_HIDDEN;
HRESULT primarybuffer_create(DirectSoundDevice *device, IDirectSoundBufferImpl **ppdsb,
const DSBUFFERDESC *dsbd) DECLSPEC_HIDDEN;
void primarybuffer_destroy(IDirectSoundBufferImpl *This) DECLSPEC_HIDDEN;
HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex) DECLSPEC_HIDDEN;
-LONG capped_refcount_dec(LONG *ref) DECLSPEC_HIDDEN;
/* duplex.c */
-
-HRESULT DSOUND_FullDuplexCreate(REFIID riid, void **ppv) DECLSPEC_HIDDEN;
+
+HRESULT DSOUND_FullDuplexCreate(REFIID riid, LPDIRECTSOUNDFULLDUPLEX* ppDSFD) DECLSPEC_HIDDEN;
/* mixer.c */
+DWORD DSOUND_bufpos_to_mixpos(const DirectSoundDevice* device, DWORD pos) DECLSPEC_HIDDEN;
void DSOUND_CheckEvent(const IDirectSoundBufferImpl *dsb, DWORD playpos, int len) DECLSPEC_HIDDEN;
void DSOUND_RecalcVolPan(PDSVOLUMEPAN volpan) DECLSPEC_HIDDEN;
void DSOUND_AmpFactorToVolPan(PDSVOLUMEPAN volpan) DECLSPEC_HIDDEN;
void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb) DECLSPEC_HIDDEN;
-DWORD DSOUND_secpos_to_bufpos(const IDirectSoundBufferImpl *dsb, DWORD secpos, DWORD secmixpos, float *overshot) DECLSPEC_HIDDEN;
+void DSOUND_MixToTemporary(const IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD mixlen, BOOL inmixer) DECLSPEC_HIDDEN;
+DWORD DSOUND_secpos_to_bufpos(const IDirectSoundBufferImpl *dsb, DWORD secpos, DWORD secmixpos, DWORD* overshot) DECLSPEC_HIDDEN;
-DWORD CALLBACK DSOUND_mixthread(void *ptr) DECLSPEC_HIDDEN;
+void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) DECLSPEC_HIDDEN;
+void CALLBACK DSOUND_callback(HWAVEOUT hwo, UINT msg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) DECLSPEC_HIDDEN;
/* sound3d.c */
/* capture.c */
-HRESULT DSOUND_CaptureCreate(REFIID riid, void **ppv) DECLSPEC_HIDDEN;
-HRESULT DSOUND_CaptureCreate8(REFIID riid, void **ppv) DECLSPEC_HIDDEN;
-HRESULT IDirectSoundCaptureImpl_Create(IUnknown *outer_unk, REFIID riid, void **ppv, BOOL has_dsc8) DECLSPEC_HIDDEN;
+HRESULT DSOUND_CaptureCreate(REFIID riid, LPDIRECTSOUNDCAPTURE *ppDSC) DECLSPEC_HIDDEN;
+HRESULT DSOUND_CaptureCreate8(REFIID riid, LPDIRECTSOUNDCAPTURE8 *ppDSC8) DECLSPEC_HIDDEN;
#define STATE_STOPPED 0
#define STATE_STARTING 1
#define STATE_CAPTURING 2
#define STATE_STOPPING 3
-extern CRITICAL_SECTION DSOUND_renderers_lock DECLSPEC_HIDDEN;
-extern CRITICAL_SECTION DSOUND_capturers_lock DECLSPEC_HIDDEN;
-extern struct list DSOUND_capturers DECLSPEC_HIDDEN;
-extern struct list DSOUND_renderers DECLSPEC_HIDDEN;
+#define DSOUND_FREQSHIFT (20)
+extern DirectSoundDevice* DSOUND_renderer[MAXWAVEDRIVERS] DECLSPEC_HIDDEN;
extern GUID DSOUND_renderer_guids[MAXWAVEDRIVERS] DECLSPEC_HIDDEN;
-extern GUID DSOUND_capture_guids[MAXWAVEDRIVERS] DECLSPEC_HIDDEN;
-extern WCHAR wine_vxd_drv[] DECLSPEC_HIDDEN;
+extern DirectSoundCaptureDevice * DSOUND_capture[MAXWAVEDRIVERS] DECLSPEC_HIDDEN;
+extern GUID DSOUND_capture_guids[MAXWAVEDRIVERS] DECLSPEC_HIDDEN;
+HRESULT mmErr(UINT err) DECLSPEC_HIDDEN;
void setup_dsound_options(void) DECLSPEC_HIDDEN;
-
-HRESULT get_mmdevice(EDataFlow flow, const GUID *tgt, IMMDevice **device) DECLSPEC_HIDDEN;
-
-BOOL DSOUND_check_supported(IAudioClient *client, DWORD rate,
- DWORD depth, WORD channels) DECLSPEC_HIDDEN;
-UINT DSOUND_create_timer(LPTIMECALLBACK cb, DWORD_PTR user) DECLSPEC_HIDDEN;
-HRESULT enumerate_mmdevices(EDataFlow flow, GUID *guids,
- LPDSENUMCALLBACKW cb, void *user) DECLSPEC_HIDDEN;
+const char * dumpCooperativeLevel(DWORD level) DECLSPEC_HIDDEN;
#endif /* _DSOUND_PRIVATE_H_ */
*/
typedef struct IDirectSoundFullDuplexImpl
{
- IUnknown IUnknown_iface;
- IDirectSoundFullDuplex IDirectSoundFullDuplex_iface;
- LONG ref, refdsfd, numIfaces;
- IUnknown *ds8_unk; /* Aggregated IDirectSound8 */
- IUnknown *dsc8_unk; /* Aggregated IDirectSoundCapture8 */
+ /* IUnknown fields */
+ const IDirectSoundFullDuplexVtbl *lpVtbl;
+ LONG ref;
+
+ /* IDirectSoundFullDuplexImpl fields */
+ IDirectSound8 *renderer_device;
+ IDirectSoundCapture *capture_device;
+
+ LPUNKNOWN pUnknown;
+ LPDIRECTSOUND8 pDS8;
+ LPDIRECTSOUNDCAPTURE pDSC;
} IDirectSoundFullDuplexImpl;
-static void fullduplex_destroy(IDirectSoundFullDuplexImpl *This)
+typedef struct IDirectSoundFullDuplex_IUnknown {
+ const IUnknownVtbl *lpVtbl;
+ LONG ref;
+ IDirectSoundFullDuplexImpl *pdsfd;
+} IDirectSoundFullDuplex_IUnknown;
+
+typedef struct IDirectSoundFullDuplex_IDirectSound8 {
+ const IDirectSound8Vtbl *lpVtbl;
+ LONG ref;
+ IDirectSoundFullDuplexImpl *pdsfd;
+} IDirectSoundFullDuplex_IDirectSound8;
+
+typedef struct IDirectSoundFullDuplex_IDirectSoundCapture {
+ const IDirectSoundCaptureVtbl *lpVtbl;
+ LONG ref;
+ IDirectSoundFullDuplexImpl *pdsfd;
+} IDirectSoundFullDuplex_IDirectSoundCapture;
+
+/*******************************************************************************
+ * IUnknown
+ */
+static HRESULT WINAPI IDirectSoundFullDuplex_IUnknown_QueryInterface(
+ LPUNKNOWN iface,
+ REFIID riid,
+ LPVOID * ppobj)
+{
+ IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface;
+ TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+ return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
+}
+
+static ULONG WINAPI IDirectSoundFullDuplex_IUnknown_AddRef(
+ LPUNKNOWN iface)
+{
+ IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface;
+ ULONG ref = InterlockedIncrement(&(This->ref));
+ TRACE("(%p) ref was %d\n", This, ref - 1);
+ return ref;
+}
+
+static ULONG WINAPI IDirectSoundFullDuplex_IUnknown_Release(
+ LPUNKNOWN iface)
+{
+ IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface;
+ ULONG ref = InterlockedDecrement(&(This->ref));
+ TRACE("(%p) ref was %d\n", This, ref + 1);
+ if (!ref) {
+ This->pdsfd->pUnknown = NULL;
+ HeapFree(GetProcessHeap(), 0, This);
+ TRACE("(%p) released\n", This);
+ }
+ return ref;
+}
+
+static const IUnknownVtbl DirectSoundFullDuplex_Unknown_Vtbl =
+{
+ IDirectSoundFullDuplex_IUnknown_QueryInterface,
+ IDirectSoundFullDuplex_IUnknown_AddRef,
+ IDirectSoundFullDuplex_IUnknown_Release
+};
+
+static HRESULT IDirectSoundFullDuplex_IUnknown_Create(
+ LPDIRECTSOUNDFULLDUPLEX pdsfd,
+ LPUNKNOWN * ppunk)
{
- IDirectSound8 *ds8;
- IDirectSoundCapture8 *dsc8;
+ IDirectSoundFullDuplex_IUnknown * pdsfdunk;
+ TRACE("(%p,%p)\n",pdsfd,ppunk);
- if (This->ds8_unk) {
- IUnknown_QueryInterface(This->ds8_unk, &IID_IDirectSound8, (void**)&ds8);
- while(IDirectSound8_Release(ds8) > 0);
- IUnknown_Release(This->ds8_unk);
+ if (pdsfd == NULL) {
+ ERR("invalid parameter: pdsfd == NULL\n");
+ return DSERR_INVALIDPARAM;
}
- if (This->dsc8_unk) {
- IUnknown_QueryInterface(This->dsc8_unk, &IID_IDirectSoundCapture8, (void**)&dsc8);
- while(IDirectSoundCapture_Release(dsc8) > 0);
- IUnknown_Release(This->dsc8_unk);
+
+ if (ppunk == NULL) {
+ ERR("invalid parameter: ppunk == NULL\n");
+ return DSERR_INVALIDPARAM;
}
- HeapFree(GetProcessHeap(), 0, This);
- TRACE("(%p) released\n", This);
+
+ pdsfdunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdunk));
+ if (pdsfdunk == NULL) {
+ WARN("out of memory\n");
+ *ppunk = NULL;
+ return DSERR_OUTOFMEMORY;
+ }
+
+ pdsfdunk->lpVtbl = &DirectSoundFullDuplex_Unknown_Vtbl;
+ pdsfdunk->ref = 0;
+ pdsfdunk->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
+
+ *ppunk = (LPUNKNOWN)pdsfdunk;
+
+ return DS_OK;
}
/*******************************************************************************
- * IUnknown implemetation for DirectSoundFullDuplex
+ * IDirectSoundFullDuplex_IDirectSound8
*/
-static inline IDirectSoundFullDuplexImpl *impl_from_IUnknown(IUnknown *iface)
+static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_QueryInterface(
+ LPDIRECTSOUND8 iface,
+ REFIID riid,
+ LPVOID * ppobj)
{
- return CONTAINING_RECORD(iface, IDirectSoundFullDuplexImpl, IUnknown_iface);
+ IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
+ TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+ return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
}
-static HRESULT WINAPI IUnknownImpl_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
+static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound8_AddRef(
+ LPDIRECTSOUND8 iface)
{
- IDirectSoundFullDuplexImpl *This = impl_from_IUnknown(iface);
-
- TRACE("(%p,%s,%p)\n", This, debugstr_guid(riid), ppv);
+ IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
+ ULONG ref = InterlockedIncrement(&(This->ref));
+ TRACE("(%p) ref was %d\n", This, ref - 1);
+ return ref;
+}
- if (!ppv) {
- WARN("invalid parameter\n");
- return E_INVALIDARG;
+static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound8_Release(
+ LPDIRECTSOUND8 iface)
+{
+ IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
+ ULONG ref = InterlockedDecrement(&(This->ref));
+ TRACE("(%p) ref was %d\n", This, ref + 1);
+ if (!ref) {
+ This->pdsfd->pDS8 = NULL;
+ HeapFree(GetProcessHeap(), 0, This);
+ TRACE("(%p) released\n", This);
}
+ return ref;
+}
- if (IsEqualIID(riid, &IID_IUnknown)) {
- IUnknown_AddRef(&This->IUnknown_iface);
- *ppv = &This->IUnknown_iface;
- return S_OK;
- } else if (IsEqualIID(riid, &IID_IDirectSoundFullDuplex)) {
- IDirectSoundFullDuplex_AddRef(&This->IDirectSoundFullDuplex_iface);
- *ppv = &This->IDirectSoundFullDuplex_iface;
- return S_OK;
- } else if (This->ds8_unk && (IsEqualIID(riid, &IID_IDirectSound) ||
- IsEqualIID(riid, &IID_IDirectSound8)))
- return IUnknown_QueryInterface(This->ds8_unk, riid, ppv);
- else if (This->dsc8_unk && IsEqualIID(riid, &IID_IDirectSoundCapture))
- return IUnknown_QueryInterface(This->dsc8_unk, riid, ppv);
+static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_CreateSoundBuffer(
+ LPDIRECTSOUND8 iface,
+ LPCDSBUFFERDESC dsbd,
+ LPLPDIRECTSOUNDBUFFER ppdsb,
+ LPUNKNOWN lpunk)
+{
+ IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
+ TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
+ return IDirectSound8_CreateSoundBuffer(This->pdsfd->renderer_device,dsbd,ppdsb,lpunk);
+}
- *ppv = NULL;
- return E_NOINTERFACE;
+static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_GetCaps(
+ LPDIRECTSOUND8 iface,
+ LPDSCAPS lpDSCaps)
+{
+ IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
+ TRACE("(%p,%p)\n",This,lpDSCaps);
+ return IDirectSound8_GetCaps(This->pdsfd->renderer_device, lpDSCaps);
}
-static ULONG WINAPI IUnknownImpl_AddRef(IUnknown *iface)
+static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_DuplicateSoundBuffer(
+ LPDIRECTSOUND8 iface,
+ LPDIRECTSOUNDBUFFER psb,
+ LPLPDIRECTSOUNDBUFFER ppdsb)
{
- IDirectSoundFullDuplexImpl *This = impl_from_IUnknown(iface);
- ULONG ref = InterlockedIncrement(&This->ref);
+ IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
+ TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
+ return IDirectSound8_DuplicateSoundBuffer(This->pdsfd->renderer_device,psb,ppdsb);
+}
- TRACE("(%p) ref=%d\n", This, ref);
+static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_SetCooperativeLevel(
+ LPDIRECTSOUND8 iface,
+ HWND hwnd,
+ DWORD level)
+{
+ IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
+ TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
+ return IDirectSound8_SetCooperativeLevel(This->pdsfd->renderer_device,hwnd,level);
+}
- if(ref == 1)
- InterlockedIncrement(&This->numIfaces);
- return ref;
+static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_Compact(
+ LPDIRECTSOUND8 iface)
+{
+ IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
+ TRACE("(%p)\n", This);
+ return IDirectSound8_Compact(This->pdsfd->renderer_device);
+}
+
+static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_GetSpeakerConfig(
+ LPDIRECTSOUND8 iface,
+ LPDWORD lpdwSpeakerConfig)
+{
+ IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
+ TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
+ return IDirectSound8_GetSpeakerConfig(This->pdsfd->renderer_device,lpdwSpeakerConfig);
}
-static ULONG WINAPI IUnknownImpl_Release(IUnknown *iface)
+static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_SetSpeakerConfig(
+ LPDIRECTSOUND8 iface,
+ DWORD config)
{
- IDirectSoundFullDuplexImpl *This = impl_from_IUnknown(iface);
- ULONG ref = InterlockedDecrement(&This->ref);
+ IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
+ TRACE("(%p,0x%08x)\n",This,config);
+ return IDirectSound8_SetSpeakerConfig(This->pdsfd->renderer_device,config);
+}
- TRACE("(%p) ref=%d\n", This, ref);
+static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_Initialize(
+ LPDIRECTSOUND8 iface,
+ LPCGUID lpcGuid)
+{
+ IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
+ TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
+ return IDirectSound8_Initialize(This->pdsfd->renderer_device,lpcGuid);
+}
- if (!ref && !InterlockedDecrement(&This->numIfaces))
- fullduplex_destroy(This);
- return ref;
+static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_VerifyCertification(
+ LPDIRECTSOUND8 iface,
+ DWORD *cert)
+{
+ IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
+ TRACE("(%p, %p)\n", This, cert);
+ return IDirectSound8_VerifyCertification(This->pdsfd->renderer_device,cert);
}
-static const IUnknownVtbl unk_vtbl =
+static const IDirectSound8Vtbl DirectSoundFullDuplex_DirectSound8_Vtbl =
{
- IUnknownImpl_QueryInterface,
- IUnknownImpl_AddRef,
- IUnknownImpl_Release
+ IDirectSoundFullDuplex_IDirectSound8_QueryInterface,
+ IDirectSoundFullDuplex_IDirectSound8_AddRef,
+ IDirectSoundFullDuplex_IDirectSound8_Release,
+ IDirectSoundFullDuplex_IDirectSound8_CreateSoundBuffer,
+ IDirectSoundFullDuplex_IDirectSound8_GetCaps,
+ IDirectSoundFullDuplex_IDirectSound8_DuplicateSoundBuffer,
+ IDirectSoundFullDuplex_IDirectSound8_SetCooperativeLevel,
+ IDirectSoundFullDuplex_IDirectSound8_Compact,
+ IDirectSoundFullDuplex_IDirectSound8_GetSpeakerConfig,
+ IDirectSoundFullDuplex_IDirectSound8_SetSpeakerConfig,
+ IDirectSoundFullDuplex_IDirectSound8_Initialize,
+ IDirectSoundFullDuplex_IDirectSound8_VerifyCertification
};
-/***************************************************************************
- * IDirectSoundFullDuplex implementation
+static HRESULT IDirectSoundFullDuplex_IDirectSound8_Create(
+ LPDIRECTSOUNDFULLDUPLEX pdsfd,
+ LPDIRECTSOUND8 * ppds8)
+{
+ IDirectSoundFullDuplex_IDirectSound8 * pdsfdds8;
+ TRACE("(%p,%p)\n",pdsfd,ppds8);
+
+ if (pdsfd == NULL) {
+ ERR("invalid parameter: pdsfd == NULL\n");
+ return DSERR_INVALIDPARAM;
+ }
+
+ if (ppds8 == NULL) {
+ ERR("invalid parameter: ppds8 == NULL\n");
+ return DSERR_INVALIDPARAM;
+ }
+
+ if (((IDirectSoundFullDuplexImpl*)pdsfd)->renderer_device == NULL) {
+ WARN("not initialized\n");
+ *ppds8 = NULL;
+ return DSERR_UNINITIALIZED;
+ }
+
+ pdsfdds8 = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdds8));
+ if (pdsfdds8 == NULL) {
+ WARN("out of memory\n");
+ *ppds8 = NULL;
+ return DSERR_OUTOFMEMORY;
+ }
+
+ pdsfdds8->lpVtbl = &DirectSoundFullDuplex_DirectSound8_Vtbl;
+ pdsfdds8->ref = 0;
+ pdsfdds8->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
+
+ *ppds8 = (LPDIRECTSOUND8)pdsfdds8;
+
+ return DS_OK;
+}
+
+/*******************************************************************************
+ * IDirectSoundFullDuplex_IDirectSoundCapture
*/
-static inline IDirectSoundFullDuplexImpl *impl_from_IDirectSoundFullDuplex(IDirectSoundFullDuplex *iface)
+static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_QueryInterface(
+ LPDIRECTSOUNDCAPTURE iface,
+ REFIID riid,
+ LPVOID * ppobj)
{
- return CONTAINING_RECORD(iface, IDirectSoundFullDuplexImpl, IDirectSoundFullDuplex_iface);
+ IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
+ TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+ return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
}
-static HRESULT WINAPI IDirectSoundFullDuplexImpl_QueryInterface(IDirectSoundFullDuplex *iface,
- REFIID riid, void **ppv)
+static ULONG WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_AddRef(
+ LPDIRECTSOUNDCAPTURE iface)
{
- IDirectSoundFullDuplexImpl *This = impl_from_IDirectSoundFullDuplex(iface);
- TRACE("(%p,%s,%p)\n", This, debugstr_guid(riid), ppv);
- return IUnknown_QueryInterface(&This->IUnknown_iface, riid, ppv);
+ IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
+ ULONG ref = InterlockedIncrement(&(This->ref));
+ TRACE("(%p) ref was %d\n", This, ref - 1);
+ return ref;
}
-static ULONG WINAPI IDirectSoundFullDuplexImpl_AddRef(IDirectSoundFullDuplex *iface)
+static ULONG WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_Release(
+ LPDIRECTSOUNDCAPTURE iface)
{
- IDirectSoundFullDuplexImpl *This = impl_from_IDirectSoundFullDuplex(iface);
- ULONG ref = InterlockedIncrement(&This->refdsfd);
+ IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
+ ULONG ref = InterlockedDecrement(&(This->ref));
+ TRACE("(%p) ref was %d\n", This, ref + 1);
+ if (!ref) {
+ This->pdsfd->pDSC = NULL;
+ HeapFree(GetProcessHeap(), 0, This);
+ TRACE("(%p) released\n", This);
+ }
+ return ref;
+}
- TRACE("(%p) ref=%d\n", This, ref);
+static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_CreateCaptureBuffer(
+ LPDIRECTSOUNDCAPTURE iface,
+ LPCDSCBUFFERDESC lpcDSCBufferDesc,
+ LPDIRECTSOUNDCAPTUREBUFFER* lplpDSCaptureBuffer,
+ LPUNKNOWN pUnk)
+{
+ IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
+ TRACE("(%p,%p,%p,%p)\n",This,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
+ return IDirectSoundCapture_CreateCaptureBuffer(This->pdsfd->capture_device,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
+}
- if(ref == 1)
- InterlockedIncrement(&This->numIfaces);
- return ref;
+static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_GetCaps(
+ LPDIRECTSOUNDCAPTURE iface,
+ LPDSCCAPS lpDSCCaps)
+{
+ IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
+ TRACE("(%p,%p)\n",This,lpDSCCaps);
+ return IDirectSoundCapture_GetCaps(This->pdsfd->capture_device, lpDSCCaps);
+}
+
+static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_Initialize(
+ LPDIRECTSOUNDCAPTURE iface,
+ LPCGUID lpcGUID)
+{
+ IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
+ TRACE("(%p, %s)\n", This, debugstr_guid(lpcGUID));
+ return IDirectSoundCapture_Initialize(This->pdsfd->capture_device,lpcGUID);
}
-static ULONG WINAPI IDirectSoundFullDuplexImpl_Release(IDirectSoundFullDuplex *iface)
+static const IDirectSoundCaptureVtbl DirectSoundFullDuplex_DirectSoundCapture_Vtbl =
{
- IDirectSoundFullDuplexImpl *This = impl_from_IDirectSoundFullDuplex(iface);
- ULONG ref = InterlockedDecrement(&This->refdsfd);
+ IDirectSoundFullDuplex_IDirectSoundCapture_QueryInterface,
+ IDirectSoundFullDuplex_IDirectSoundCapture_AddRef,
+ IDirectSoundFullDuplex_IDirectSoundCapture_Release,
+ IDirectSoundFullDuplex_IDirectSoundCapture_CreateCaptureBuffer,
+ IDirectSoundFullDuplex_IDirectSoundCapture_GetCaps,
+ IDirectSoundFullDuplex_IDirectSoundCapture_Initialize
+};
+
+static HRESULT IDirectSoundFullDuplex_IDirectSoundCapture_Create(
+ LPDIRECTSOUNDFULLDUPLEX pdsfd,
+ LPDIRECTSOUNDCAPTURE8 * ppdsc8)
+{
+ IDirectSoundFullDuplex_IDirectSoundCapture * pdsfddsc;
+ TRACE("(%p,%p)\n",pdsfd,ppdsc8);
+
+ if (pdsfd == NULL) {
+ ERR("invalid parameter: pdsfd == NULL\n");
+ return DSERR_INVALIDPARAM;
+ }
- TRACE("(%p) ref=%d\n", This, ref);
+ if (ppdsc8 == NULL) {
+ ERR("invalid parameter: ppdsc8 == NULL\n");
+ return DSERR_INVALIDPARAM;
+ }
+
+ if (((IDirectSoundFullDuplexImpl*)pdsfd)->capture_device == NULL) {
+ WARN("not initialized\n");
+ *ppdsc8 = NULL;
+ return DSERR_UNINITIALIZED;
+ }
- if (!ref && !InterlockedDecrement(&This->numIfaces))
- fullduplex_destroy(This);
+ pdsfddsc = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfddsc));
+ if (pdsfddsc == NULL) {
+ WARN("out of memory\n");
+ *ppdsc8 = NULL;
+ return DSERR_OUTOFMEMORY;
+ }
+
+ pdsfddsc->lpVtbl = &DirectSoundFullDuplex_DirectSoundCapture_Vtbl;
+ pdsfddsc->ref = 0;
+ pdsfddsc->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
+
+ *ppdsc8 = (LPDIRECTSOUNDCAPTURE)pdsfddsc;
+
+ return DS_OK;
+}
+
+/***************************************************************************
+ * IDirectSoundFullDuplexImpl
+ */
+static ULONG WINAPI
+IDirectSoundFullDuplexImpl_AddRef( LPDIRECTSOUNDFULLDUPLEX iface )
+{
+ IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
+ ULONG ref = InterlockedIncrement(&(This->ref));
+ TRACE("(%p) ref was %d\n", This, ref - 1);
return ref;
}
-static HRESULT WINAPI IDirectSoundFullDuplexImpl_Initialize(IDirectSoundFullDuplex *iface,
- const GUID *capture_dev, const GUID *render_dev, const DSCBUFFERDESC *cbufdesc,
- const DSBUFFERDESC *bufdesc, HWND hwnd, DWORD level, IDirectSoundCaptureBuffer8 **dscb8,
- IDirectSoundBuffer8 **dsb8)
+static HRESULT WINAPI
+IDirectSoundFullDuplexImpl_QueryInterface(
+ LPDIRECTSOUNDFULLDUPLEX iface,
+ REFIID riid,
+ LPVOID* ppobj )
{
- IDirectSoundFullDuplexImpl *This = impl_from_IDirectSoundFullDuplex(iface);
- IDirectSound8 *ds8 = NULL;
- IDirectSoundCapture8 *dsc8 = NULL;
- HRESULT hr;
+ IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
+ TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
+
+ if (ppobj == NULL) {
+ WARN("invalid parameter\n");
+ return E_INVALIDARG;
+ }
+
+ *ppobj = NULL;
+
+ if (IsEqualIID(riid, &IID_IUnknown)) {
+ if (!This->pUnknown) {
+ IDirectSoundFullDuplex_IUnknown_Create(iface, &This->pUnknown);
+ if (!This->pUnknown) {
+ WARN("IDirectSoundFullDuplex_IUnknown_Create() failed\n");
+ *ppobj = NULL;
+ return E_NOINTERFACE;
+ }
+ }
+ IDirectSoundFullDuplex_IUnknown_AddRef(This->pUnknown);
+ *ppobj = This->pUnknown;
+ return S_OK;
+ } else if (IsEqualIID(riid, &IID_IDirectSoundFullDuplex)) {
+ IDirectSoundFullDuplexImpl_AddRef(iface);
+ *ppobj = This;
+ return S_OK;
+ } else if (IsEqualIID(riid, &IID_IDirectSound)
+ || IsEqualIID(riid, &IID_IDirectSound8)) {
+ if (!This->pDS8) {
+ IDirectSoundFullDuplex_IDirectSound8_Create(iface, &This->pDS8);
+ if (!This->pDS8) {
+ WARN("IDirectSoundFullDuplex_IDirectSound8_Create() failed\n");
+ *ppobj = NULL;
+ return E_NOINTERFACE;
+ }
+ }
+ IDirectSoundFullDuplex_IDirectSound8_AddRef(This->pDS8);
+ *ppobj = This->pDS8;
+ return S_OK;
+ } else if (IsEqualIID(riid, &IID_IDirectSoundCapture)) {
+ if (!This->pDSC) {
+ IDirectSoundFullDuplex_IDirectSoundCapture_Create(iface, &This->pDSC);
+ if (!This->pDSC) {
+ WARN("IDirectSoundFullDuplex_IDirectSoundCapture_Create() failed\n");
+ *ppobj = NULL;
+ return E_NOINTERFACE;
+ }
+ }
+ IDirectSoundFullDuplex_IDirectSoundCapture_AddRef(This->pDSC);
+ *ppobj = This->pDSC;
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+}
- TRACE("(%p,%s,%s,%p,%p,%p,%x,%p,%p)\n", This, debugstr_guid(capture_dev),
- debugstr_guid(render_dev), cbufdesc, bufdesc, hwnd, level, dscb8, dsb8);
+static ULONG WINAPI
+IDirectSoundFullDuplexImpl_Release( LPDIRECTSOUNDFULLDUPLEX iface )
+{
+ IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
+ ULONG ref = InterlockedDecrement(&(This->ref));
+ TRACE("(%p) ref was %d\n", This, ref - 1);
+
+ if (!ref) {
+ if (This->capture_device)
+ IDirectSoundCapture_Release(This->capture_device);
+ if (This->renderer_device)
+ IDirectSound_Release(This->renderer_device);
+ HeapFree( GetProcessHeap(), 0, This );
+ TRACE("(%p) released\n", This);
+ }
+ return ref;
+}
- if (!dscb8 || !dsb8)
- return E_INVALIDARG;
+static HRESULT WINAPI
+IDirectSoundFullDuplexImpl_Initialize(
+ LPDIRECTSOUNDFULLDUPLEX iface,
+ LPCGUID pCaptureGuid,
+ LPCGUID pRendererGuid,
+ LPCDSCBUFFERDESC lpDscBufferDesc,
+ LPCDSBUFFERDESC lpDsBufferDesc,
+ HWND hWnd,
+ DWORD dwLevel,
+ LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8,
+ LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8 )
+{
+ HRESULT hr;
+ IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
- *dscb8 = NULL;
- *dsb8 = NULL;
+ TRACE("(%p,%s,%s,%p,%p,%p,%x,%p,%p)\n", This,
+ debugstr_guid(pCaptureGuid), debugstr_guid(pRendererGuid),
+ lpDscBufferDesc, lpDsBufferDesc, hWnd, dwLevel,
+ lplpDirectSoundCaptureBuffer8, lplpDirectSoundBuffer8);
- if (This->ds8_unk || This->dsc8_unk) {
+ if (This->renderer_device != NULL || This->capture_device != NULL) {
WARN("already initialized\n");
+ *lplpDirectSoundCaptureBuffer8 = NULL;
+ *lplpDirectSoundBuffer8 = NULL;
return DSERR_ALREADYINITIALIZED;
}
- hr = IDirectSoundImpl_Create(&This->IUnknown_iface, &IID_IUnknown, (void**)&This->ds8_unk,
- TRUE);
- if (SUCCEEDED(hr)) {
- IUnknown_QueryInterface(This->ds8_unk, &IID_IDirectSound8, (void**)&ds8);
- hr = IDirectSound_Initialize(ds8, render_dev);
- }
+ hr = DSOUND_Create8(&IID_IDirectSound8, &This->renderer_device);
+ if (SUCCEEDED(hr))
+ hr = IDirectSound_Initialize(This->renderer_device, pRendererGuid);
if (hr != DS_OK) {
- WARN("Creating/initializing IDirectSound8 failed\n");
- goto error;
+ WARN("DirectSoundDevice_Initialize() failed\n");
+ *lplpDirectSoundCaptureBuffer8 = NULL;
+ *lplpDirectSoundBuffer8 = NULL;
+ return hr;
}
- IDirectSound8_SetCooperativeLevel(ds8, hwnd, level);
+ IDirectSound8_SetCooperativeLevel(This->renderer_device, hWnd, dwLevel);
- hr = IDirectSound8_CreateSoundBuffer(ds8, bufdesc, (IDirectSoundBuffer**)dsb8, NULL);
+ hr = IDirectSound8_CreateSoundBuffer(This->renderer_device, lpDsBufferDesc,
+ (IDirectSoundBuffer**)lplpDirectSoundBuffer8, NULL);
if (hr != DS_OK) {
- WARN("IDirectSoundBuffer_Create() failed\n");
- goto error;
+ WARN("IDirectSoundBufferImpl_Create() failed\n");
+ *lplpDirectSoundCaptureBuffer8 = NULL;
+ *lplpDirectSoundBuffer8 = NULL;
+ return hr;
}
- hr = IDirectSoundCaptureImpl_Create(&This->IUnknown_iface, &IID_IUnknown,
- (void**)&This->dsc8_unk, TRUE);
- if (SUCCEEDED(hr)) {
- IUnknown_QueryInterface(This->dsc8_unk, &IID_IDirectSoundCapture8, (void**)&dsc8);
- hr = IDirectSoundCapture_Initialize(dsc8, capture_dev);
- }
+ hr = DSOUND_CaptureCreate8(&IID_IDirectSoundCapture8, &This->capture_device);
+ if (SUCCEEDED(hr))
+ hr = IDirectSoundCapture_Initialize(This->capture_device, pCaptureGuid);
if (hr != DS_OK) {
- WARN("Creating/initializing IDirectSoundCapture8 failed\n");
- goto error;
+ WARN("DirectSoundCaptureDevice_Initialize() failed\n");
+ *lplpDirectSoundCaptureBuffer8 = NULL;
+ *lplpDirectSoundBuffer8 = NULL;
+ return hr;
}
- hr = IDirectSoundCapture_CreateCaptureBuffer(dsc8, cbufdesc,
- (IDirectSoundCaptureBuffer**)dscb8, NULL);
+ hr = IDirectSoundCapture_CreateCaptureBuffer(This->capture_device,
+ lpDscBufferDesc,
+ (IDirectSoundCaptureBuffer**)lplpDirectSoundCaptureBuffer8,
+ NULL);
if (hr != DS_OK) {
- WARN("IDirectSoundCapture_CreateCaptureBuffer() failed\n");
- goto error;
+ WARN("IDirectSoundCaptureBufferImpl_Create() failed\n");
+ *lplpDirectSoundCaptureBuffer8 = NULL;
+ *lplpDirectSoundBuffer8 = NULL;
+ return hr;
}
- IDirectSound8_Release(ds8);
- IDirectSoundCapture_Release(dsc8);
- return DS_OK;
-
-error:
- if (*dsb8) {
- IDirectSoundBuffer8_Release(*dsb8);
- *dsb8 = NULL;
- }
- if (ds8)
- IDirectSound8_Release(ds8);
- if (This->ds8_unk) {
- IUnknown_Release(This->ds8_unk);
- This->ds8_unk = NULL;
- }
- if (*dscb8) {
- IDirectSoundCaptureBuffer8_Release(*dscb8);
- *dscb8 = NULL;
- }
- if (dsc8)
- IDirectSoundCapture_Release(dsc8);
- if (This->dsc8_unk) {
- IUnknown_Release(This->dsc8_unk);
- This->dsc8_unk = NULL;
- }
return hr;
}
-static const IDirectSoundFullDuplexVtbl dsfd_vtbl =
+static const IDirectSoundFullDuplexVtbl dsfdvt =
{
/* IUnknown methods */
IDirectSoundFullDuplexImpl_QueryInterface,
IDirectSoundFullDuplexImpl_Initialize
};
-HRESULT DSOUND_FullDuplexCreate(REFIID riid, void **ppv)
+HRESULT DSOUND_FullDuplexCreate(
+ REFIID riid,
+ LPDIRECTSOUNDFULLDUPLEX* ppDSFD)
{
- IDirectSoundFullDuplexImpl *obj;
- HRESULT hr;
+ IDirectSoundFullDuplexImpl *This = NULL;
+ TRACE("(%s, %p)\n", debugstr_guid(riid), ppDSFD);
- TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
+ if (ppDSFD == NULL) {
+ WARN("invalid parameter: ppDSFD == NULL\n");
+ return DSERR_INVALIDPARAM;
+ }
- *ppv = NULL;
- obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*obj));
- if (!obj) {
- WARN("out of memory\n");
- return DSERR_OUTOFMEMORY;
+ if (!IsEqualIID(riid, &IID_IUnknown) &&
+ !IsEqualIID(riid, &IID_IDirectSoundFullDuplex)) {
+ *ppDSFD = 0;
+ return E_NOINTERFACE;
}
+ /* Get dsound configuration */
setup_dsound_options();
- obj->IDirectSoundFullDuplex_iface.lpVtbl = &dsfd_vtbl;
- obj->IUnknown_iface.lpVtbl = &unk_vtbl;
- obj->ref = 1;
- obj->refdsfd = 0;
- obj->numIfaces = 1;
+ This = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl));
- hr = IUnknown_QueryInterface(&obj->IUnknown_iface, riid, ppv);
- IUnknown_Release(&obj->IUnknown_iface);
+ if (This == NULL) {
+ WARN("out of memory\n");
+ *ppDSFD = NULL;
+ return DSERR_OUTOFMEMORY;
+ }
- return hr;
+ This->lpVtbl = &dsfdvt;
+ This->ref = 1;
+ This->capture_device = NULL;
+ This->renderer_device = NULL;
+
+ *ppDSFD = (LPDIRECTSOUNDFULLDUPLEX)This;
+
+ return DS_OK;
}
/***************************************************************************
* Create and initialize a DirectSoundFullDuplex interface.
*
* PARAMS
- * capture_dev [I] Address of sound capture device GUID.
- * render_dev [I] Address of sound render device GUID.
- * cbufdesc [I] Address of capture buffer description.
- * bufdesc [I] Address of render buffer description.
- * hwnd [I] Handle to application window.
- * level [I] Cooperative level.
- * dsfd [O] Address where full duplex interface returned.
- * dscb8 [0] Address where capture buffer interface returned.
- * dsb8 [0] Address where render buffer interface returned.
- * outer_unk [I] Must be NULL.
+ * pcGuidCaptureDevice [I] Address of sound capture device GUID.
+ * pcGuidRenderDevice [I] Address of sound render device GUID.
+ * pcDSCBufferDesc [I] Address of capture buffer description.
+ * pcDSBufferDesc [I] Address of render buffer description.
+ * hWnd [I] Handle to application window.
+ * dwLevel [I] Cooperative level.
+ * ppDSFD [O] Address where full duplex interface returned.
+ * ppDSCBuffer8 [0] Address where capture buffer interface returned.
+ * ppDSBuffer8 [0] Address where render buffer interface returned.
+ * pUnkOuter [I] Must be NULL.
*
* RETURNS
* Success: DS_OK
* Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
* DSERR_OUTOFMEMORY DSERR_INVALIDCALL DSERR_NODRIVER
*/
-HRESULT WINAPI DirectSoundFullDuplexCreate(const GUID *capture_dev, const GUID *render_dev,
- const DSCBUFFERDESC *cbufdesc, const DSBUFFERDESC *bufdesc, HWND hwnd, DWORD level,
- IDirectSoundFullDuplex **dsfd, IDirectSoundCaptureBuffer8 **dscb8,
- IDirectSoundBuffer8 **dsb8, IUnknown *outer_unk)
+HRESULT WINAPI
+DirectSoundFullDuplexCreate(
+ LPCGUID pcGuidCaptureDevice,
+ LPCGUID pcGuidRenderDevice,
+ LPCDSCBUFFERDESC pcDSCBufferDesc,
+ LPCDSBUFFERDESC pcDSBufferDesc,
+ HWND hWnd,
+ DWORD dwLevel,
+ LPDIRECTSOUNDFULLDUPLEX *ppDSFD,
+ LPDIRECTSOUNDCAPTUREBUFFER8 *ppDSCBuffer8,
+ LPDIRECTSOUNDBUFFER8 *ppDSBuffer8,
+ LPUNKNOWN pUnkOuter)
{
- HRESULT hr;
+ HRESULT hres;
+ IDirectSoundFullDuplexImpl *This = NULL;
+ TRACE("(%s,%s,%p,%p,%p,%x,%p,%p,%p,%p)\n",
+ debugstr_guid(pcGuidCaptureDevice), debugstr_guid(pcGuidRenderDevice),
+ pcDSCBufferDesc, pcDSBufferDesc, hWnd, dwLevel, ppDSFD, ppDSCBuffer8,
+ ppDSBuffer8, pUnkOuter);
+
+ if (pUnkOuter) {
+ WARN("pUnkOuter != 0\n");
+ *ppDSFD = NULL;
+ return DSERR_NOAGGREGATION;
+ }
- TRACE("(%s,%s,%p,%p,%p,%x,%p,%p,%p,%p)\n", debugstr_guid(capture_dev),
- debugstr_guid(render_dev), cbufdesc, bufdesc, hwnd, level, dsfd, dscb8, dsb8,
- outer_unk);
+ if (pcDSCBufferDesc == NULL) {
+ WARN("invalid parameter: pcDSCBufferDesc == NULL\n");
+ *ppDSFD = NULL;
+ return DSERR_INVALIDPARAM;
+ }
- if (!dsfd)
+ if (pcDSBufferDesc == NULL) {
+ WARN("invalid parameter: pcDSBufferDesc == NULL\n");
+ *ppDSFD = NULL;
return DSERR_INVALIDPARAM;
- if (outer_unk) {
- *dsfd = NULL;
- return DSERR_NOAGGREGATION;
}
- hr = DSOUND_FullDuplexCreate(&IID_IDirectSoundFullDuplex, (void**)dsfd);
- if (hr == DS_OK) {
- hr = IDirectSoundFullDuplex_Initialize(*dsfd, capture_dev, render_dev, cbufdesc, bufdesc,
- hwnd, level, dscb8, dsb8);
- if (hr != DS_OK) {
- IDirectSoundFullDuplex_Release(*dsfd);
- *dsfd = NULL;
- WARN("IDirectSoundFullDuplexImpl_Initialize failed\n");
- }
+ if (ppDSFD == NULL) {
+ WARN("invalid parameter: ppDSFD == NULL\n");
+ return DSERR_INVALIDPARAM;
}
- return hr;
+ if (ppDSCBuffer8 == NULL) {
+ WARN("invalid parameter: ppDSCBuffer8 == NULL\n");
+ *ppDSFD = NULL;
+ return DSERR_INVALIDPARAM;
+ }
+
+ if (ppDSBuffer8 == NULL) {
+ WARN("invalid parameter: ppDSBuffer8 == NULL\n");
+ *ppDSFD = NULL;
+ return DSERR_INVALIDPARAM;
+ }
+
+ hres = DSOUND_FullDuplexCreate(&IID_IDirectSoundFullDuplex, (LPDIRECTSOUNDFULLDUPLEX*)&This);
+ if (FAILED(hres)) return hres;
+
+ hres = IDirectSoundFullDuplexImpl_Initialize((LPDIRECTSOUNDFULLDUPLEX)This,
+ pcGuidCaptureDevice,
+ pcGuidRenderDevice,
+ pcDSCBufferDesc,
+ pcDSBufferDesc,
+ hWnd, dwLevel, ppDSCBuffer8,
+ ppDSBuffer8);
+ if (hres != DS_OK) {
+ IUnknown_Release((LPDIRECTSOUNDFULLDUPLEX)This);
+ WARN("IDirectSoundFullDuplexImpl_Initialize failed\n");
+ *ppDSFD = NULL;
+ } else
+ *ppDSFD = (LPDIRECTSOUNDFULLDUPLEX)This;
+
+ return hres;
}
+++ /dev/null
-#ifdef _MSC_VER
-#pragma warning (disable:4305)
-#endif
-
-/* generated by tools/make_fir; DO NOT EDIT! */
-static const int fir_len = 7907;
-static const int fir_step = 120;
-static const float fir[] = {
--0.0000000000, -0.0000021601, -0.0000043304, -0.0000065096, -0.0000086969,
--0.0000108911, -0.0000130912, -0.0000152960, -0.0000175046, -0.0000197157,
--0.0000219284, -0.0000241414, -0.0000263537, -0.0000285642, -0.0000307717,
--0.0000329751, -0.0000351732, -0.0000373650, -0.0000395493, -0.0000417249,
--0.0000438907, -0.0000460456, -0.0000481885, -0.0000503180, -0.0000524333,
--0.0000545330, -0.0000566161, -0.0000586814, -0.0000607277, -0.0000627541,
--0.0000647592, -0.0000667421, -0.0000687015, -0.0000706365, -0.0000725458,
--0.0000744284, -0.0000762832, -0.0000781091, -0.0000799051, -0.0000816701,
--0.0000834030, -0.0000851028, -0.0000867685, -0.0000883990, -0.0000899935,
--0.0000915507, -0.0000930699, -0.0000945500, -0.0000959901, -0.0000973892,
--0.0000987464, -0.0001000609, -0.0001013318, -0.0001025581, -0.0001037391,
--0.0001048739, -0.0001059617, -0.0001070018, -0.0001079932, -0.0001089354,
--0.0001098276, -0.0001106690, -0.0001114590, -0.0001121969, -0.0001128821,
--0.0001135140, -0.0001140920, -0.0001146154, -0.0001150839, -0.0001154968,
--0.0001158536, -0.0001161540, -0.0001163974, -0.0001165834, -0.0001167117,
--0.0001167819, -0.0001167937, -0.0001167467, -0.0001166408, -0.0001164755,
--0.0001162508, -0.0001159664, -0.0001156222, -0.0001152181, -0.0001147539,
--0.0001142295, -0.0001136450, -0.0001130003, -0.0001122954, -0.0001115305,
--0.0001107055, -0.0001098205, -0.0001088758, -0.0001078715, -0.0001068078,
--0.0001056850, -0.0001045032, -0.0001032628, -0.0001019642, -0.0001006076,
--0.0000991935, -0.0000977224, -0.0000961945, -0.0000946105, -0.0000929709,
--0.0000912761, -0.0000895269, -0.0000877237, -0.0000858672, -0.0000839581,
--0.0000819970, -0.0000799848, -0.0000779221, -0.0000758098, -0.0000736486,
--0.0000714395, -0.0000691832, -0.0000668807, -0.0000645329, -0.0000621407,
--0.0000597052, -0.0000572273, -0.0000547082, -0.0000521487, -0.0000495501,
--0.0000469135, -0.0000442399, -0.0000415306, -0.0000387867, -0.0000360095,
--0.0000332001, -0.0000303599, -0.0000274901, -0.0000245920, -0.0000216669,
--0.0000187162, -0.0000157412, -0.0000127433, -0.0000097239, -0.0000066844,
--0.0000036262, -0.0000005509, 0.0000025402, 0.0000056456, 0.0000087637,
-0.0000118931, 0.0000150322, 0.0000181796, 0.0000213335, 0.0000244926,
-0.0000276553, 0.0000308199, 0.0000339848, 0.0000371486, 0.0000403095,
-0.0000434660, 0.0000466164, 0.0000497592, 0.0000528927, 0.0000560153,
-0.0000591253, 0.0000622212, 0.0000653013, 0.0000683639, 0.0000714075,
-0.0000744303, 0.0000774309, 0.0000804075, 0.0000833585, 0.0000862823,
-0.0000891774, 0.0000920420, 0.0000948747, 0.0000976737, 0.0001004377,
-0.0001031648, 0.0001058537, 0.0001085028, 0.0001111105, 0.0001136753,
-0.0001161957, 0.0001186702, 0.0001210974, 0.0001234757, 0.0001258038,
-0.0001280801, 0.0001303034, 0.0001324722, 0.0001345852, 0.0001366410,
-0.0001386382, 0.0001405757, 0.0001424521, 0.0001442661, 0.0001460166,
-0.0001477024, 0.0001493222, 0.0001508749, 0.0001523595, 0.0001537748,
-0.0001551198, 0.0001563934, 0.0001575947, 0.0001587227, 0.0001597764,
-0.0001607549, 0.0001616575, 0.0001624832, 0.0001632313, 0.0001639010,
-0.0001644915, 0.0001650023, 0.0001654325, 0.0001657817, 0.0001660492,
-0.0001662345, 0.0001663371, 0.0001663566, 0.0001662924, 0.0001661444,
-0.0001659120, 0.0001655949, 0.0001651931, 0.0001647061, 0.0001641339,
-0.0001634764, 0.0001627333, 0.0001619047, 0.0001609906, 0.0001599910,
-0.0001589060, 0.0001577357, 0.0001564803, 0.0001551400, 0.0001537151,
-0.0001522058, 0.0001506125, 0.0001489356, 0.0001471756, 0.0001453328,
-0.0001434079, 0.0001414014, 0.0001393138, 0.0001371460, 0.0001348984,
-0.0001325720, 0.0001301674, 0.0001276856, 0.0001251273, 0.0001224936,
-0.0001197852, 0.0001170033, 0.0001141489, 0.0001112231, 0.0001082270,
-0.0001051617, 0.0001020285, 0.0000988286, 0.0000955632, 0.0000922338,
-0.0000888417, 0.0000853883, 0.0000818750, 0.0000783033, 0.0000746747,
-0.0000709908, 0.0000672531, 0.0000634633, 0.0000596230, 0.0000557339,
-0.0000517978, 0.0000478164, 0.0000437914, 0.0000397247, 0.0000356181,
-0.0000314736, 0.0000272929, 0.0000230781, 0.0000188311, 0.0000145539,
-0.0000102485, 0.0000059168, 0.0000015611, -0.0000028167, -0.0000072145,
--0.0000116301, -0.0000160614, -0.0000205062, -0.0000249624, -0.0000294277,
--0.0000339001, -0.0000383772, -0.0000428568, -0.0000473367, -0.0000518146,
--0.0000562883, -0.0000607554, -0.0000652138, -0.0000696610, -0.0000740949,
--0.0000785131, -0.0000829133, -0.0000872932, -0.0000916505, -0.0000959829,
--0.0001002881, -0.0001045638, -0.0001088077, -0.0001130175, -0.0001171909,
--0.0001213257, -0.0001254195, -0.0001294702, -0.0001334754, -0.0001374329,
--0.0001413406, -0.0001451961, -0.0001489973, -0.0001527420, -0.0001564281,
--0.0001600534, -0.0001636158, -0.0001671132, -0.0001705435, -0.0001739047,
--0.0001771947, -0.0001804116, -0.0001835533, -0.0001866179, -0.0001896036,
--0.0001925083, -0.0001953304, -0.0001980679, -0.0002007190, -0.0002032820,
--0.0002057553, -0.0002081370, -0.0002104256, -0.0002126195, -0.0002147171,
--0.0002167169, -0.0002186173, -0.0002204171, -0.0002221147, -0.0002237089,
--0.0002251983, -0.0002265817, -0.0002278578, -0.0002290256, -0.0002300839,
--0.0002310316, -0.0002318677, -0.0002325913, -0.0002332015, -0.0002336975,
--0.0002340783, -0.0002343433, -0.0002344918, -0.0002345232, -0.0002344368,
--0.0002342322, -0.0002339089, -0.0002334665, -0.0002329046, -0.0002322229,
--0.0002314213, -0.0002304995, -0.0002294574, -0.0002282950, -0.0002270123,
--0.0002256094, -0.0002240864, -0.0002224434, -0.0002206808, -0.0002187988,
--0.0002167979, -0.0002146784, -0.0002124409, -0.0002100859, -0.0002076141,
--0.0002050261, -0.0002023227, -0.0001995047, -0.0001965730, -0.0001935285,
--0.0001903722, -0.0001871051, -0.0001837284, -0.0001802433, -0.0001766509,
--0.0001729527, -0.0001691499, -0.0001652439, -0.0001612363, -0.0001571285,
--0.0001529222, -0.0001486190, -0.0001442206, -0.0001397288, -0.0001351454,
--0.0001304723, -0.0001257113, -0.0001208645, -0.0001159339, -0.0001109216,
--0.0001058298, -0.0001006605, -0.0000954161, -0.0000900988, -0.0000847109,
--0.0000792549, -0.0000737331, -0.0000681481, -0.0000625023, -0.0000567983,
--0.0000510387, -0.0000452261, -0.0000393633, -0.0000334528, -0.0000274975,
--0.0000215001, -0.0000154635, -0.0000093905, -0.0000032841, 0.0000028530,
-0.0000090176, 0.0000152070, 0.0000214180, 0.0000276476, 0.0000338928,
-0.0000401505, 0.0000464177, 0.0000526912, 0.0000589678, 0.0000652446,
-0.0000715181, 0.0000777854, 0.0000840433, 0.0000902884, 0.0000965177,
-0.0001027279, 0.0001089158, 0.0001150782, 0.0001212119, 0.0001273136,
-0.0001333801, 0.0001394082, 0.0001453946, 0.0001513363, 0.0001572299,
-0.0001630723, 0.0001688602, 0.0001745906, 0.0001802603, 0.0001858661,
-0.0001914049, 0.0001968736, 0.0002022692, 0.0002075885, 0.0002128285,
-0.0002179862, 0.0002230587, 0.0002280430, 0.0002329361, 0.0002377352,
-0.0002424374, 0.0002470399, 0.0002515399, 0.0002559347, 0.0002602215,
-0.0002643977, 0.0002684607, 0.0002724079, 0.0002762367, 0.0002799448,
-0.0002835296, 0.0002869888, 0.0002903200, 0.0002935210, 0.0002965895,
-0.0002995235, 0.0003023207, 0.0003049791, 0.0003074968, 0.0003098718,
-0.0003121023, 0.0003141865, 0.0003161226, 0.0003179089, 0.0003195440,
-0.0003210261, 0.0003223540, 0.0003235261, 0.0003245412, 0.0003253981,
-0.0003260955, 0.0003266324, 0.0003270078, 0.0003272206, 0.0003272702,
-0.0003271556, 0.0003268761, 0.0003264312, 0.0003258202, 0.0003250428,
-0.0003240985, 0.0003229871, 0.0003217083, 0.0003202619, 0.0003186480,
-0.0003168666, 0.0003149178, 0.0003128017, 0.0003105187, 0.0003080692,
-0.0003054536, 0.0003026725, 0.0002997264, 0.0002966162, 0.0002933425,
-0.0002899064, 0.0002863087, 0.0002825506, 0.0002786332, 0.0002745577,
-0.0002703254, 0.0002659378, 0.0002613963, 0.0002567025, 0.0002518580,
-0.0002468647, 0.0002417243, 0.0002364387, 0.0002310100, 0.0002254401,
-0.0002197313, 0.0002138857, 0.0002079058, 0.0002017938, 0.0001955522,
-0.0001891836, 0.0001826906, 0.0001760759, 0.0001693423, 0.0001624925,
-0.0001555296, 0.0001484564, 0.0001412761, 0.0001339917, 0.0001266065,
-0.0001191237, 0.0001115465, 0.0001038785, 0.0000961230, 0.0000882835,
-0.0000803636, 0.0000723668, 0.0000642970, 0.0000561577, 0.0000479528,
-0.0000396861, 0.0000313614, 0.0000229828, 0.0000145541, 0.0000060793,
--0.0000024374, -0.0000109920, -0.0000195804, -0.0000281984, -0.0000368418,
--0.0000455063, -0.0000541878, -0.0000628818, -0.0000715842, -0.0000802906,
--0.0000889965, -0.0000976976, -0.0001063896, -0.0001150680, -0.0001237283,
--0.0001323662, -0.0001409772, -0.0001495568, -0.0001581006, -0.0001666042,
--0.0001750629, -0.0001834725, -0.0001918284, -0.0002001262, -0.0002083615,
--0.0002165298, -0.0002246267, -0.0002326478, -0.0002405888, -0.0002484452,
--0.0002562128, -0.0002638872, -0.0002714641, -0.0002789393, -0.0002863086,
--0.0002935678, -0.0003007127, -0.0003077392, -0.0003146432, -0.0003214208,
--0.0003280679, -0.0003345805, -0.0003409549, -0.0003471871, -0.0003532734,
--0.0003592101, -0.0003649934, -0.0003706199, -0.0003760859, -0.0003813879,
--0.0003865227, -0.0003914867, -0.0003962768, -0.0004008897, -0.0004053224,
--0.0004095717, -0.0004136348, -0.0004175087, -0.0004211906, -0.0004246778,
--0.0004279676, -0.0004310576, -0.0004339452, -0.0004366281, -0.0004391040,
--0.0004413708, -0.0004434263, -0.0004452685, -0.0004468956, -0.0004483058,
--0.0004494974, -0.0004504687, -0.0004512184, -0.0004517450, -0.0004520473,
--0.0004521241, -0.0004519743, -0.0004515970, -0.0004509913, -0.0004501566,
--0.0004490922, -0.0004477977, -0.0004462725, -0.0004445166, -0.0004425296,
--0.0004403116, -0.0004378626, -0.0004351828, -0.0004322726, -0.0004291324,
--0.0004257626, -0.0004221641, -0.0004183374, -0.0004142837, -0.0004100037,
--0.0004054988, -0.0004007702, -0.0003958191, -0.0003906472, -0.0003852560,
--0.0003796473, -0.0003738228, -0.0003677846, -0.0003615348, -0.0003550754,
--0.0003484089, -0.0003415377, -0.0003344642, -0.0003271912, -0.0003197214,
--0.0003120577, -0.0003042030, -0.0002961605, -0.0002879334, -0.0002795249,
--0.0002709385, -0.0002621777, -0.0002532462, -0.0002441476, -0.0002348857,
--0.0002254646, -0.0002158883, -0.0002061608, -0.0001962863, -0.0001862693,
--0.0001761140, -0.0001658250, -0.0001554068, -0.0001448641, -0.0001342017,
--0.0001234244, -0.0001125370, -0.0001015446, -0.0000904522, -0.0000792650,
--0.0000679881, -0.0000566268, -0.0000451865, -0.0000336725, -0.0000220904,
--0.0000104456, 0.0000012563, 0.0000130097, 0.0000248089, 0.0000366481,
-0.0000485216, 0.0000604235, 0.0000723481, 0.0000842894, 0.0000962415,
-0.0001081984, 0.0001201541, 0.0001321027, 0.0001440381, 0.0001559542,
-0.0001678449, 0.0001797043, 0.0001915261, 0.0002033042, 0.0002150326,
-0.0002267052, 0.0002383157, 0.0002498582, 0.0002613264, 0.0002727144,
-0.0002840160, 0.0002952252, 0.0003063359, 0.0003173421, 0.0003282378,
-0.0003390171, 0.0003496739, 0.0003602026, 0.0003705970, 0.0003808515,
-0.0003909603, 0.0004009177, 0.0004107179, 0.0004203554, 0.0004298245,
-0.0004391199, 0.0004482360, 0.0004571676, 0.0004659092, 0.0004744556,
-0.0004828018, 0.0004909425, 0.0004988729, 0.0005065881, 0.0005140831,
-0.0005213533, 0.0005283939, 0.0005352006, 0.0005417688, 0.0005480941,
-0.0005541724, 0.0005599994, 0.0005655712, 0.0005708838, 0.0005759334,
-0.0005807164, 0.0005852291, 0.0005894681, 0.0005934301, 0.0005971119,
-0.0006005103, 0.0006036225, 0.0006064456, 0.0006089769, 0.0006112139,
-0.0006131542, 0.0006147954, 0.0006161355, 0.0006171725, 0.0006179045,
-0.0006183298, 0.0006184469, 0.0006182543, 0.0006177508, 0.0006169354,
-0.0006158069, 0.0006143647, 0.0006126081, 0.0006105366, 0.0006081498,
-0.0006054476, 0.0006024300, 0.0005990971, 0.0005954492, 0.0005914868,
-0.0005872105, 0.0005826210, 0.0005777193, 0.0005725066, 0.0005669840,
-0.0005611530, 0.0005550152, 0.0005485724, 0.0005418263, 0.0005347792,
-0.0005274332, 0.0005197908, 0.0005118544, 0.0005036269, 0.0004951109,
-0.0004863097, 0.0004772264, 0.0004678642, 0.0004582267, 0.0004483176,
-0.0004381406, 0.0004276998, 0.0004169991, 0.0004060428, 0.0003948354,
-0.0003833814, 0.0003716854, 0.0003597523, 0.0003475871, 0.0003351948,
-0.0003225808, 0.0003097503, 0.0002967089, 0.0002834622, 0.0002700161,
-0.0002563763, 0.0002425489, 0.0002285401, 0.0002143560, 0.0002000031,
-0.0001854879, 0.0001708168, 0.0001559967, 0.0001410343, 0.0001259365,
-0.0001107104, 0.0000953630, 0.0000799015, 0.0000643331, 0.0000486653,
-0.0000329055, 0.0000170612, 0.0000011400, -0.0000148505, -0.0000309025,
--0.0000470081, -0.0000631597, -0.0000793491, -0.0000955685, -0.0001118099,
--0.0001280652, -0.0001443262, -0.0001605849, -0.0001768330, -0.0001930624,
--0.0002092648, -0.0002254319, -0.0002415556, -0.0002576275, -0.0002736393,
--0.0002895827, -0.0003054494, -0.0003212311, -0.0003369196, -0.0003525065,
--0.0003679835, -0.0003833426, -0.0003985753, -0.0004136736, -0.0004286292,
--0.0004434340, -0.0004580801, -0.0004725592, -0.0004868635, -0.0005009850,
--0.0005149159, -0.0005286483, -0.0005421744, -0.0005554866, -0.0005685774,
--0.0005814391, -0.0005940644, -0.0006064459, -0.0006185763, -0.0006304484,
--0.0006420553, -0.0006533899, -0.0006644455, -0.0006752151, -0.0006856923,
--0.0006958705, -0.0007057433, -0.0007153045, -0.0007245480, -0.0007334676,
--0.0007420577, -0.0007503124, -0.0007582263, -0.0007657937, -0.0007730096,
--0.0007798688, -0.0007863663, -0.0007924973, -0.0007982572, -0.0008036415,
--0.0008086459, -0.0008132662, -0.0008174987, -0.0008213393, -0.0008247847,
--0.0008278313, -0.0008304759, -0.0008327155, -0.0008345473, -0.0008359687,
--0.0008369770, -0.0008375702, -0.0008377461, -0.0008375030, -0.0008368390,
--0.0008357529, -0.0008342432, -0.0008323091, -0.0008299497, -0.0008271644,
--0.0008239527, -0.0008203145, -0.0008162498, -0.0008117589, -0.0008068421,
--0.0008015002, -0.0007957340, -0.0007895447, -0.0007829336, -0.0007759022,
--0.0007684523, -0.0007605858, -0.0007523049, -0.0007436121, -0.0007345100,
--0.0007250014, -0.0007150893, -0.0007047771, -0.0006940683, -0.0006829665,
--0.0006714757, -0.0006596000, -0.0006473437, -0.0006347115, -0.0006217080,
--0.0006083382, -0.0005946073, -0.0005805207, -0.0005660839, -0.0005513028,
--0.0005361833, -0.0005207315, -0.0005049539, -0.0004888569, -0.0004724474,
--0.0004557322, -0.0004387185, -0.0004214136, -0.0004038248, -0.0003859599,
--0.0003678267, -0.0003494331, -0.0003307873, -0.0003118976, -0.0002927724,
--0.0002734204, -0.0002538504, -0.0002340711, -0.0002140918, -0.0001939216,
--0.0001735697, -0.0001530458, -0.0001323593, -0.0001115200, -0.0000905376,
--0.0000694222, -0.0000481837, -0.0000268323, -0.0000053783, 0.0000161680,
-0.0000377962, 0.0000594957, 0.0000812561, 0.0001030665, 0.0001249163,
-0.0001467946, 0.0001686906, 0.0001905934, 0.0002124920, 0.0002343754,
-0.0002562326, 0.0002780524, 0.0002998238, 0.0003215357, 0.0003431768,
-0.0003647361, 0.0003862023, 0.0004075644, 0.0004288111, 0.0004499314,
-0.0004709140, 0.0004917479, 0.0005124220, 0.0005329253, 0.0005532468,
-0.0005733755, 0.0005933005, 0.0006130110, 0.0006324962, 0.0006517454,
-0.0006707479, 0.0006894932, 0.0007079708, 0.0007261704, 0.0007440816,
-0.0007616942, 0.0007789982, 0.0007959837, 0.0008126407, 0.0008289596,
-0.0008449308, 0.0008605448, 0.0008757923, 0.0008906642, 0.0009051513,
-0.0009192450, 0.0009329365, 0.0009462171, 0.0009590787, 0.0009715130,
-0.0009835120, 0.0009950678, 0.0010061729, 0.0010168199, 0.0010270014,
-0.0010367105, 0.0010459403, 0.0010546843, 0.0010629361, 0.0010706894,
-0.0010779384, 0.0010846773, 0.0010909007, 0.0010966033, 0.0011017801,
-0.0011064263, 0.0011105375, 0.0011141094, 0.0011171379, 0.0011196193,
-0.0011215502, 0.0011229273, 0.0011237476, 0.0011240084, 0.0011237074,
-0.0011228423, 0.0011214113, 0.0011194127, 0.0011168454, 0.0011137081,
-0.0011100002, 0.0011057211, 0.0011008708, 0.0010954492, 0.0010894568,
-0.0010828942, 0.0010757624, 0.0010680626, 0.0010597965, 0.0010509657,
-0.0010415725, 0.0010316192, 0.0010211086, 0.0010100437, 0.0009984277,
-0.0009862642, 0.0009735571, 0.0009603105, 0.0009465290, 0.0009322172,
-0.0009173801, 0.0009020230, 0.0008861516, 0.0008697717, 0.0008528894,
-0.0008355112, 0.0008176438, 0.0007992941, 0.0007804694, 0.0007611772,
-0.0007414252, 0.0007212216, 0.0007005745, 0.0006794927, 0.0006579848,
-0.0006360599, 0.0006137274, 0.0005909967, 0.0005678777, 0.0005443804,
-0.0005205151, 0.0004962922, 0.0004717224, 0.0004468167, 0.0004215861,
-0.0003960420, 0.0003701960, 0.0003440598, 0.0003176453, 0.0002909647,
-0.0002640303, 0.0002368545, 0.0002094500, 0.0001818296, 0.0001540064,
-0.0001259933, 0.0000978039, 0.0000694513, 0.0000409493, 0.0000123115,
--0.0000164483, -0.0000453161, -0.0000742779, -0.0001033196, -0.0001324268,
--0.0001615854, -0.0001907807, -0.0002199984, -0.0002492239, -0.0002784426,
--0.0003076398, -0.0003368006, -0.0003659105, -0.0003949545, -0.0004239178,
--0.0004527857, -0.0004815431, -0.0005101753, -0.0005386673, -0.0005670044,
--0.0005951717, -0.0006231543, -0.0006509376, -0.0006785067, -0.0007058470,
--0.0007329438, -0.0007597826, -0.0007863489, -0.0008126283, -0.0008386063,
--0.0008642689, -0.0008896018, -0.0009145911, -0.0009392227, -0.0009634830,
--0.0009873583, -0.0010108350, -0.0010338998, -0.0010565395, -0.0010787410,
--0.0011004914, -0.0011217780, -0.0011425883, -0.0011629099, -0.0011827307,
--0.0012020388, -0.0012208223, -0.0012390699, -0.0012567701, -0.0012739120,
--0.0012904848, -0.0013064777, -0.0013218805, -0.0013366832, -0.0013508758,
--0.0013644489, -0.0013773932, -0.0013896996, -0.0014013595, -0.0014123644,
--0.0014227062, -0.0014323770, -0.0014413695, -0.0014496762, -0.0014572904,
--0.0014642055, -0.0014704152, -0.0014759136, -0.0014806951, -0.0014847545,
--0.0014880868, -0.0014906875, -0.0014925524, -0.0014936777, -0.0014940597,
--0.0014936955, -0.0014925821, -0.0014907172, -0.0014880988, -0.0014847251,
--0.0014805949, -0.0014757072, -0.0014700615, -0.0014636576, -0.0014564957,
--0.0014485764, -0.0014399006, -0.0014304698, -0.0014202856, -0.0014093503,
--0.0013976662, -0.0013852363, -0.0013720639, -0.0013581526, -0.0013435065,
--0.0013281301, -0.0013120281, -0.0012952058, -0.0012776687, -0.0012594229,
--0.0012404746, -0.0012208306, -0.0012004980, -0.0011794844, -0.0011577974,
--0.0011354454, -0.0011124369, -0.0010887809, -0.0010644867, -0.0010395640,
--0.0010140227, -0.0009878733, -0.0009611264, -0.0009337931, -0.0009058849,
--0.0008774134, -0.0008483907, -0.0008188291, -0.0007887415, -0.0007581408,
--0.0007270403, -0.0006954536, -0.0006633947, -0.0006308778, -0.0005979174,
--0.0005645283, -0.0005307256, -0.0004965245, -0.0004619406, -0.0004269898,
--0.0003916882, -0.0003560521, -0.0003200980, -0.0002838427, -0.0002473033,
--0.0002104968, -0.0001734408, -0.0001361528, -0.0000986506, -0.0000609521,
--0.0000230756, 0.0000149607, 0.0000531385, 0.0000914390, 0.0001298435,
-0.0001683333, 0.0002068894, 0.0002454926, 0.0002841239, 0.0003227639,
-0.0003613934, 0.0003999929, 0.0004385430, 0.0004770241, 0.0005154167,
-0.0005537012, 0.0005918580, 0.0006298674, 0.0006677099, 0.0007053659,
-0.0007428156, 0.0007800396, 0.0008170183, 0.0008537322, 0.0008901619,
-0.0009262880, 0.0009620912, 0.0009975524, 0.0010326524, 0.0010673723,
-0.0011016931, 0.0011355960, 0.0011690626, 0.0012020743, 0.0012346128,
-0.0012666600, 0.0012981978, 0.0013292086, 0.0013596746, 0.0013895787,
-0.0014189035, 0.0014476321, 0.0014757478, 0.0015032342, 0.0015300751,
-0.0015562544, 0.0015817566, 0.0016065662, 0.0016306680, 0.0016540474,
-0.0016766897, 0.0016985808, 0.0017197068, 0.0017400541, 0.0017596096,
-0.0017783603, 0.0017962939, 0.0018133981, 0.0018296611, 0.0018450717,
-0.0018596186, 0.0018732914, 0.0018860799, 0.0018979741, 0.0019089647,
-0.0019190427, 0.0019281995, 0.0019364271, 0.0019437176, 0.0019500638,
-0.0019554590, 0.0019598967, 0.0019633710, 0.0019658766, 0.0019674083,
-0.0019679618, 0.0019675329, 0.0019661182, 0.0019637144, 0.0019603191,
-0.0019559301, 0.0019505458, 0.0019441651, 0.0019367874, 0.0019284124,
-0.0019190407, 0.0019086731, 0.0018973109, 0.0018849560, 0.0018716109,
-0.0018572784, 0.0018419618, 0.0018256652, 0.0018083930, 0.0017901499,
-0.0017709416, 0.0017507738, 0.0017296531, 0.0017075864, 0.0016845811,
-0.0016606451, 0.0016357870, 0.0016100155, 0.0015833403, 0.0015557711,
-0.0015273183, 0.0014979929, 0.0014678062, 0.0014367701, 0.0014048968,
-0.0013721991, 0.0013386903, 0.0013043841, 0.0012692947, 0.0012334365,
-0.0011968247, 0.0011594747, 0.0011214025, 0.0010826243, 0.0010431569,
-0.0010030174, 0.0009622235, 0.0009207930, 0.0008787443, 0.0008360961,
-0.0007928675, 0.0007490779, 0.0007047472, 0.0006598955, 0.0006145433,
-0.0005687114, 0.0005224210, 0.0004756935, 0.0004285507, 0.0003810145,
-0.0003331074, 0.0002848520, 0.0002362710, 0.0001873876, 0.0001382251,
-0.0000888071, 0.0000391574, -0.0000107000, -0.0000607409, -0.0001109410,
--0.0001612757, -0.0002117203, -0.0002622499, -0.0003128396, -0.0003634642,
--0.0004140985, -0.0004647171, -0.0005152948, -0.0005658059, -0.0006162249,
--0.0006665263, -0.0007166843, -0.0007666733, -0.0008164676, -0.0008660416,
--0.0009153695, -0.0009644258, -0.0010131848, -0.0010616211, -0.0011097090,
--0.0011574233, -0.0012047386, -0.0012516297, -0.0012980715, -0.0013440391,
--0.0013895077, -0.0014344526, -0.0014788493, -0.0015226735, -0.0015659012,
--0.0016085084, -0.0016504714, -0.0016917669, -0.0017323716, -0.0017722626,
--0.0018114173, -0.0018498132, -0.0018874283, -0.0019242408, -0.0019602293,
--0.0019953726, -0.0020296500, -0.0020630411, -0.0020955259, -0.0021270845,
--0.0021576979, -0.0021873471, -0.0022160136, -0.0022436795, -0.0022703270,
--0.0022959392, -0.0023204992, -0.0023439908, -0.0023663983, -0.0023877064,
--0.0024079004, -0.0024269658, -0.0024448891, -0.0024616569, -0.0024772565,
--0.0024916758, -0.0025049031, -0.0025169273, -0.0025277381, -0.0025373253,
--0.0025456797, -0.0025527924, -0.0025586554, -0.0025632609, -0.0025666021,
--0.0025686724, -0.0025694663, -0.0025689784, -0.0025672043, -0.0025641401,
--0.0025597826, -0.0025541290, -0.0025471774, -0.0025389266, -0.0025293756,
--0.0025185247, -0.0025063742, -0.0024929256, -0.0024781806, -0.0024621419,
--0.0024448128, -0.0024261971, -0.0024062993, -0.0023851246, -0.0023626791,
--0.0023389690, -0.0023140018, -0.0022877851, -0.0022603275, -0.0022316382,
--0.0022017270, -0.0021706043, -0.0021382811, -0.0021047694, -0.0020700814,
--0.0020342302, -0.0019972294, -0.0019590932, -0.0019198367, -0.0018794753,
--0.0018380252, -0.0017955030, -0.0017519262, -0.0017073126, -0.0016616808,
--0.0016150498, -0.0015674393, -0.0015188696, -0.0014693614, -0.0014189360,
--0.0013676154, -0.0013154219, -0.0012623785, -0.0012085085, -0.0011538359,
--0.0010983851, -0.0010421811, -0.0009852491, -0.0009276151, -0.0008693052,
--0.0008103463, -0.0007507654, -0.0006905900, -0.0006298483, -0.0005685683,
--0.0005067789, -0.0004445092, -0.0003817885, -0.0003186466, -0.0002551136,
--0.0001912198, -0.0001269959, -0.0000624728, 0.0000023182, 0.0000673457,
-0.0001325780, 0.0001979832, 0.0002635292, 0.0003291837, 0.0003949141,
-0.0004606880, 0.0005264724, 0.0005922346, 0.0006579415, 0.0007235600,
-0.0007890569, 0.0008543990, 0.0009195531, 0.0009844857, 0.0010491637,
-0.0011135537, 0.0011776223, 0.0012413365, 0.0013046629, 0.0013675684,
-0.0014300201, 0.0014919850, 0.0015534303, 0.0016143233, 0.0016746316,
-0.0017343229, 0.0017933649, 0.0018517259, 0.0019093741, 0.0019662779,
-0.0020224064, 0.0020777285, 0.0021322135, 0.0021858313, 0.0022385517,
-0.0022903452, 0.0023411825, 0.0023910345, 0.0024398728, 0.0024876693,
-0.0025343963, 0.0025800264, 0.0026245328, 0.0026678893, 0.0027100699,
-0.0027510492, 0.0027908024, 0.0028293051, 0.0028665336, 0.0029024645,
-0.0029370752, 0.0029703436, 0.0030022482, 0.0030327680, 0.0030618828,
-0.0030895730, 0.0031158194, 0.0031406037, 0.0031639083, 0.0031857162,
-0.0032060109, 0.0032247769, 0.0032419993, 0.0032576639, 0.0032717571,
-0.0032842663, 0.0032951796, 0.0033044855, 0.0033121739, 0.0033182348,
-0.0033226595, 0.0033254397, 0.0033265683, 0.0033260387, 0.0033238451,
-0.0033199827, 0.0033144474, 0.0033072359, 0.0032983458, 0.0032877756,
-0.0032755244, 0.0032615923, 0.0032459804, 0.0032286903, 0.0032097246,
-0.0031890869, 0.0031667815, 0.0031428134, 0.0031171889, 0.0030899146,
-0.0030609984, 0.0030304488, 0.0029982753, 0.0029644882, 0.0029290984,
-0.0028921181, 0.0028535600, 0.0028134378, 0.0027717659, 0.0027285596,
-0.0026838351, 0.0026376093, 0.0025899000, 0.0025407257, 0.0024901057,
-0.0024380603, 0.0023846105, 0.0023297778, 0.0022735848, 0.0022160549,
-0.0021572119, 0.0020970806, 0.0020356866, 0.0019730560, 0.0019092157,
-0.0018441934, 0.0017780175, 0.0017107168, 0.0016423212, 0.0015728608,
-0.0015023666, 0.0014308703, 0.0013584040, 0.0012850006, 0.0012106934,
-0.0011355164, 0.0010595042, 0.0009826917, 0.0009051145, 0.0008268089,
-0.0007478113, 0.0006681588, 0.0005878890, 0.0005070398, 0.0004256495,
-0.0003437572, 0.0002614018, 0.0001786230, 0.0000954606, 0.0000119550,
--0.0000718533, -0.0001559234, -0.0002402143, -0.0003246844, -0.0004092923,
--0.0004939960, -0.0005787535, -0.0006635226, -0.0007482608, -0.0008329258,
--0.0009174749, -0.0010018654, -0.0010860544, -0.0011699992, -0.0012536568,
--0.0013369845, -0.0014199393, -0.0015024785, -0.0015845592, -0.0016661388,
--0.0017471747, -0.0018276244, -0.0019074456, -0.0019865962, -0.0020650342,
--0.0021427177, -0.0022196054, -0.0022956558, -0.0023708281, -0.0024450815,
--0.0025183756, -0.0025906704, -0.0026619261, -0.0027321035, -0.0028011637,
--0.0028690681, -0.0029357788, -0.0030012581, -0.0030654689, -0.0031283747,
--0.0031899394, -0.0032501275, -0.0033089041, -0.0033662347, -0.0034220855,
--0.0034764236, -0.0035292163, -0.0035804318, -0.0036300389, -0.0036780073,
--0.0037243070, -0.0037689092, -0.0038117856, -0.0038529085, -0.0038922514,
--0.0039297883, -0.0039654940, -0.0039993444, -0.0040313159, -0.0040613860,
--0.0040895329, -0.0041157359, -0.0041399751, -0.0041622314, -0.0041824868,
--0.0042007241, -0.0042169271, -0.0042310807, -0.0042431705, -0.0042531833,
--0.0042611069, -0.0042669299, -0.0042706422, -0.0042722345, -0.0042716985,
--0.0042690272, -0.0042642143, -0.0042572549, -0.0042481449, -0.0042368814,
--0.0042234624, -0.0042078873, -0.0041901562, -0.0041702705, -0.0041482326,
--0.0041240461, -0.0040977156, -0.0040692468, -0.0040386465, -0.0040059225,
--0.0039710838, -0.0039341405, -0.0038951038, -0.0038539859, -0.0038108001,
--0.0037655608, -0.0037182836, -0.0036689849, -0.0036176824, -0.0035643948,
--0.0035091419, -0.0034519445, -0.0033928243, -0.0033318045, -0.0032689087,
--0.0032041620, -0.0031375904, -0.0030692209, -0.0029990813, -0.0029272006,
--0.0028536087, -0.0027783366, -0.0027014160, -0.0026228797, -0.0025427614,
--0.0024610956, -0.0023779179, -0.0022932646, -0.0022071730, -0.0021196811,
--0.0020308278, -0.0019406529, -0.0018491969, -0.0017565011, -0.0016626076,
--0.0015675591, -0.0014713993, -0.0013741725, -0.0012759234, -0.0011766978,
--0.0010765418, -0.0009755024, -0.0008736271, -0.0007709638, -0.0006675613,
--0.0005634687, -0.0004587356, -0.0003534123, -0.0002475493, -0.0001411978,
--0.0000344092, 0.0000727645, 0.0001802712, 0.0002880581, 0.0003960723,
-0.0005042607, 0.0006125697, 0.0007209455, 0.0008293342, 0.0009376817,
-0.0010459336, 0.0011540355, 0.0012619327, 0.0013695707, 0.0014768947,
-0.0015838501, 0.0016903819, 0.0017964356, 0.0019019563, 0.0020068897,
-0.0021111811, 0.0022147762, 0.0023176209, 0.0024196611, 0.0025208431,
-0.0026211132, 0.0027204184, 0.0028187055, 0.0029159221, 0.0030120157,
-0.0031069345, 0.0032006271, 0.0032930424, 0.0033841298, 0.0034738392,
-0.0035621211, 0.0036489264, 0.0037342067, 0.0038179142, 0.0039000017,
-0.0039804224, 0.0040591307, 0.0041360811, 0.0042112294, 0.0042845317,
-0.0043559452, 0.0044254276, 0.0044929376, 0.0045584348, 0.0046218796,
-0.0046832332, 0.0047424579, 0.0047995168, 0.0048543739, 0.0049069944,
-0.0049573443, 0.0050053908, 0.0050511019, 0.0050944469, 0.0051353961,
-0.0051739208, 0.0052099936, 0.0052435880, 0.0052746789, 0.0053032421,
-0.0053292549, 0.0053526956, 0.0053735437, 0.0053917800, 0.0054073864,
-0.0054203464, 0.0054306444, 0.0054382662, 0.0054431990, 0.0054454311,
-0.0054449524, 0.0054417538, 0.0054358277, 0.0054271679, 0.0054157694,
-0.0054016287, 0.0053847435, 0.0053651130, 0.0053427377, 0.0053176194,
-0.0052897616, 0.0052591688, 0.0052258471, 0.0051898039, 0.0051510480,
-0.0051095896, 0.0050654404, 0.0050186133, 0.0049691226, 0.0049169842,
-0.0048622151, 0.0048048338, 0.0047448602, 0.0046823156, 0.0046172225,
-0.0045496048, 0.0044794879, 0.0044068984, 0.0043318642, 0.0042544146,
-0.0041745801, 0.0040923927, 0.0040078855, 0.0039210929, 0.0038320506,
-0.0037407955, 0.0036473659, 0.0035518011, 0.0034541416, 0.0033544293,
-0.0032527070, 0.0031490190, 0.0030434103, 0.0029359274, 0.0028266176,
-0.0027155294, 0.0026027124, 0.0024882172, 0.0023720954, 0.0022543995,
-0.0021351832, 0.0020145008, 0.0018924077, 0.0017689604, 0.0016442159,
-0.0015182322, 0.0013910681, 0.0012627833, 0.0011334381, 0.0010030935,
-0.0008718115, 0.0007396544, 0.0006066854, 0.0004729683, 0.0003385673,
-0.0002035473, 0.0000679738, -0.0000680874, -0.0002045699, -0.0003414068,
--0.0004785311, -0.0006158750, -0.0007533707, -0.0008909501, -0.0010285445,
--0.0011660854, -0.0013035038, -0.0014407305, -0.0015776965, -0.0017143323,
--0.0018505686, -0.0019863359, -0.0021215650, -0.0022561863, -0.0023901305,
--0.0025233286, -0.0026557114, -0.0027872101, -0.0029177559, -0.0030472806,
--0.0031757159, -0.0033029941, -0.0034290478, -0.0035538097, -0.0036772133,
--0.0037991925, -0.0039196815, -0.0040386151, -0.0041559288, -0.0042715586,
--0.0043854410, -0.0044975134, -0.0046077137, -0.0047159807, -0.0048222538,
--0.0049264734, -0.0050285805, -0.0051285171, -0.0052262260, -0.0053216511,
--0.0054147371, -0.0055054298, -0.0055936757, -0.0056794229, -0.0057626201,
--0.0058432173, -0.0059211657, -0.0059964175, -0.0060689262, -0.0061386464,
--0.0062055342, -0.0062695467, -0.0063306424, -0.0063887812, -0.0064439242,
--0.0064960339, -0.0065450743, -0.0065910108, -0.0066338102, -0.0066734406,
--0.0067098718, -0.0067430751, -0.0067730233, -0.0067996905, -0.0068230526,
--0.0068430871, -0.0068597730, -0.0068730909, -0.0068830230, -0.0068895532,
--0.0068926670, -0.0068923516, -0.0068885959, -0.0068813904, -0.0068707273,
--0.0068566006, -0.0068390059, -0.0068179406, -0.0067934038, -0.0067653964,
--0.0067339208, -0.0066989815, -0.0066605844, -0.0066187374, -0.0065734501,
--0.0065247337, -0.0064726014, -0.0064170679, -0.0063581499, -0.0062958655,
--0.0062302350, -0.0061612801, -0.0060890242, -0.0060134928, -0.0059347128,
--0.0058527128, -0.0057675233, -0.0056791763, -0.0055877057, -0.0054931469,
--0.0053955370, -0.0052949147, -0.0051913206, -0.0050847965, -0.0049753861,
--0.0048631346, -0.0047480887, -0.0046302969, -0.0045098089, -0.0043866761,
--0.0042609514, -0.0041326891, -0.0040019449, -0.0038687761, -0.0037332412,
--0.0035954003, -0.0034553146, -0.0033130467, -0.0031686607, -0.0030222217,
--0.0028737961, -0.0027234517, -0.0025712572, -0.0024172826, -0.0022615991,
--0.0021042788, -0.0019453950, -0.0017850218, -0.0016232347, -0.0014601097,
--0.0012957241, -0.0011301557, -0.0009634835, -0.0007957871, -0.0006271469,
--0.0004576441, -0.0002873606, -0.0001163788, 0.0000552181, 0.0002273465,
-0.0003999219, 0.0005728599, 0.0007460750, 0.0009194817, 0.0010929941,
-0.0012665257, 0.0014399901, 0.0016133002, 0.0017863692, 0.0019591096,
-0.0021314343, 0.0023032557, 0.0024744865, 0.0026450392, 0.0028148263,
-0.0029837607, 0.0031517551, 0.0033187227, 0.0034845767, 0.0036492306,
-0.0038125983, 0.0039745941, 0.0041351326, 0.0042941290, 0.0044514987,
-0.0046071580, 0.0047610235, 0.0049130126, 0.0050630433, 0.0052110344,
-0.0053569054, 0.0055005764, 0.0056419687, 0.0057810043, 0.0059176061,
-0.0060516980, 0.0061832049, 0.0063120528, 0.0064381688, 0.0065614810,
-0.0066819189, 0.0067994129, 0.0069138948, 0.0070252979, 0.0071335564,
-0.0072386063, 0.0073403846, 0.0074388300, 0.0075338826, 0.0076254839,
-0.0077135771, 0.0077981068, 0.0078790195, 0.0079562629, 0.0080297867,
-0.0080995421, 0.0081654823, 0.0082275620, 0.0082857377, 0.0083399679,
-0.0083902126, 0.0084364341, 0.0084785963, 0.0085166650, 0.0085506081,
-0.0085803953, 0.0086059984, 0.0086273912, 0.0086445494, 0.0086574509,
-0.0086660755, 0.0086704051, 0.0086704239, 0.0086661178, 0.0086574753,
-0.0086444866, 0.0086271443, 0.0086054431, 0.0085793798, 0.0085489535,
-0.0085141652, 0.0084750184, 0.0084315187, 0.0083836737, 0.0083314935,
-0.0082749902, 0.0082141782, 0.0081490739, 0.0080796962, 0.0080060659,
-0.0079282063, 0.0078461426, 0.0077599023, 0.0076695152, 0.0075750131,
-0.0074764299, 0.0073738019, 0.0072671672, 0.0071565665, 0.0070420421,
-0.0069236387, 0.0068014030, 0.0066753838, 0.0065456319, 0.0064122001,
-0.0062751433, 0.0061345183, 0.0059903840, 0.0058428010, 0.0056918321,
-0.0055375418, 0.0053799965, 0.0052192645, 0.0050554159, 0.0048885224,
-0.0047186578, 0.0045458972, 0.0043703178, 0.0041919982, 0.0040110187,
-0.0038274611, 0.0036414089, 0.0034529470, 0.0032621617, 0.0030691410,
-0.0028739740, 0.0026767514, 0.0024775651, 0.0022765082, 0.0020736751,
-0.0018691616, 0.0016630642, 0.0014554808, 0.0012465104, 0.0010362529,
-0.0008248091, 0.0006122807, 0.0003987705, 0.0001843818, -0.0000307810,
--0.0002466130, -0.0004630087, -0.0006798618, -0.0008970655, -0.0011145124,
--0.0013320949, -0.0015497047, -0.0017672333, -0.0019845719, -0.0022016113,
--0.0024182424, -0.0026343555, -0.0028498413, -0.0030645902, -0.0032784925,
--0.0034914390, -0.0037033203, -0.0039140271, -0.0041234507, -0.0043314824,
--0.0045380139, -0.0047429375, -0.0049461458, -0.0051475318, -0.0053469893,
--0.0055444126, -0.0057396967, -0.0059327375, -0.0061234313, -0.0063116757,
--0.0064973689, -0.0066804102, -0.0068606997, -0.0070381389, -0.0072126301,
--0.0073840769, -0.0075523841, -0.0077174578, -0.0078792054, -0.0080375355,
--0.0081923585, -0.0083435859, -0.0084911310, -0.0086349083, -0.0087748343,
--0.0089108270, -0.0090428060, -0.0091706929, -0.0092944108, -0.0094138849,
--0.0095290421, -0.0096398114, -0.0097461236, -0.0098479117, -0.0099451104,
--0.0100376569, -0.0101254902, -0.0102085518, -0.0102867850, -0.0103601356,
--0.0104285517, -0.0104919834, -0.0105503836, -0.0106037071, -0.0106519113,
--0.0106949562, -0.0107328038, -0.0107654191, -0.0107927692, -0.0108148239,
--0.0108315555, -0.0108429390, -0.0108489518, -0.0108495740, -0.0108447883,
--0.0108345802, -0.0108189376, -0.0107978513, -0.0107713147, -0.0107393238,
--0.0107018776, -0.0106589775, -0.0106106278, -0.0105568355, -0.0104976103,
--0.0104329648, -0.0103629142, -0.0102874763, -0.0102066721, -0.0101205249,
--0.0100290609, -0.0099323091, -0.0098303012, -0.0097230716, -0.0096106574,
--0.0094930984, -0.0093704371, -0.0092427188, -0.0091099913, -0.0089723051,
--0.0088297134, -0.0086822719, -0.0085300391, -0.0083730758, -0.0082114456,
--0.0080452144, -0.0078744508, -0.0076992258, -0.0075196129, -0.0073356879,
--0.0071475291, -0.0069552170, -0.0067588348, -0.0065584675, -0.0063542028,
--0.0061461303, -0.0059343419, -0.0057189316, -0.0054999956, -0.0052776322,
--0.0050519414, -0.0048230256, -0.0045909889, -0.0043559371, -0.0041179783,
--0.0038772221, -0.0036337797, -0.0033877643, -0.0031392906, -0.0028884748,
--0.0026354347, -0.0023802898, -0.0021231606, -0.0018641693, -0.0016034392,
--0.0013410951, -0.0010772627, -0.0008120690, -0.0005456421, -0.0002781110,
--0.0000096058, 0.0002597426, 0.0005298025, 0.0008004413, 0.0010715259,
-0.0013429225, 0.0016144965, 0.0018861131, 0.0021576369, 0.0024289322,
-0.0026998629, 0.0029702926, 0.0032400851, 0.0035091036, 0.0037772115,
-0.0040442724, 0.0043101496, 0.0045747069, 0.0048378082, 0.0050993177,
-0.0053591000, 0.0056170202, 0.0058729437, 0.0061267367, 0.0063782659,
-0.0066273989, 0.0068740040, 0.0071179501, 0.0073591075, 0.0075973470,
-0.0078325408, 0.0080645621, 0.0082932854, 0.0085185861, 0.0087403414,
-0.0089584296, 0.0091727305, 0.0093831254, 0.0095894973, 0.0097917307,
-0.0099897118, 0.0101833288, 0.0103724714, 0.0105570314, 0.0107369026,
-0.0109119807, 0.0110821634, 0.0112473506, 0.0114074445, 0.0115623494,
-0.0117119718, 0.0118562209, 0.0119950079, 0.0121282468, 0.0122558537,
-0.0123777476, 0.0124938499, 0.0126040849, 0.0127083792, 0.0128066625,
-0.0128988671, 0.0129849281, 0.0130647837, 0.0131383746, 0.0132056448,
-0.0132665411, 0.0133210134, 0.0133690146, 0.0134105007, 0.0134454309,
-0.0134737674, 0.0134954756, 0.0135105241, 0.0135188849, 0.0135205330,
-0.0135154468, 0.0135036081, 0.0134850017, 0.0134596160, 0.0134274427,
-0.0133884768, 0.0133427167, 0.0132901641, 0.0132308244, 0.0131647059,
-0.0130918209, 0.0130121845, 0.0129258157, 0.0128327367, 0.0127329732,
-0.0126265542, 0.0125135122, 0.0123938831, 0.0122677061, 0.0121350239,
-0.0119958827, 0.0118503317, 0.0116984238, 0.0115402150, 0.0113757647,
-0.0112051357, 0.0110283940, 0.0108456087, 0.0106568524, 0.0104622007,
-0.0102617324, 0.0100555296, 0.0098436773, 0.0096262638, 0.0094033802,
-0.0091751208, 0.0089415828, 0.0087028663, 0.0084590744, 0.0082103130,
-0.0079566907, 0.0076983191, 0.0074353122, 0.0071677869, 0.0068958626,
-0.0066196614, 0.0063393077, 0.0060549285, 0.0057666532, 0.0054746135,
-0.0051789434, 0.0048797791, 0.0045772590, 0.0042715235, 0.0039627152,
-0.0036509786, 0.0033364600, 0.0030193077, 0.0026996717, 0.0023777036,
-0.0020535569, 0.0017273863, 0.0013993484, 0.0010696008, 0.0007383027,
-0.0004056145, 0.0000716978, -0.0002632848, -0.0005991694, -0.0009357916,
--0.0012729856, -0.0016105852, -0.0019484233, -0.0022863322, -0.0026241437,
--0.0029616890, -0.0032987991, -0.0036353045, -0.0039710357, -0.0043058228,
--0.0046394962, -0.0049718859, -0.0053028224, -0.0056321361, -0.0059596580,
--0.0062852192, -0.0066086514, -0.0069297868, -0.0072484582, -0.0075644993,
--0.0078777443, -0.0081880284, -0.0084951880, -0.0087990603, -0.0090994836,
--0.0093962976, -0.0096893433, -0.0099784629, -0.0102635002, -0.0105443006,
--0.0108207111, -0.0110925803, -0.0113597589, -0.0116220991, -0.0118794553,
--0.0121316840, -0.0123786435, -0.0126201946, -0.0128562002, -0.0130865257,
--0.0133110387, -0.0135296094, -0.0137421107, -0.0139484179, -0.0141484092,
--0.0143419654, -0.0145289703, -0.0147093105, -0.0148828756, -0.0150495583,
--0.0152092543, -0.0153618625, -0.0155072851, -0.0156454275, -0.0157761985,
--0.0158995102, -0.0160152781, -0.0161234215, -0.0162238629, -0.0163165287,
--0.0164013487, -0.0164782565, -0.0165471894, -0.0166080887, -0.0166608992,
--0.0167055697, -0.0167420530, -0.0167703057, -0.0167902885, -0.0168019658,
--0.0168053065, -0.0168002831, -0.0167868725, -0.0167650556, -0.0167348174,
--0.0166961471, -0.0166490381, -0.0165934878, -0.0165294981, -0.0164570748,
--0.0163762282, -0.0162869726, -0.0161893267, -0.0160833133, -0.0159689596,
--0.0158462969, -0.0157153607, -0.0155761910, -0.0154288318, -0.0152733313,
--0.0151097420, -0.0149381205, -0.0147585277, -0.0145710286, -0.0143756923,
--0.0141725921, -0.0139618053, -0.0137434133, -0.0135175016, -0.0132841597,
--0.0130434809, -0.0127955627, -0.0125405063, -0.0122784169, -0.0120094035,
--0.0117335789, -0.0114510595, -0.0111619655, -0.0108664208, -0.0105645529,
--0.0102564926, -0.0099423745, -0.0096223365, -0.0092965198, -0.0089650690,
--0.0086281320, -0.0082858597, -0.0079384063, -0.0075859290, -0.0072285880,
--0.0068665463, -0.0064999700, -0.0061290276, -0.0057538906, -0.0053747331,
--0.0049917315, -0.0046050648, -0.0042149145, -0.0038214642, -0.0034248998,
--0.0030254092, -0.0026231826, -0.0022184119, -0.0018112910, -0.0014020154,
--0.0009907824, -0.0005777908, -0.0001632411, 0.0002526650, 0.0006697246,
-0.0010877333, 0.0015064860, 0.0019257762, 0.0023453967, 0.0027651394,
-0.0031847958, 0.0036041564, 0.0040230114, 0.0044411507, 0.0048583636,
-0.0052744396, 0.0056891678, 0.0061023376, 0.0065137383, 0.0069231595,
-0.0073303912, 0.0077352238, 0.0081374483, 0.0085368563, 0.0089332402,
-0.0093263932, 0.0097161095, 0.0101021845, 0.0104844146, 0.0108625976,
-0.0112365327, 0.0116060206, 0.0119708635, 0.0123308655, 0.0126858322,
-0.0130355714, 0.0133798928, 0.0137186083, 0.0140515319, 0.0143784798,
-0.0146992710, 0.0150137267, 0.0153216706, 0.0156229295, 0.0159173327,
-0.0162047124, 0.0164849039, 0.0167577456, 0.0170230788, 0.0172807484,
-0.0175306024, 0.0177724922, 0.0180062730, 0.0182318033, 0.0184489453,
-0.0186575650, 0.0188575324, 0.0190487212, 0.0192310091, 0.0194042780,
-0.0195684137, 0.0197233063, 0.0198688503, 0.0200049443, 0.0201314915,
-0.0202483994, 0.0203555801, 0.0204529502, 0.0205404311, 0.0206179485,
-0.0206854333, 0.0207428209, 0.0207900516, 0.0208270705, 0.0208538278,
-0.0208702784, 0.0208763824, 0.0208721048, 0.0208574158, 0.0208322904,
-0.0207967092, 0.0207506574, 0.0206941258, 0.0206271102, 0.0205496115,
-0.0204616360, 0.0203631952, 0.0202543057, 0.0201349897, 0.0200052742,
-0.0198651918, 0.0197147802, 0.0195540825, 0.0193831468, 0.0192020266,
-0.0190107807, 0.0188094731, 0.0185981728, 0.0183769543, 0.0181458969,
-0.0179050854, 0.0176546096, 0.0173945641, 0.0171250491, 0.0168461693,
-0.0165580347, 0.0162607600, 0.0159544652, 0.0156392747, 0.0153153180,
-0.0149827292, 0.0146416472, 0.0142922156, 0.0139345826, 0.0135689006,
-0.0131953271, 0.0128140234, 0.0124251554, 0.0120288935, 0.0116254119,
-0.0112148892, 0.0107975079, 0.0103734546, 0.0099429197, 0.0095060974,
-0.0090631859, 0.0086143866, 0.0081599047, 0.0076999490, 0.0072347313,
-0.0067644670, 0.0062893745, 0.0058096753, 0.0053255940, 0.0048373579,
-0.0043451972, 0.0038493447, 0.0033500357, 0.0028475082, 0.0023420022,
-0.0018337601, 0.0013230264, 0.0008100476, 0.0002950720, -0.0002216501,
--0.0007398671, -0.0012593256, -0.0017797709, -0.0023009471, -0.0028225970,
--0.0033444625, -0.0038662845, -0.0043878030, -0.0049087577, -0.0054288875,
--0.0059479308, -0.0064656261, -0.0069817115, -0.0074959251, -0.0080080052,
--0.0085176902, -0.0090247190, -0.0095288312, -0.0100297665, -0.0105272660,
--0.0110210713, -0.0115109251, -0.0119965714, -0.0124777553, -0.0129542235,
--0.0134257242, -0.0138920072, -0.0143528243, -0.0148079291, -0.0152570773,
--0.0157000268, -0.0161365379, -0.0165663733, -0.0169892981, -0.0174050805,
--0.0178134913, -0.0182143041, -0.0186072958, -0.0189922466, -0.0193689396,
--0.0197371617, -0.0200967031, -0.0204473579, -0.0207889239, -0.0211212026,
--0.0214439997, -0.0217571249, -0.0220603922, -0.0223536199, -0.0226366307,
--0.0229092517, -0.0231713149, -0.0234226568, -0.0236631188, -0.0238925473,
--0.0241107934, -0.0243177136, -0.0245131696, -0.0246970280, -0.0248691612,
--0.0250294468, -0.0251777677, -0.0253140129, -0.0254380765, -0.0255498588,
--0.0256492655, -0.0257362083, -0.0258106050, -0.0258723791, -0.0259214603,
--0.0259577843, -0.0259812930, -0.0259919344, -0.0259896629, -0.0259744389,
--0.0259462294, -0.0259050075, -0.0258507529, -0.0257834515, -0.0257030959,
--0.0256096849, -0.0255032239, -0.0253837247, -0.0252512059, -0.0251056924,
--0.0249472155, -0.0247758133, -0.0245915303, -0.0243944177, -0.0241845329,
--0.0239619403, -0.0237267103, -0.0234789202, -0.0232186535, -0.0229460004,
--0.0226610575, -0.0223639275, -0.0220547199, -0.0217335503, -0.0214005407,
--0.0210558192, -0.0206995203, -0.0203317846, -0.0199527589, -0.0195625960,
--0.0191614546, -0.0187494996, -0.0183269017, -0.0178938372, -0.0174504885,
--0.0169970434, -0.0165336956, -0.0160606440, -0.0155780931, -0.0150862529,
--0.0145853384, -0.0140755700, -0.0135571731, -0.0130303781, -0.0124954204,
--0.0119525400, -0.0114019817, -0.0108439950, -0.0102788338, -0.0097067561,
--0.0091280246, -0.0085429059, -0.0079516706, -0.0073545932, -0.0067519520,
--0.0061440290, -0.0055311097, -0.0049134828, -0.0042914406, -0.0036652782,
--0.0030352938, -0.0024017885, -0.0017650660, -0.0011254327, -0.0004831972,
-0.0001613293, 0.0008078339, 0.0014560012, 0.0021055145, 0.0027560551,
-0.0034073028, 0.0040589362, 0.0047106324, 0.0053620678, 0.0060129176,
-0.0066628564, 0.0073115581, 0.0079586963, 0.0086039444, 0.0092469753,
-0.0098874625, 0.0105250794, 0.0111594997, 0.0117903979, 0.0124174490,
-0.0130403290, 0.0136587149, 0.0142722848, 0.0148807183, 0.0154836965,
-0.0160809021, 0.0166720197, 0.0172567358, 0.0178347393, 0.0184057213,
-0.0189693753, 0.0195253977, 0.0200734874, 0.0206133465, 0.0211446801,
-0.0216671967, 0.0221806081, 0.0226846298, 0.0231789810, 0.0236633848,
-0.0241375683, 0.0246012629, 0.0250542041, 0.0254961322, 0.0259267919,
-0.0263459327, 0.0267533090, 0.0271486805, 0.0275318116, 0.0279024723,
-0.0282604381, 0.0286054900, 0.0289374145, 0.0292560042, 0.0295610575,
-0.0298523789, 0.0301297791, 0.0303930749, 0.0306420898, 0.0308766536,
-0.0310966027, 0.0313017804, 0.0314920367, 0.0316672284, 0.0318272194,
-0.0319718809, 0.0321010909, 0.0322147348, 0.0323127056, 0.0323949034,
-0.0324612358, 0.0325116182, 0.0325459735, 0.0325642322, 0.0325663326,
-0.0325522210, 0.0325218512, 0.0324751853, 0.0324121930, 0.0323328523,
-0.0322371490, 0.0321250770, 0.0319966384, 0.0318518433, 0.0316907100,
-0.0315132649, 0.0313195427, 0.0311095860, 0.0308834460, 0.0306411817,
-0.0303828605, 0.0301085578, 0.0298183574, 0.0295123510, 0.0291906387,
-0.0288533284, 0.0285005363, 0.0281323866, 0.0277490115, 0.0273505511,
-0.0269371536, 0.0265089750, 0.0260661791, 0.0256089375, 0.0251374295,
-0.0246518421, 0.0241523699, 0.0236392150, 0.0231125868, 0.0225727023,
-0.0220197857, 0.0214540682, 0.0208757885, 0.0202851918, 0.0196825308,
-0.0190680644, 0.0184420586, 0.0178047860, 0.0171565254, 0.0164975622,
-0.0158281880, 0.0151487004, 0.0144594032, 0.0137606059, 0.0130526237,
-0.0123357777, 0.0116103940, 0.0108768043, 0.0101353455, 0.0093863594,
-0.0086301925, 0.0078671964, 0.0070977270, 0.0063221446, 0.0055408137,
-0.0047541030, 0.0039623850, 0.0031660360, 0.0023654356, 0.0015609671,
-0.0007530169, -0.0000580258, -0.0008717687, -0.0016878170, -0.0025057733,
--0.0033252381, -0.0041458096, -0.0049670844, -0.0057886571, -0.0066101210,
--0.0074310679, -0.0082510887, -0.0090697732, -0.0098867106, -0.0107014895,
--0.0115136982, -0.0123229249, -0.0131287579, -0.0139307858, -0.0147285976,
--0.0155217831, -0.0163099329, -0.0170926389, -0.0178694941, -0.0186400931,
--0.0194040323, -0.0201609098, -0.0209103260, -0.0216518837, -0.0223851881,
--0.0231098472, -0.0238254719, -0.0245316762, -0.0252280776, -0.0259142971,
--0.0265899594, -0.0272546930, -0.0279081308, -0.0285499099, -0.0291796719,
--0.0297970631, -0.0304017349, -0.0309933435, -0.0315715507, -0.0321360235,
--0.0326864346, -0.0332224626, -0.0337437921, -0.0342501139, -0.0347411250,
--0.0352165291, -0.0356760366, -0.0361193646, -0.0365462373, -0.0369563861,
--0.0373495498, -0.0377254745, -0.0380839142, -0.0384246304, -0.0387473928,
--0.0390519790, -0.0393381748, -0.0396057745, -0.0398545807, -0.0400844047,
--0.0402950665, -0.0404863949, -0.0406582277, -0.0408104118, -0.0409428031,
--0.0410552669, -0.0411476780, -0.0412199204, -0.0412718878, -0.0413034835,
--0.0413146206, -0.0413052219, -0.0412752200, -0.0412245577, -0.0411531875,
--0.0410610721, -0.0409481843, -0.0408145071, -0.0406600336, -0.0404847672,
--0.0402887216, -0.0400719206, -0.0398343986, -0.0395762002, -0.0392973804,
--0.0389980046, -0.0386781484, -0.0383378980, -0.0379773497, -0.0375966105,
--0.0371957974, -0.0367750379, -0.0363344698, -0.0358742410, -0.0353945098,
--0.0348954445, -0.0343772237, -0.0338400360, -0.0332840800, -0.0327095642,
--0.0321167073, -0.0315057374, -0.0308768926, -0.0302304205, -0.0295665785,
--0.0288856333, -0.0281878610, -0.0274735469, -0.0267429858, -0.0259964811,
--0.0252343455, -0.0244569004, -0.0236644758, -0.0228574104, -0.0220360513,
--0.0212007538, -0.0203518815, -0.0194898058, -0.0186149061, -0.0177275694,
--0.0168281903, -0.0159171706, -0.0149949194, -0.0140618528, -0.0131183937,
--0.0121649716, -0.0112020226, -0.0102299890, -0.0092493190, -0.0082604669,
--0.0072638927, -0.0062600617, -0.0052494445, -0.0042325168, -0.0032097591,
--0.0021816566, -0.0011486988, -0.0001113794, 0.0009298040, 0.0019743499,
-0.0030217536, 0.0040715069, 0.0051230987, 0.0061760151, 0.0072297398,
-0.0082837539, 0.0093375368, 0.0103905658, 0.0114423169, 0.0124922647,
-0.0135398828, 0.0145846438, 0.0156260201, 0.0166634836, 0.0176965062,
-0.0187245601, 0.0197471179, 0.0207636531, 0.0217736400, 0.0227765544,
-0.0237718735, 0.0247590762, 0.0257376438, 0.0267070595, 0.0276668094,
-0.0286163823, 0.0295552701, 0.0304829681, 0.0313989751, 0.0323027939,
-0.0331939315, 0.0340718990, 0.0349362125, 0.0357863927, 0.0366219656,
-0.0374424626, 0.0382474207, 0.0390363829, 0.0398088980, 0.0405645217,
-0.0413028159, 0.0420233496, 0.0427256986, 0.0434094465, 0.0440741841,
-0.0447195100, 0.0453450309, 0.0459503619, 0.0465351261, 0.0470989558,
-0.0476414918, 0.0481623841, 0.0486612920, 0.0491378843, 0.0495918395,
-0.0500228460, 0.0504306021, 0.0508148166, 0.0511752086, 0.0515115078,
-0.0518234548, 0.0521108010, 0.0523733090, 0.0526107526, 0.0528229172,
-0.0530095996, 0.0531706083, 0.0533057638, 0.0534148984, 0.0534978568,
-0.0535544955, 0.0535846837, 0.0535883030, 0.0535652475, 0.0535154239,
-0.0534387518, 0.0533351636, 0.0532046046, 0.0530470330, 0.0528624204,
-0.0526507512, 0.0524120231, 0.0521462471, 0.0518534476, 0.0515336620,
-0.0511869413, 0.0508133500, 0.0504129657, 0.0499858797, 0.0495321967,
-0.0490520346, 0.0485455250, 0.0480128128, 0.0474540563, 0.0468694272,
-0.0462591107, 0.0456233049, 0.0449622216, 0.0442760856, 0.0435651348,
-0.0428296204, 0.0420698064, 0.0412859698, 0.0404784006, 0.0396474015,
-0.0387932877, 0.0379163872, 0.0370170403, 0.0360955999, 0.0351524307,
-0.0341879100, 0.0332024265, 0.0321963813, 0.0311701866, 0.0301242667,
-0.0290590567, 0.0279750034, 0.0268725642, 0.0257522075, 0.0246144125,
-0.0234596687, 0.0222884760, 0.0211013441, 0.0198987930, 0.0186813520,
-0.0174495601, 0.0162039652, 0.0149451245, 0.0136736037, 0.0123899774,
-0.0110948280, 0.0097887463, 0.0084723306, 0.0071461869, 0.0058109285,
-0.0044671755, 0.0031155547, 0.0017566996, 0.0003912497, -0.0009801497,
--0.0023568476, -0.0037381876, -0.0051235086, -0.0065121445, -0.0079034250,
--0.0092966754, -0.0106912177, -0.0120863699, -0.0134814472, -0.0148757617,
--0.0162686232, -0.0176593392, -0.0190472153, -0.0204315554, -0.0218116625,
--0.0231868384, -0.0245563845, -0.0259196020, -0.0272757920, -0.0286242563,
--0.0299642972, -0.0312952185, -0.0326163250, -0.0339269237, -0.0352263234,
--0.0365138356, -0.0377887747, -0.0390504580, -0.0402982064, -0.0415313447,
--0.0427492019, -0.0439511115, -0.0451364118, -0.0463044463, -0.0474545642,
--0.0485861203, -0.0496984759, -0.0507909987, -0.0518630632, -0.0529140513,
--0.0539433522, -0.0549503631, -0.0559344894, -0.0568951448, -0.0578317521,
--0.0587437430, -0.0596305587, -0.0604916501, -0.0613264784, -0.0621345148,
--0.0629152414, -0.0636681511, -0.0643927482, -0.0650885482, -0.0657550788,
--0.0663918795, -0.0669985022, -0.0675745116, -0.0681194850, -0.0686330131,
--0.0691146997, -0.0695641626, -0.0699810331, -0.0703649569, -0.0707155940,
--0.0710326189, -0.0713157209, -0.0715646043, -0.0717789887, -0.0719586091,
--0.0721032160, -0.0722125759, -0.0722864709, -0.0723246997, -0.0723270771,
--0.0722934344, -0.0722236195, -0.0721174972, -0.0719749490, -0.0717958738,
--0.0715801873, -0.0713278227, -0.0710387307, -0.0707128793, -0.0703502542,
--0.0699508588, -0.0695147141, -0.0690418592, -0.0685323510, -0.0679862642,
--0.0674036916, -0.0667847442, -0.0661295508, -0.0654382585, -0.0647110323,
--0.0639480554, -0.0631495291, -0.0623156729, -0.0614467242, -0.0605429384,
--0.0596045891, -0.0586319676, -0.0576253834, -0.0565851636, -0.0555116532,
--0.0544052146, -0.0532662283, -0.0520950917, -0.0508922201, -0.0496580458,
--0.0483930182, -0.0470976040, -0.0457722864, -0.0444175657, -0.0430339585,
--0.0416219979, -0.0401822332, -0.0387152298, -0.0372215690, -0.0357018476,
--0.0341566780, -0.0325866877, -0.0309925194, -0.0293748304, -0.0277342927,
--0.0260715924, -0.0243874299, -0.0226825192, -0.0209575878, -0.0192133766,
--0.0174506393, -0.0156701424, -0.0138726645, -0.0120589966, -0.0102299412,
--0.0083863124, -0.0065289352, -0.0046586456, -0.0027762899, -0.0008827244,
-0.0010211847, 0.0029345619, 0.0048565227, 0.0067861739, 0.0087226141,
-0.0106649339, 0.0126122165, 0.0145635380, 0.0165179676, 0.0184745685,
-0.0204323977, 0.0223905068, 0.0243479423, 0.0263037461, 0.0282569558,
-0.0302066051, 0.0321517244, 0.0340913411, 0.0360244802, 0.0379501644,
-0.0398674149, 0.0417752518, 0.0436726943, 0.0455587612, 0.0474324718,
-0.0492928457, 0.0511389038, 0.0529696683, 0.0547841636, 0.0565814165,
-0.0583604566, 0.0601203169, 0.0618600345, 0.0635786504, 0.0652752107,
-0.0669487665, 0.0685983747, 0.0702230985, 0.0718220074, 0.0733941783,
-0.0749386954, 0.0764546512, 0.0779411463, 0.0793972906, 0.0808222031,
-0.0822150126, 0.0835748586, 0.0849008908, 0.0861922705, 0.0874481703,
-0.0886677751, 0.0898502822, 0.0909949018, 0.0921008575, 0.0931673867,
-0.0941937410, 0.0951791867, 0.0961230049, 0.0970244924, 0.0978829617,
-0.0986977416, 0.0994681776, 0.1001936321, 0.1008734849, 0.1015071339,
-0.1020939947, 0.1026335017, 0.1031251081, 0.1035682863, 0.1039625284,
-0.1043073461, 0.1046022718, 0.1048468579, 0.1050406782, 0.1051833274,
-0.1052744216, 0.1053135989, 0.1053005193, 0.1052348653, 0.1051163417,
-0.1049446764, 0.1047196204, 0.1044409479, 0.1041084567, 0.1037219686,
-0.1032813291, 0.1027864082, 0.1022371001, 0.1016333237, 0.1009750227,
-0.1002621657, 0.0994947463, 0.0986727834, 0.0977963213, 0.0968654299,
-0.0958802044, 0.0948407661, 0.0937472617, 0.0925998642, 0.0913987723,
-0.0901442107, 0.0888364304, 0.0874757082, 0.0860623475, 0.0845966773,
-0.0830790532, 0.0815098568, 0.0798894959, 0.0782184043, 0.0764970420,
-0.0747258951, 0.0729054754, 0.0710363210, 0.0691189955, 0.0671540883,
-0.0651422145, 0.0630840147, 0.0609801548, 0.0588313260, 0.0566382445,
-0.0544016516, 0.0521223131, 0.0498010197, 0.0474385862, 0.0450358517,
-0.0425936791, 0.0401129553, 0.0375945904, 0.0350395180, 0.0324486944,
-0.0298230988, 0.0271637328, 0.0244716200, 0.0217478060, 0.0189933578,
-0.0162093637, 0.0133969326, 0.0105571942, 0.0076912982, 0.0048004142,
-0.0018857311, -0.0010515431, -0.0040101818, -0.0069889400, -0.0099865552,
--0.0130017470, -0.0160332186, -0.0190796561, -0.0221397300, -0.0252120948,
--0.0282953900, -0.0313882404, -0.0344892565, -0.0375970350, -0.0407101596,
--0.0438272010, -0.0469467180, -0.0500672573, -0.0531873547, -0.0563055352,
--0.0594203139, -0.0625301961, -0.0656336781, -0.0687292478, -0.0718153853,
--0.0748905633, -0.0779532475, -0.0810018979, -0.0840349685, -0.0870509084,
--0.0900481623, -0.0930251712, -0.0959803727, -0.0989122018, -0.1018190916,
--0.1046994738, -0.1075517791, -0.1103744383, -0.1131658825, -0.1159245439,
--0.1186488564, -0.1213372563, -0.1239881827, -0.1266000784, -0.1291713903,
--0.1317005702, -0.1341860754, -0.1366263692, -0.1390199217, -0.1413652104,
--0.1436607206, -0.1459049465, -0.1480963913, -0.1502335681, -0.1523150008,
--0.1543392240, -0.1563047842, -0.1582102405, -0.1600541646, -0.1618351421,
--0.1635517727, -0.1652026708, -0.1667864664, -0.1683018055, -0.1697473506,
--0.1711217816, -0.1724237959, -0.1736521096, -0.1748054577, -0.1758825945,
--0.1768822946, -0.1778033533, -0.1786445870, -0.1794048340, -0.1800829546,
--0.1806778324, -0.1811883740, -0.1816135100, -0.1819521956, -0.1822034106,
--0.1823661605, -0.1824394765, -0.1824224162, -0.1823140643, -0.1821135324,
--0.1818199604, -0.1814325160, -0.1809503957, -0.1803728252, -0.1796990596,
--0.1789283840, -0.1780601136, -0.1770935947, -0.1760282042, -0.1748633509,
--0.1735984751, -0.1722330493, -0.1707665787, -0.1691986010, -0.1675286871,
--0.1657564415, -0.1638815022, -0.1619035412, -0.1598222647, -0.1576374137,
--0.1553487634, -0.1529561244, -0.1504593422, -0.1478582978, -0.1451529077,
--0.1423431241, -0.1394289353, -0.1364103652, -0.1332874743, -0.1300603591,
--0.1267291528, -0.1232940247, -0.1197551811, -0.1161128647, -0.1123673549,
--0.1085189679, -0.1045680566, -0.1005150108, -0.0963602570, -0.0921042585,
--0.0877475152, -0.0832905640, -0.0787339781, -0.0740783674, -0.0693243784,
--0.0644726937, -0.0595240325, -0.0544791499, -0.0493388371, -0.0441039212,
--0.0387752649, -0.0333537664, -0.0278403591, -0.0222360119, -0.0165417281,
--0.0107585458, -0.0048875377, 0.0010701897, 0.0071134959, 0.0132412068,
-0.0194521151, 0.0257449807, 0.0321185306, 0.0385714598, 0.0451024313,
-0.0517100765, 0.0583929957, 0.0651497585, 0.0719789041, 0.0788789416,
-0.0858483508, 0.0928855823, 0.0999890582, 0.1071571724, 0.1143882911,
-0.1216807533, 0.1290328713, 0.1364429314, 0.1439091941, 0.1514298947,
-0.1590032442, 0.1666274291, 0.1743006130, 0.1820209363, 0.1897865170,
-0.1975954515, 0.2054458153, 0.2133356630, 0.2212630296, 0.2292259307,
-0.2372223633, 0.2452503065, 0.2533077219, 0.2613925546, 0.2695027336,
-0.2776361727, 0.2857907708, 0.2939644130, 0.3021549712, 0.3103603046,
-0.3185782607, 0.3268066755, 0.3350433750, 0.3432861752, 0.3515328833,
-0.3597812980, 0.3680292108, 0.3762744061, 0.3845146625, 0.3927477532,
-0.4009714470, 0.4091835086, 0.4173817001, 0.4255637810, 0.4337275094,
-0.4418706427, 0.4499909381, 0.4580861540, 0.4661540499, 0.4741923878,
-0.4821989328, 0.4901714538, 0.4981077244, 0.5060055234, 0.5138626359,
-0.5216768538, 0.5294459766, 0.5371678125, 0.5448401785, 0.5524609020,
-0.5600278206, 0.5675387836, 0.5749916526, 0.5823843019, 0.5897146196,
-0.5969805081, 0.6041798851, 0.6113106841, 0.6183708551, 0.6253583655,
-0.6322712007, 0.6391073649, 0.6458648816, 0.6525417945, 0.6591361680,
-0.6656460881, 0.6720696629, 0.6784050234, 0.6846503240, 0.6908037433,
-0.6968634846, 0.7028277766, 0.7086948742, 0.7144630588, 0.7201306391,
-0.7256959517, 0.7311573616, 0.7365132628, 0.7417620790, 0.7469022639,
-0.7519323022, 0.7568507094, 0.7616560333, 0.7663468534, 0.7709217826,
-0.7753794666, 0.7797185851, 0.7839378519, 0.7880360158, 0.7920118604,
-0.7958642049, 0.7995919047, 0.8031938516, 0.8066689739, 0.8100162374,
-0.8132346454, 0.8163232389, 0.8192810973, 0.8221073386, 0.8248011197,
-0.8273616366, 0.8297881248, 0.8320798597, 0.8342361565, 0.8362563709,
-0.8381398988, 0.8398861771, 0.8414946834, 0.8429649364, 0.8442964963,
-0.8454889644, 0.8465419838, 0.8474552392, 0.8482284572, 0.8488614061,
-0.8493538965, 0.8497057807, 0.8499169534, 0.8499873514, 0.8499169534,
-0.8497057807, 0.8493538965, 0.8488614061, 0.8482284572, 0.8474552392,
-0.8465419838, 0.8454889644, 0.8442964963, 0.8429649364, 0.8414946834,
-0.8398861771, 0.8381398988, 0.8362563709, 0.8342361565, 0.8320798597,
-0.8297881248, 0.8273616366, 0.8248011197, 0.8221073386, 0.8192810973,
-0.8163232389, 0.8132346454, 0.8100162374, 0.8066689739, 0.8031938516,
-0.7995919047, 0.7958642049, 0.7920118604, 0.7880360158, 0.7839378519,
-0.7797185851, 0.7753794666, 0.7709217826, 0.7663468534, 0.7616560333,
-0.7568507094, 0.7519323022, 0.7469022639, 0.7417620790, 0.7365132628,
-0.7311573616, 0.7256959517, 0.7201306391, 0.7144630588, 0.7086948742,
-0.7028277766, 0.6968634846, 0.6908037433, 0.6846503240, 0.6784050234,
-0.6720696629, 0.6656460881, 0.6591361680, 0.6525417945, 0.6458648816,
-0.6391073649, 0.6322712007, 0.6253583655, 0.6183708551, 0.6113106841,
-0.6041798851, 0.5969805081, 0.5897146196, 0.5823843019, 0.5749916526,
-0.5675387836, 0.5600278206, 0.5524609020, 0.5448401785, 0.5371678125,
-0.5294459766, 0.5216768538, 0.5138626359, 0.5060055234, 0.4981077244,
-0.4901714538, 0.4821989328, 0.4741923878, 0.4661540499, 0.4580861540,
-0.4499909381, 0.4418706427, 0.4337275094, 0.4255637810, 0.4173817001,
-0.4091835086, 0.4009714470, 0.3927477532, 0.3845146625, 0.3762744061,
-0.3680292108, 0.3597812980, 0.3515328833, 0.3432861752, 0.3350433750,
-0.3268066755, 0.3185782607, 0.3103603046, 0.3021549712, 0.2939644130,
-0.2857907708, 0.2776361727, 0.2695027336, 0.2613925546, 0.2533077219,
-0.2452503065, 0.2372223633, 0.2292259307, 0.2212630296, 0.2133356630,
-0.2054458153, 0.1975954515, 0.1897865170, 0.1820209363, 0.1743006130,
-0.1666274291, 0.1590032442, 0.1514298947, 0.1439091941, 0.1364429314,
-0.1290328713, 0.1216807533, 0.1143882911, 0.1071571724, 0.0999890582,
-0.0928855823, 0.0858483508, 0.0788789416, 0.0719789041, 0.0651497585,
-0.0583929957, 0.0517100765, 0.0451024313, 0.0385714598, 0.0321185306,
-0.0257449807, 0.0194521151, 0.0132412068, 0.0071134959, 0.0010701897,
--0.0048875377, -0.0107585458, -0.0165417281, -0.0222360119, -0.0278403591,
--0.0333537664, -0.0387752649, -0.0441039212, -0.0493388371, -0.0544791499,
--0.0595240325, -0.0644726937, -0.0693243784, -0.0740783674, -0.0787339781,
--0.0832905640, -0.0877475152, -0.0921042585, -0.0963602570, -0.1005150108,
--0.1045680566, -0.1085189679, -0.1123673549, -0.1161128647, -0.1197551811,
--0.1232940247, -0.1267291528, -0.1300603591, -0.1332874743, -0.1364103652,
--0.1394289353, -0.1423431241, -0.1451529077, -0.1478582978, -0.1504593422,
--0.1529561244, -0.1553487634, -0.1576374137, -0.1598222647, -0.1619035412,
--0.1638815022, -0.1657564415, -0.1675286871, -0.1691986010, -0.1707665787,
--0.1722330493, -0.1735984751, -0.1748633509, -0.1760282042, -0.1770935947,
--0.1780601136, -0.1789283840, -0.1796990596, -0.1803728252, -0.1809503957,
--0.1814325160, -0.1818199604, -0.1821135324, -0.1823140643, -0.1824224162,
--0.1824394765, -0.1823661605, -0.1822034106, -0.1819521956, -0.1816135100,
--0.1811883740, -0.1806778324, -0.1800829546, -0.1794048340, -0.1786445870,
--0.1778033533, -0.1768822946, -0.1758825945, -0.1748054577, -0.1736521096,
--0.1724237959, -0.1711217816, -0.1697473506, -0.1683018055, -0.1667864664,
--0.1652026708, -0.1635517727, -0.1618351421, -0.1600541646, -0.1582102405,
--0.1563047842, -0.1543392240, -0.1523150008, -0.1502335681, -0.1480963913,
--0.1459049465, -0.1436607206, -0.1413652104, -0.1390199217, -0.1366263692,
--0.1341860754, -0.1317005702, -0.1291713903, -0.1266000784, -0.1239881827,
--0.1213372563, -0.1186488564, -0.1159245439, -0.1131658825, -0.1103744383,
--0.1075517791, -0.1046994738, -0.1018190916, -0.0989122018, -0.0959803727,
--0.0930251712, -0.0900481623, -0.0870509084, -0.0840349685, -0.0810018979,
--0.0779532475, -0.0748905633, -0.0718153853, -0.0687292478, -0.0656336781,
--0.0625301961, -0.0594203139, -0.0563055352, -0.0531873547, -0.0500672573,
--0.0469467180, -0.0438272010, -0.0407101596, -0.0375970350, -0.0344892565,
--0.0313882404, -0.0282953900, -0.0252120948, -0.0221397300, -0.0190796561,
--0.0160332186, -0.0130017470, -0.0099865552, -0.0069889400, -0.0040101818,
--0.0010515431, 0.0018857311, 0.0048004142, 0.0076912982, 0.0105571942,
-0.0133969326, 0.0162093637, 0.0189933578, 0.0217478060, 0.0244716200,
-0.0271637328, 0.0298230988, 0.0324486944, 0.0350395180, 0.0375945904,
-0.0401129553, 0.0425936791, 0.0450358517, 0.0474385862, 0.0498010197,
-0.0521223131, 0.0544016516, 0.0566382445, 0.0588313260, 0.0609801548,
-0.0630840147, 0.0651422145, 0.0671540883, 0.0691189955, 0.0710363210,
-0.0729054754, 0.0747258951, 0.0764970420, 0.0782184043, 0.0798894959,
-0.0815098568, 0.0830790532, 0.0845966773, 0.0860623475, 0.0874757082,
-0.0888364304, 0.0901442107, 0.0913987723, 0.0925998642, 0.0937472617,
-0.0948407661, 0.0958802044, 0.0968654299, 0.0977963213, 0.0986727834,
-0.0994947463, 0.1002621657, 0.1009750227, 0.1016333237, 0.1022371001,
-0.1027864082, 0.1032813291, 0.1037219686, 0.1041084567, 0.1044409479,
-0.1047196204, 0.1049446764, 0.1051163417, 0.1052348653, 0.1053005193,
-0.1053135989, 0.1052744216, 0.1051833274, 0.1050406782, 0.1048468579,
-0.1046022718, 0.1043073461, 0.1039625284, 0.1035682863, 0.1031251081,
-0.1026335017, 0.1020939947, 0.1015071339, 0.1008734849, 0.1001936321,
-0.0994681776, 0.0986977416, 0.0978829617, 0.0970244924, 0.0961230049,
-0.0951791867, 0.0941937410, 0.0931673867, 0.0921008575, 0.0909949018,
-0.0898502822, 0.0886677751, 0.0874481703, 0.0861922705, 0.0849008908,
-0.0835748586, 0.0822150126, 0.0808222031, 0.0793972906, 0.0779411463,
-0.0764546512, 0.0749386954, 0.0733941783, 0.0718220074, 0.0702230985,
-0.0685983747, 0.0669487665, 0.0652752107, 0.0635786504, 0.0618600345,
-0.0601203169, 0.0583604566, 0.0565814165, 0.0547841636, 0.0529696683,
-0.0511389038, 0.0492928457, 0.0474324718, 0.0455587612, 0.0436726943,
-0.0417752518, 0.0398674149, 0.0379501644, 0.0360244802, 0.0340913411,
-0.0321517244, 0.0302066051, 0.0282569558, 0.0263037461, 0.0243479423,
-0.0223905068, 0.0204323977, 0.0184745685, 0.0165179676, 0.0145635380,
-0.0126122165, 0.0106649339, 0.0087226141, 0.0067861739, 0.0048565227,
-0.0029345619, 0.0010211847, -0.0008827244, -0.0027762899, -0.0046586456,
--0.0065289352, -0.0083863124, -0.0102299412, -0.0120589966, -0.0138726645,
--0.0156701424, -0.0174506393, -0.0192133766, -0.0209575878, -0.0226825192,
--0.0243874299, -0.0260715924, -0.0277342927, -0.0293748304, -0.0309925194,
--0.0325866877, -0.0341566780, -0.0357018476, -0.0372215690, -0.0387152298,
--0.0401822332, -0.0416219979, -0.0430339585, -0.0444175657, -0.0457722864,
--0.0470976040, -0.0483930182, -0.0496580458, -0.0508922201, -0.0520950917,
--0.0532662283, -0.0544052146, -0.0555116532, -0.0565851636, -0.0576253834,
--0.0586319676, -0.0596045891, -0.0605429384, -0.0614467242, -0.0623156729,
--0.0631495291, -0.0639480554, -0.0647110323, -0.0654382585, -0.0661295508,
--0.0667847442, -0.0674036916, -0.0679862642, -0.0685323510, -0.0690418592,
--0.0695147141, -0.0699508588, -0.0703502542, -0.0707128793, -0.0710387307,
--0.0713278227, -0.0715801873, -0.0717958738, -0.0719749490, -0.0721174972,
--0.0722236195, -0.0722934344, -0.0723270771, -0.0723246997, -0.0722864709,
--0.0722125759, -0.0721032160, -0.0719586091, -0.0717789887, -0.0715646043,
--0.0713157209, -0.0710326189, -0.0707155940, -0.0703649569, -0.0699810331,
--0.0695641626, -0.0691146997, -0.0686330131, -0.0681194850, -0.0675745116,
--0.0669985022, -0.0663918795, -0.0657550788, -0.0650885482, -0.0643927482,
--0.0636681511, -0.0629152414, -0.0621345148, -0.0613264784, -0.0604916501,
--0.0596305587, -0.0587437430, -0.0578317521, -0.0568951448, -0.0559344894,
--0.0549503631, -0.0539433522, -0.0529140513, -0.0518630632, -0.0507909987,
--0.0496984759, -0.0485861203, -0.0474545642, -0.0463044463, -0.0451364118,
--0.0439511115, -0.0427492019, -0.0415313447, -0.0402982064, -0.0390504580,
--0.0377887747, -0.0365138356, -0.0352263234, -0.0339269237, -0.0326163250,
--0.0312952185, -0.0299642972, -0.0286242563, -0.0272757920, -0.0259196020,
--0.0245563845, -0.0231868384, -0.0218116625, -0.0204315554, -0.0190472153,
--0.0176593392, -0.0162686232, -0.0148757617, -0.0134814472, -0.0120863699,
--0.0106912177, -0.0092966754, -0.0079034250, -0.0065121445, -0.0051235086,
--0.0037381876, -0.0023568476, -0.0009801497, 0.0003912497, 0.0017566996,
-0.0031155547, 0.0044671755, 0.0058109285, 0.0071461869, 0.0084723306,
-0.0097887463, 0.0110948280, 0.0123899774, 0.0136736037, 0.0149451245,
-0.0162039652, 0.0174495601, 0.0186813520, 0.0198987930, 0.0211013441,
-0.0222884760, 0.0234596687, 0.0246144125, 0.0257522075, 0.0268725642,
-0.0279750034, 0.0290590567, 0.0301242667, 0.0311701866, 0.0321963813,
-0.0332024265, 0.0341879100, 0.0351524307, 0.0360955999, 0.0370170403,
-0.0379163872, 0.0387932877, 0.0396474015, 0.0404784006, 0.0412859698,
-0.0420698064, 0.0428296204, 0.0435651348, 0.0442760856, 0.0449622216,
-0.0456233049, 0.0462591107, 0.0468694272, 0.0474540563, 0.0480128128,
-0.0485455250, 0.0490520346, 0.0495321967, 0.0499858797, 0.0504129657,
-0.0508133500, 0.0511869413, 0.0515336620, 0.0518534476, 0.0521462471,
-0.0524120231, 0.0526507512, 0.0528624204, 0.0530470330, 0.0532046046,
-0.0533351636, 0.0534387518, 0.0535154239, 0.0535652475, 0.0535883030,
-0.0535846837, 0.0535544955, 0.0534978568, 0.0534148984, 0.0533057638,
-0.0531706083, 0.0530095996, 0.0528229172, 0.0526107526, 0.0523733090,
-0.0521108010, 0.0518234548, 0.0515115078, 0.0511752086, 0.0508148166,
-0.0504306021, 0.0500228460, 0.0495918395, 0.0491378843, 0.0486612920,
-0.0481623841, 0.0476414918, 0.0470989558, 0.0465351261, 0.0459503619,
-0.0453450309, 0.0447195100, 0.0440741841, 0.0434094465, 0.0427256986,
-0.0420233496, 0.0413028159, 0.0405645217, 0.0398088980, 0.0390363829,
-0.0382474207, 0.0374424626, 0.0366219656, 0.0357863927, 0.0349362125,
-0.0340718990, 0.0331939315, 0.0323027939, 0.0313989751, 0.0304829681,
-0.0295552701, 0.0286163823, 0.0276668094, 0.0267070595, 0.0257376438,
-0.0247590762, 0.0237718735, 0.0227765544, 0.0217736400, 0.0207636531,
-0.0197471179, 0.0187245601, 0.0176965062, 0.0166634836, 0.0156260201,
-0.0145846438, 0.0135398828, 0.0124922647, 0.0114423169, 0.0103905658,
-0.0093375368, 0.0082837539, 0.0072297398, 0.0061760151, 0.0051230987,
-0.0040715069, 0.0030217536, 0.0019743499, 0.0009298040, -0.0001113794,
--0.0011486988, -0.0021816566, -0.0032097591, -0.0042325168, -0.0052494445,
--0.0062600617, -0.0072638927, -0.0082604669, -0.0092493190, -0.0102299890,
--0.0112020226, -0.0121649716, -0.0131183937, -0.0140618528, -0.0149949194,
--0.0159171706, -0.0168281903, -0.0177275694, -0.0186149061, -0.0194898058,
--0.0203518815, -0.0212007538, -0.0220360513, -0.0228574104, -0.0236644758,
--0.0244569004, -0.0252343455, -0.0259964811, -0.0267429858, -0.0274735469,
--0.0281878610, -0.0288856333, -0.0295665785, -0.0302304205, -0.0308768926,
--0.0315057374, -0.0321167073, -0.0327095642, -0.0332840800, -0.0338400360,
--0.0343772237, -0.0348954445, -0.0353945098, -0.0358742410, -0.0363344698,
--0.0367750379, -0.0371957974, -0.0375966105, -0.0379773497, -0.0383378980,
--0.0386781484, -0.0389980046, -0.0392973804, -0.0395762002, -0.0398343986,
--0.0400719206, -0.0402887216, -0.0404847672, -0.0406600336, -0.0408145071,
--0.0409481843, -0.0410610721, -0.0411531875, -0.0412245577, -0.0412752200,
--0.0413052219, -0.0413146206, -0.0413034835, -0.0412718878, -0.0412199204,
--0.0411476780, -0.0410552669, -0.0409428031, -0.0408104118, -0.0406582277,
--0.0404863949, -0.0402950665, -0.0400844047, -0.0398545807, -0.0396057745,
--0.0393381748, -0.0390519790, -0.0387473928, -0.0384246304, -0.0380839142,
--0.0377254745, -0.0373495498, -0.0369563861, -0.0365462373, -0.0361193646,
--0.0356760366, -0.0352165291, -0.0347411250, -0.0342501139, -0.0337437921,
--0.0332224626, -0.0326864346, -0.0321360235, -0.0315715507, -0.0309933435,
--0.0304017349, -0.0297970631, -0.0291796719, -0.0285499099, -0.0279081308,
--0.0272546930, -0.0265899594, -0.0259142971, -0.0252280776, -0.0245316762,
--0.0238254719, -0.0231098472, -0.0223851881, -0.0216518837, -0.0209103260,
--0.0201609098, -0.0194040323, -0.0186400931, -0.0178694941, -0.0170926389,
--0.0163099329, -0.0155217831, -0.0147285976, -0.0139307858, -0.0131287579,
--0.0123229249, -0.0115136982, -0.0107014895, -0.0098867106, -0.0090697732,
--0.0082510887, -0.0074310679, -0.0066101210, -0.0057886571, -0.0049670844,
--0.0041458096, -0.0033252381, -0.0025057733, -0.0016878170, -0.0008717687,
--0.0000580258, 0.0007530169, 0.0015609671, 0.0023654356, 0.0031660360,
-0.0039623850, 0.0047541030, 0.0055408137, 0.0063221446, 0.0070977270,
-0.0078671964, 0.0086301925, 0.0093863594, 0.0101353455, 0.0108768043,
-0.0116103940, 0.0123357777, 0.0130526237, 0.0137606059, 0.0144594032,
-0.0151487004, 0.0158281880, 0.0164975622, 0.0171565254, 0.0178047860,
-0.0184420586, 0.0190680644, 0.0196825308, 0.0202851918, 0.0208757885,
-0.0214540682, 0.0220197857, 0.0225727023, 0.0231125868, 0.0236392150,
-0.0241523699, 0.0246518421, 0.0251374295, 0.0256089375, 0.0260661791,
-0.0265089750, 0.0269371536, 0.0273505511, 0.0277490115, 0.0281323866,
-0.0285005363, 0.0288533284, 0.0291906387, 0.0295123510, 0.0298183574,
-0.0301085578, 0.0303828605, 0.0306411817, 0.0308834460, 0.0311095860,
-0.0313195427, 0.0315132649, 0.0316907100, 0.0318518433, 0.0319966384,
-0.0321250770, 0.0322371490, 0.0323328523, 0.0324121930, 0.0324751853,
-0.0325218512, 0.0325522210, 0.0325663326, 0.0325642322, 0.0325459735,
-0.0325116182, 0.0324612358, 0.0323949034, 0.0323127056, 0.0322147348,
-0.0321010909, 0.0319718809, 0.0318272194, 0.0316672284, 0.0314920367,
-0.0313017804, 0.0310966027, 0.0308766536, 0.0306420898, 0.0303930749,
-0.0301297791, 0.0298523789, 0.0295610575, 0.0292560042, 0.0289374145,
-0.0286054900, 0.0282604381, 0.0279024723, 0.0275318116, 0.0271486805,
-0.0267533090, 0.0263459327, 0.0259267919, 0.0254961322, 0.0250542041,
-0.0246012629, 0.0241375683, 0.0236633848, 0.0231789810, 0.0226846298,
-0.0221806081, 0.0216671967, 0.0211446801, 0.0206133465, 0.0200734874,
-0.0195253977, 0.0189693753, 0.0184057213, 0.0178347393, 0.0172567358,
-0.0166720197, 0.0160809021, 0.0154836965, 0.0148807183, 0.0142722848,
-0.0136587149, 0.0130403290, 0.0124174490, 0.0117903979, 0.0111594997,
-0.0105250794, 0.0098874625, 0.0092469753, 0.0086039444, 0.0079586963,
-0.0073115581, 0.0066628564, 0.0060129176, 0.0053620678, 0.0047106324,
-0.0040589362, 0.0034073028, 0.0027560551, 0.0021055145, 0.0014560012,
-0.0008078339, 0.0001613293, -0.0004831972, -0.0011254327, -0.0017650660,
--0.0024017885, -0.0030352938, -0.0036652782, -0.0042914406, -0.0049134828,
--0.0055311097, -0.0061440290, -0.0067519520, -0.0073545932, -0.0079516706,
--0.0085429059, -0.0091280246, -0.0097067561, -0.0102788338, -0.0108439950,
--0.0114019817, -0.0119525400, -0.0124954204, -0.0130303781, -0.0135571731,
--0.0140755700, -0.0145853384, -0.0150862529, -0.0155780931, -0.0160606440,
--0.0165336956, -0.0169970434, -0.0174504885, -0.0178938372, -0.0183269017,
--0.0187494996, -0.0191614546, -0.0195625960, -0.0199527589, -0.0203317846,
--0.0206995203, -0.0210558192, -0.0214005407, -0.0217335503, -0.0220547199,
--0.0223639275, -0.0226610575, -0.0229460004, -0.0232186535, -0.0234789202,
--0.0237267103, -0.0239619403, -0.0241845329, -0.0243944177, -0.0245915303,
--0.0247758133, -0.0249472155, -0.0251056924, -0.0252512059, -0.0253837247,
--0.0255032239, -0.0256096849, -0.0257030959, -0.0257834515, -0.0258507529,
--0.0259050075, -0.0259462294, -0.0259744389, -0.0259896629, -0.0259919344,
--0.0259812930, -0.0259577843, -0.0259214603, -0.0258723791, -0.0258106050,
--0.0257362083, -0.0256492655, -0.0255498588, -0.0254380765, -0.0253140129,
--0.0251777677, -0.0250294468, -0.0248691612, -0.0246970280, -0.0245131696,
--0.0243177136, -0.0241107934, -0.0238925473, -0.0236631188, -0.0234226568,
--0.0231713149, -0.0229092517, -0.0226366307, -0.0223536199, -0.0220603922,
--0.0217571249, -0.0214439997, -0.0211212026, -0.0207889239, -0.0204473579,
--0.0200967031, -0.0197371617, -0.0193689396, -0.0189922466, -0.0186072958,
--0.0182143041, -0.0178134913, -0.0174050805, -0.0169892981, -0.0165663733,
--0.0161365379, -0.0157000268, -0.0152570773, -0.0148079291, -0.0143528243,
--0.0138920072, -0.0134257242, -0.0129542235, -0.0124777553, -0.0119965714,
--0.0115109251, -0.0110210713, -0.0105272660, -0.0100297665, -0.0095288312,
--0.0090247190, -0.0085176902, -0.0080080052, -0.0074959251, -0.0069817115,
--0.0064656261, -0.0059479308, -0.0054288875, -0.0049087577, -0.0043878030,
--0.0038662845, -0.0033444625, -0.0028225970, -0.0023009471, -0.0017797709,
--0.0012593256, -0.0007398671, -0.0002216501, 0.0002950720, 0.0008100476,
-0.0013230264, 0.0018337601, 0.0023420022, 0.0028475082, 0.0033500357,
-0.0038493447, 0.0043451972, 0.0048373579, 0.0053255940, 0.0058096753,
-0.0062893745, 0.0067644670, 0.0072347313, 0.0076999490, 0.0081599047,
-0.0086143866, 0.0090631859, 0.0095060974, 0.0099429197, 0.0103734546,
-0.0107975079, 0.0112148892, 0.0116254119, 0.0120288935, 0.0124251554,
-0.0128140234, 0.0131953271, 0.0135689006, 0.0139345826, 0.0142922156,
-0.0146416472, 0.0149827292, 0.0153153180, 0.0156392747, 0.0159544652,
-0.0162607600, 0.0165580347, 0.0168461693, 0.0171250491, 0.0173945641,
-0.0176546096, 0.0179050854, 0.0181458969, 0.0183769543, 0.0185981728,
-0.0188094731, 0.0190107807, 0.0192020266, 0.0193831468, 0.0195540825,
-0.0197147802, 0.0198651918, 0.0200052742, 0.0201349897, 0.0202543057,
-0.0203631952, 0.0204616360, 0.0205496115, 0.0206271102, 0.0206941258,
-0.0207506574, 0.0207967092, 0.0208322904, 0.0208574158, 0.0208721048,
-0.0208763824, 0.0208702784, 0.0208538278, 0.0208270705, 0.0207900516,
-0.0207428209, 0.0206854333, 0.0206179485, 0.0205404311, 0.0204529502,
-0.0203555801, 0.0202483994, 0.0201314915, 0.0200049443, 0.0198688503,
-0.0197233063, 0.0195684137, 0.0194042780, 0.0192310091, 0.0190487212,
-0.0188575324, 0.0186575650, 0.0184489453, 0.0182318033, 0.0180062730,
-0.0177724922, 0.0175306024, 0.0172807484, 0.0170230788, 0.0167577456,
-0.0164849039, 0.0162047124, 0.0159173327, 0.0156229295, 0.0153216706,
-0.0150137267, 0.0146992710, 0.0143784798, 0.0140515319, 0.0137186083,
-0.0133798928, 0.0130355714, 0.0126858322, 0.0123308655, 0.0119708635,
-0.0116060206, 0.0112365327, 0.0108625976, 0.0104844146, 0.0101021845,
-0.0097161095, 0.0093263932, 0.0089332402, 0.0085368563, 0.0081374483,
-0.0077352238, 0.0073303912, 0.0069231595, 0.0065137383, 0.0061023376,
-0.0056891678, 0.0052744396, 0.0048583636, 0.0044411507, 0.0040230114,
-0.0036041564, 0.0031847958, 0.0027651394, 0.0023453967, 0.0019257762,
-0.0015064860, 0.0010877333, 0.0006697246, 0.0002526650, -0.0001632411,
--0.0005777908, -0.0009907824, -0.0014020154, -0.0018112910, -0.0022184119,
--0.0026231826, -0.0030254092, -0.0034248998, -0.0038214642, -0.0042149145,
--0.0046050648, -0.0049917315, -0.0053747331, -0.0057538906, -0.0061290276,
--0.0064999700, -0.0068665463, -0.0072285880, -0.0075859290, -0.0079384063,
--0.0082858597, -0.0086281320, -0.0089650690, -0.0092965198, -0.0096223365,
--0.0099423745, -0.0102564926, -0.0105645529, -0.0108664208, -0.0111619655,
--0.0114510595, -0.0117335789, -0.0120094035, -0.0122784169, -0.0125405063,
--0.0127955627, -0.0130434809, -0.0132841597, -0.0135175016, -0.0137434133,
--0.0139618053, -0.0141725921, -0.0143756923, -0.0145710286, -0.0147585277,
--0.0149381205, -0.0151097420, -0.0152733313, -0.0154288318, -0.0155761910,
--0.0157153607, -0.0158462969, -0.0159689596, -0.0160833133, -0.0161893267,
--0.0162869726, -0.0163762282, -0.0164570748, -0.0165294981, -0.0165934878,
--0.0166490381, -0.0166961471, -0.0167348174, -0.0167650556, -0.0167868725,
--0.0168002831, -0.0168053065, -0.0168019658, -0.0167902885, -0.0167703057,
--0.0167420530, -0.0167055697, -0.0166608992, -0.0166080887, -0.0165471894,
--0.0164782565, -0.0164013487, -0.0163165287, -0.0162238629, -0.0161234215,
--0.0160152781, -0.0158995102, -0.0157761985, -0.0156454275, -0.0155072851,
--0.0153618625, -0.0152092543, -0.0150495583, -0.0148828756, -0.0147093105,
--0.0145289703, -0.0143419654, -0.0141484092, -0.0139484179, -0.0137421107,
--0.0135296094, -0.0133110387, -0.0130865257, -0.0128562002, -0.0126201946,
--0.0123786435, -0.0121316840, -0.0118794553, -0.0116220991, -0.0113597589,
--0.0110925803, -0.0108207111, -0.0105443006, -0.0102635002, -0.0099784629,
--0.0096893433, -0.0093962976, -0.0090994836, -0.0087990603, -0.0084951880,
--0.0081880284, -0.0078777443, -0.0075644993, -0.0072484582, -0.0069297868,
--0.0066086514, -0.0062852192, -0.0059596580, -0.0056321361, -0.0053028224,
--0.0049718859, -0.0046394962, -0.0043058228, -0.0039710357, -0.0036353045,
--0.0032987991, -0.0029616890, -0.0026241437, -0.0022863322, -0.0019484233,
--0.0016105852, -0.0012729856, -0.0009357916, -0.0005991694, -0.0002632848,
-0.0000716978, 0.0004056145, 0.0007383027, 0.0010696008, 0.0013993484,
-0.0017273863, 0.0020535569, 0.0023777036, 0.0026996717, 0.0030193077,
-0.0033364600, 0.0036509786, 0.0039627152, 0.0042715235, 0.0045772590,
-0.0048797791, 0.0051789434, 0.0054746135, 0.0057666532, 0.0060549285,
-0.0063393077, 0.0066196614, 0.0068958626, 0.0071677869, 0.0074353122,
-0.0076983191, 0.0079566907, 0.0082103130, 0.0084590744, 0.0087028663,
-0.0089415828, 0.0091751208, 0.0094033802, 0.0096262638, 0.0098436773,
-0.0100555296, 0.0102617324, 0.0104622007, 0.0106568524, 0.0108456087,
-0.0110283940, 0.0112051357, 0.0113757647, 0.0115402150, 0.0116984238,
-0.0118503317, 0.0119958827, 0.0121350239, 0.0122677061, 0.0123938831,
-0.0125135122, 0.0126265542, 0.0127329732, 0.0128327367, 0.0129258157,
-0.0130121845, 0.0130918209, 0.0131647059, 0.0132308244, 0.0132901641,
-0.0133427167, 0.0133884768, 0.0134274427, 0.0134596160, 0.0134850017,
-0.0135036081, 0.0135154468, 0.0135205330, 0.0135188849, 0.0135105241,
-0.0134954756, 0.0134737674, 0.0134454309, 0.0134105007, 0.0133690146,
-0.0133210134, 0.0132665411, 0.0132056448, 0.0131383746, 0.0130647837,
-0.0129849281, 0.0128988671, 0.0128066625, 0.0127083792, 0.0126040849,
-0.0124938499, 0.0123777476, 0.0122558537, 0.0121282468, 0.0119950079,
-0.0118562209, 0.0117119718, 0.0115623494, 0.0114074445, 0.0112473506,
-0.0110821634, 0.0109119807, 0.0107369026, 0.0105570314, 0.0103724714,
-0.0101833288, 0.0099897118, 0.0097917307, 0.0095894973, 0.0093831254,
-0.0091727305, 0.0089584296, 0.0087403414, 0.0085185861, 0.0082932854,
-0.0080645621, 0.0078325408, 0.0075973470, 0.0073591075, 0.0071179501,
-0.0068740040, 0.0066273989, 0.0063782659, 0.0061267367, 0.0058729437,
-0.0056170202, 0.0053591000, 0.0050993177, 0.0048378082, 0.0045747069,
-0.0043101496, 0.0040442724, 0.0037772115, 0.0035091036, 0.0032400851,
-0.0029702926, 0.0026998629, 0.0024289322, 0.0021576369, 0.0018861131,
-0.0016144965, 0.0013429225, 0.0010715259, 0.0008004413, 0.0005298025,
-0.0002597426, -0.0000096058, -0.0002781110, -0.0005456421, -0.0008120690,
--0.0010772627, -0.0013410951, -0.0016034392, -0.0018641693, -0.0021231606,
--0.0023802898, -0.0026354347, -0.0028884748, -0.0031392906, -0.0033877643,
--0.0036337797, -0.0038772221, -0.0041179783, -0.0043559371, -0.0045909889,
--0.0048230256, -0.0050519414, -0.0052776322, -0.0054999956, -0.0057189316,
--0.0059343419, -0.0061461303, -0.0063542028, -0.0065584675, -0.0067588348,
--0.0069552170, -0.0071475291, -0.0073356879, -0.0075196129, -0.0076992258,
--0.0078744508, -0.0080452144, -0.0082114456, -0.0083730758, -0.0085300391,
--0.0086822719, -0.0088297134, -0.0089723051, -0.0091099913, -0.0092427188,
--0.0093704371, -0.0094930984, -0.0096106574, -0.0097230716, -0.0098303012,
--0.0099323091, -0.0100290609, -0.0101205249, -0.0102066721, -0.0102874763,
--0.0103629142, -0.0104329648, -0.0104976103, -0.0105568355, -0.0106106278,
--0.0106589775, -0.0107018776, -0.0107393238, -0.0107713147, -0.0107978513,
--0.0108189376, -0.0108345802, -0.0108447883, -0.0108495740, -0.0108489518,
--0.0108429390, -0.0108315555, -0.0108148239, -0.0107927692, -0.0107654191,
--0.0107328038, -0.0106949562, -0.0106519113, -0.0106037071, -0.0105503836,
--0.0104919834, -0.0104285517, -0.0103601356, -0.0102867850, -0.0102085518,
--0.0101254902, -0.0100376569, -0.0099451104, -0.0098479117, -0.0097461236,
--0.0096398114, -0.0095290421, -0.0094138849, -0.0092944108, -0.0091706929,
--0.0090428060, -0.0089108270, -0.0087748343, -0.0086349083, -0.0084911310,
--0.0083435859, -0.0081923585, -0.0080375355, -0.0078792054, -0.0077174578,
--0.0075523841, -0.0073840769, -0.0072126301, -0.0070381389, -0.0068606997,
--0.0066804102, -0.0064973689, -0.0063116757, -0.0061234313, -0.0059327375,
--0.0057396967, -0.0055444126, -0.0053469893, -0.0051475318, -0.0049461458,
--0.0047429375, -0.0045380139, -0.0043314824, -0.0041234507, -0.0039140271,
--0.0037033203, -0.0034914390, -0.0032784925, -0.0030645902, -0.0028498413,
--0.0026343555, -0.0024182424, -0.0022016113, -0.0019845719, -0.0017672333,
--0.0015497047, -0.0013320949, -0.0011145124, -0.0008970655, -0.0006798618,
--0.0004630087, -0.0002466130, -0.0000307810, 0.0001843818, 0.0003987705,
-0.0006122807, 0.0008248091, 0.0010362529, 0.0012465104, 0.0014554808,
-0.0016630642, 0.0018691616, 0.0020736751, 0.0022765082, 0.0024775651,
-0.0026767514, 0.0028739740, 0.0030691410, 0.0032621617, 0.0034529470,
-0.0036414089, 0.0038274611, 0.0040110187, 0.0041919982, 0.0043703178,
-0.0045458972, 0.0047186578, 0.0048885224, 0.0050554159, 0.0052192645,
-0.0053799965, 0.0055375418, 0.0056918321, 0.0058428010, 0.0059903840,
-0.0061345183, 0.0062751433, 0.0064122001, 0.0065456319, 0.0066753838,
-0.0068014030, 0.0069236387, 0.0070420421, 0.0071565665, 0.0072671672,
-0.0073738019, 0.0074764299, 0.0075750131, 0.0076695152, 0.0077599023,
-0.0078461426, 0.0079282063, 0.0080060659, 0.0080796962, 0.0081490739,
-0.0082141782, 0.0082749902, 0.0083314935, 0.0083836737, 0.0084315187,
-0.0084750184, 0.0085141652, 0.0085489535, 0.0085793798, 0.0086054431,
-0.0086271443, 0.0086444866, 0.0086574753, 0.0086661178, 0.0086704239,
-0.0086704051, 0.0086660755, 0.0086574509, 0.0086445494, 0.0086273912,
-0.0086059984, 0.0085803953, 0.0085506081, 0.0085166650, 0.0084785963,
-0.0084364341, 0.0083902126, 0.0083399679, 0.0082857377, 0.0082275620,
-0.0081654823, 0.0080995421, 0.0080297867, 0.0079562629, 0.0078790195,
-0.0077981068, 0.0077135771, 0.0076254839, 0.0075338826, 0.0074388300,
-0.0073403846, 0.0072386063, 0.0071335564, 0.0070252979, 0.0069138948,
-0.0067994129, 0.0066819189, 0.0065614810, 0.0064381688, 0.0063120528,
-0.0061832049, 0.0060516980, 0.0059176061, 0.0057810043, 0.0056419687,
-0.0055005764, 0.0053569054, 0.0052110344, 0.0050630433, 0.0049130126,
-0.0047610235, 0.0046071580, 0.0044514987, 0.0042941290, 0.0041351326,
-0.0039745941, 0.0038125983, 0.0036492306, 0.0034845767, 0.0033187227,
-0.0031517551, 0.0029837607, 0.0028148263, 0.0026450392, 0.0024744865,
-0.0023032557, 0.0021314343, 0.0019591096, 0.0017863692, 0.0016133002,
-0.0014399901, 0.0012665257, 0.0010929941, 0.0009194817, 0.0007460750,
-0.0005728599, 0.0003999219, 0.0002273465, 0.0000552181, -0.0001163788,
--0.0002873606, -0.0004576441, -0.0006271469, -0.0007957871, -0.0009634835,
--0.0011301557, -0.0012957241, -0.0014601097, -0.0016232347, -0.0017850218,
--0.0019453950, -0.0021042788, -0.0022615991, -0.0024172826, -0.0025712572,
--0.0027234517, -0.0028737961, -0.0030222217, -0.0031686607, -0.0033130467,
--0.0034553146, -0.0035954003, -0.0037332412, -0.0038687761, -0.0040019449,
--0.0041326891, -0.0042609514, -0.0043866761, -0.0045098089, -0.0046302969,
--0.0047480887, -0.0048631346, -0.0049753861, -0.0050847965, -0.0051913206,
--0.0052949147, -0.0053955370, -0.0054931469, -0.0055877057, -0.0056791763,
--0.0057675233, -0.0058527128, -0.0059347128, -0.0060134928, -0.0060890242,
--0.0061612801, -0.0062302350, -0.0062958655, -0.0063581499, -0.0064170679,
--0.0064726014, -0.0065247337, -0.0065734501, -0.0066187374, -0.0066605844,
--0.0066989815, -0.0067339208, -0.0067653964, -0.0067934038, -0.0068179406,
--0.0068390059, -0.0068566006, -0.0068707273, -0.0068813904, -0.0068885959,
--0.0068923516, -0.0068926670, -0.0068895532, -0.0068830230, -0.0068730909,
--0.0068597730, -0.0068430871, -0.0068230526, -0.0067996905, -0.0067730233,
--0.0067430751, -0.0067098718, -0.0066734406, -0.0066338102, -0.0065910108,
--0.0065450743, -0.0064960339, -0.0064439242, -0.0063887812, -0.0063306424,
--0.0062695467, -0.0062055342, -0.0061386464, -0.0060689262, -0.0059964175,
--0.0059211657, -0.0058432173, -0.0057626201, -0.0056794229, -0.0055936757,
--0.0055054298, -0.0054147371, -0.0053216511, -0.0052262260, -0.0051285171,
--0.0050285805, -0.0049264734, -0.0048222538, -0.0047159807, -0.0046077137,
--0.0044975134, -0.0043854410, -0.0042715586, -0.0041559288, -0.0040386151,
--0.0039196815, -0.0037991925, -0.0036772133, -0.0035538097, -0.0034290478,
--0.0033029941, -0.0031757159, -0.0030472806, -0.0029177559, -0.0027872101,
--0.0026557114, -0.0025233286, -0.0023901305, -0.0022561863, -0.0021215650,
--0.0019863359, -0.0018505686, -0.0017143323, -0.0015776965, -0.0014407305,
--0.0013035038, -0.0011660854, -0.0010285445, -0.0008909501, -0.0007533707,
--0.0006158750, -0.0004785311, -0.0003414068, -0.0002045699, -0.0000680874,
-0.0000679738, 0.0002035473, 0.0003385673, 0.0004729683, 0.0006066854,
-0.0007396544, 0.0008718115, 0.0010030935, 0.0011334381, 0.0012627833,
-0.0013910681, 0.0015182322, 0.0016442159, 0.0017689604, 0.0018924077,
-0.0020145008, 0.0021351832, 0.0022543995, 0.0023720954, 0.0024882172,
-0.0026027124, 0.0027155294, 0.0028266176, 0.0029359274, 0.0030434103,
-0.0031490190, 0.0032527070, 0.0033544293, 0.0034541416, 0.0035518011,
-0.0036473659, 0.0037407955, 0.0038320506, 0.0039210929, 0.0040078855,
-0.0040923927, 0.0041745801, 0.0042544146, 0.0043318642, 0.0044068984,
-0.0044794879, 0.0045496048, 0.0046172225, 0.0046823156, 0.0047448602,
-0.0048048338, 0.0048622151, 0.0049169842, 0.0049691226, 0.0050186133,
-0.0050654404, 0.0051095896, 0.0051510480, 0.0051898039, 0.0052258471,
-0.0052591688, 0.0052897616, 0.0053176194, 0.0053427377, 0.0053651130,
-0.0053847435, 0.0054016287, 0.0054157694, 0.0054271679, 0.0054358277,
-0.0054417538, 0.0054449524, 0.0054454311, 0.0054431990, 0.0054382662,
-0.0054306444, 0.0054203464, 0.0054073864, 0.0053917800, 0.0053735437,
-0.0053526956, 0.0053292549, 0.0053032421, 0.0052746789, 0.0052435880,
-0.0052099936, 0.0051739208, 0.0051353961, 0.0050944469, 0.0050511019,
-0.0050053908, 0.0049573443, 0.0049069944, 0.0048543739, 0.0047995168,
-0.0047424579, 0.0046832332, 0.0046218796, 0.0045584348, 0.0044929376,
-0.0044254276, 0.0043559452, 0.0042845317, 0.0042112294, 0.0041360811,
-0.0040591307, 0.0039804224, 0.0039000017, 0.0038179142, 0.0037342067,
-0.0036489264, 0.0035621211, 0.0034738392, 0.0033841298, 0.0032930424,
-0.0032006271, 0.0031069345, 0.0030120157, 0.0029159221, 0.0028187055,
-0.0027204184, 0.0026211132, 0.0025208431, 0.0024196611, 0.0023176209,
-0.0022147762, 0.0021111811, 0.0020068897, 0.0019019563, 0.0017964356,
-0.0016903819, 0.0015838501, 0.0014768947, 0.0013695707, 0.0012619327,
-0.0011540355, 0.0010459336, 0.0009376817, 0.0008293342, 0.0007209455,
-0.0006125697, 0.0005042607, 0.0003960723, 0.0002880581, 0.0001802712,
-0.0000727645, -0.0000344092, -0.0001411978, -0.0002475493, -0.0003534123,
--0.0004587356, -0.0005634687, -0.0006675613, -0.0007709638, -0.0008736271,
--0.0009755024, -0.0010765418, -0.0011766978, -0.0012759234, -0.0013741725,
--0.0014713993, -0.0015675591, -0.0016626076, -0.0017565011, -0.0018491969,
--0.0019406529, -0.0020308278, -0.0021196811, -0.0022071730, -0.0022932646,
--0.0023779179, -0.0024610956, -0.0025427614, -0.0026228797, -0.0027014160,
--0.0027783366, -0.0028536087, -0.0029272006, -0.0029990813, -0.0030692209,
--0.0031375904, -0.0032041620, -0.0032689087, -0.0033318045, -0.0033928243,
--0.0034519445, -0.0035091419, -0.0035643948, -0.0036176824, -0.0036689849,
--0.0037182836, -0.0037655608, -0.0038108001, -0.0038539859, -0.0038951038,
--0.0039341405, -0.0039710838, -0.0040059225, -0.0040386465, -0.0040692468,
--0.0040977156, -0.0041240461, -0.0041482326, -0.0041702705, -0.0041901562,
--0.0042078873, -0.0042234624, -0.0042368814, -0.0042481449, -0.0042572549,
--0.0042642143, -0.0042690272, -0.0042716985, -0.0042722345, -0.0042706422,
--0.0042669299, -0.0042611069, -0.0042531833, -0.0042431705, -0.0042310807,
--0.0042169271, -0.0042007241, -0.0041824868, -0.0041622314, -0.0041399751,
--0.0041157359, -0.0040895329, -0.0040613860, -0.0040313159, -0.0039993444,
--0.0039654940, -0.0039297883, -0.0038922514, -0.0038529085, -0.0038117856,
--0.0037689092, -0.0037243070, -0.0036780073, -0.0036300389, -0.0035804318,
--0.0035292163, -0.0034764236, -0.0034220855, -0.0033662347, -0.0033089041,
--0.0032501275, -0.0031899394, -0.0031283747, -0.0030654689, -0.0030012581,
--0.0029357788, -0.0028690681, -0.0028011637, -0.0027321035, -0.0026619261,
--0.0025906704, -0.0025183756, -0.0024450815, -0.0023708281, -0.0022956558,
--0.0022196054, -0.0021427177, -0.0020650342, -0.0019865962, -0.0019074456,
--0.0018276244, -0.0017471747, -0.0016661388, -0.0015845592, -0.0015024785,
--0.0014199393, -0.0013369845, -0.0012536568, -0.0011699992, -0.0010860544,
--0.0010018654, -0.0009174749, -0.0008329258, -0.0007482608, -0.0006635226,
--0.0005787535, -0.0004939960, -0.0004092923, -0.0003246844, -0.0002402143,
--0.0001559234, -0.0000718533, 0.0000119550, 0.0000954606, 0.0001786230,
-0.0002614018, 0.0003437572, 0.0004256495, 0.0005070398, 0.0005878890,
-0.0006681588, 0.0007478113, 0.0008268089, 0.0009051145, 0.0009826917,
-0.0010595042, 0.0011355164, 0.0012106934, 0.0012850006, 0.0013584040,
-0.0014308703, 0.0015023666, 0.0015728608, 0.0016423212, 0.0017107168,
-0.0017780175, 0.0018441934, 0.0019092157, 0.0019730560, 0.0020356866,
-0.0020970806, 0.0021572119, 0.0022160549, 0.0022735848, 0.0023297778,
-0.0023846105, 0.0024380603, 0.0024901057, 0.0025407257, 0.0025899000,
-0.0026376093, 0.0026838351, 0.0027285596, 0.0027717659, 0.0028134378,
-0.0028535600, 0.0028921181, 0.0029290984, 0.0029644882, 0.0029982753,
-0.0030304488, 0.0030609984, 0.0030899146, 0.0031171889, 0.0031428134,
-0.0031667815, 0.0031890869, 0.0032097246, 0.0032286903, 0.0032459804,
-0.0032615923, 0.0032755244, 0.0032877756, 0.0032983458, 0.0033072359,
-0.0033144474, 0.0033199827, 0.0033238451, 0.0033260387, 0.0033265683,
-0.0033254397, 0.0033226595, 0.0033182348, 0.0033121739, 0.0033044855,
-0.0032951796, 0.0032842663, 0.0032717571, 0.0032576639, 0.0032419993,
-0.0032247769, 0.0032060109, 0.0031857162, 0.0031639083, 0.0031406037,
-0.0031158194, 0.0030895730, 0.0030618828, 0.0030327680, 0.0030022482,
-0.0029703436, 0.0029370752, 0.0029024645, 0.0028665336, 0.0028293051,
-0.0027908024, 0.0027510492, 0.0027100699, 0.0026678893, 0.0026245328,
-0.0025800264, 0.0025343963, 0.0024876693, 0.0024398728, 0.0023910345,
-0.0023411825, 0.0022903452, 0.0022385517, 0.0021858313, 0.0021322135,
-0.0020777285, 0.0020224064, 0.0019662779, 0.0019093741, 0.0018517259,
-0.0017933649, 0.0017343229, 0.0016746316, 0.0016143233, 0.0015534303,
-0.0014919850, 0.0014300201, 0.0013675684, 0.0013046629, 0.0012413365,
-0.0011776223, 0.0011135537, 0.0010491637, 0.0009844857, 0.0009195531,
-0.0008543990, 0.0007890569, 0.0007235600, 0.0006579415, 0.0005922346,
-0.0005264724, 0.0004606880, 0.0003949141, 0.0003291837, 0.0002635292,
-0.0001979832, 0.0001325780, 0.0000673457, 0.0000023182, -0.0000624728,
--0.0001269959, -0.0001912198, -0.0002551136, -0.0003186466, -0.0003817885,
--0.0004445092, -0.0005067789, -0.0005685683, -0.0006298483, -0.0006905900,
--0.0007507654, -0.0008103463, -0.0008693052, -0.0009276151, -0.0009852491,
--0.0010421811, -0.0010983851, -0.0011538359, -0.0012085085, -0.0012623785,
--0.0013154219, -0.0013676154, -0.0014189360, -0.0014693614, -0.0015188696,
--0.0015674393, -0.0016150498, -0.0016616808, -0.0017073126, -0.0017519262,
--0.0017955030, -0.0018380252, -0.0018794753, -0.0019198367, -0.0019590932,
--0.0019972294, -0.0020342302, -0.0020700814, -0.0021047694, -0.0021382811,
--0.0021706043, -0.0022017270, -0.0022316382, -0.0022603275, -0.0022877851,
--0.0023140018, -0.0023389690, -0.0023626791, -0.0023851246, -0.0024062993,
--0.0024261971, -0.0024448128, -0.0024621419, -0.0024781806, -0.0024929256,
--0.0025063742, -0.0025185247, -0.0025293756, -0.0025389266, -0.0025471774,
--0.0025541290, -0.0025597826, -0.0025641401, -0.0025672043, -0.0025689784,
--0.0025694663, -0.0025686724, -0.0025666021, -0.0025632609, -0.0025586554,
--0.0025527924, -0.0025456797, -0.0025373253, -0.0025277381, -0.0025169273,
--0.0025049031, -0.0024916758, -0.0024772565, -0.0024616569, -0.0024448891,
--0.0024269658, -0.0024079004, -0.0023877064, -0.0023663983, -0.0023439908,
--0.0023204992, -0.0022959392, -0.0022703270, -0.0022436795, -0.0022160136,
--0.0021873471, -0.0021576979, -0.0021270845, -0.0020955259, -0.0020630411,
--0.0020296500, -0.0019953726, -0.0019602293, -0.0019242408, -0.0018874283,
--0.0018498132, -0.0018114173, -0.0017722626, -0.0017323716, -0.0016917669,
--0.0016504714, -0.0016085084, -0.0015659012, -0.0015226735, -0.0014788493,
--0.0014344526, -0.0013895077, -0.0013440391, -0.0012980715, -0.0012516297,
--0.0012047386, -0.0011574233, -0.0011097090, -0.0010616211, -0.0010131848,
--0.0009644258, -0.0009153695, -0.0008660416, -0.0008164676, -0.0007666733,
--0.0007166843, -0.0006665263, -0.0006162249, -0.0005658059, -0.0005152948,
--0.0004647171, -0.0004140985, -0.0003634642, -0.0003128396, -0.0002622499,
--0.0002117203, -0.0001612757, -0.0001109410, -0.0000607409, -0.0000107000,
-0.0000391574, 0.0000888071, 0.0001382251, 0.0001873876, 0.0002362710,
-0.0002848520, 0.0003331074, 0.0003810145, 0.0004285507, 0.0004756935,
-0.0005224210, 0.0005687114, 0.0006145433, 0.0006598955, 0.0007047472,
-0.0007490779, 0.0007928675, 0.0008360961, 0.0008787443, 0.0009207930,
-0.0009622235, 0.0010030174, 0.0010431569, 0.0010826243, 0.0011214025,
-0.0011594747, 0.0011968247, 0.0012334365, 0.0012692947, 0.0013043841,
-0.0013386903, 0.0013721991, 0.0014048968, 0.0014367701, 0.0014678062,
-0.0014979929, 0.0015273183, 0.0015557711, 0.0015833403, 0.0016100155,
-0.0016357870, 0.0016606451, 0.0016845811, 0.0017075864, 0.0017296531,
-0.0017507738, 0.0017709416, 0.0017901499, 0.0018083930, 0.0018256652,
-0.0018419618, 0.0018572784, 0.0018716109, 0.0018849560, 0.0018973109,
-0.0019086731, 0.0019190407, 0.0019284124, 0.0019367874, 0.0019441651,
-0.0019505458, 0.0019559301, 0.0019603191, 0.0019637144, 0.0019661182,
-0.0019675329, 0.0019679618, 0.0019674083, 0.0019658766, 0.0019633710,
-0.0019598967, 0.0019554590, 0.0019500638, 0.0019437176, 0.0019364271,
-0.0019281995, 0.0019190427, 0.0019089647, 0.0018979741, 0.0018860799,
-0.0018732914, 0.0018596186, 0.0018450717, 0.0018296611, 0.0018133981,
-0.0017962939, 0.0017783603, 0.0017596096, 0.0017400541, 0.0017197068,
-0.0016985808, 0.0016766897, 0.0016540474, 0.0016306680, 0.0016065662,
-0.0015817566, 0.0015562544, 0.0015300751, 0.0015032342, 0.0014757478,
-0.0014476321, 0.0014189035, 0.0013895787, 0.0013596746, 0.0013292086,
-0.0012981978, 0.0012666600, 0.0012346128, 0.0012020743, 0.0011690626,
-0.0011355960, 0.0011016931, 0.0010673723, 0.0010326524, 0.0009975524,
-0.0009620912, 0.0009262880, 0.0008901619, 0.0008537322, 0.0008170183,
-0.0007800396, 0.0007428156, 0.0007053659, 0.0006677099, 0.0006298674,
-0.0005918580, 0.0005537012, 0.0005154167, 0.0004770241, 0.0004385430,
-0.0003999929, 0.0003613934, 0.0003227639, 0.0002841239, 0.0002454926,
-0.0002068894, 0.0001683333, 0.0001298435, 0.0000914390, 0.0000531385,
-0.0000149607, -0.0000230756, -0.0000609521, -0.0000986506, -0.0001361528,
--0.0001734408, -0.0002104968, -0.0002473033, -0.0002838427, -0.0003200980,
--0.0003560521, -0.0003916882, -0.0004269898, -0.0004619406, -0.0004965245,
--0.0005307256, -0.0005645283, -0.0005979174, -0.0006308778, -0.0006633947,
--0.0006954536, -0.0007270403, -0.0007581408, -0.0007887415, -0.0008188291,
--0.0008483907, -0.0008774134, -0.0009058849, -0.0009337931, -0.0009611264,
--0.0009878733, -0.0010140227, -0.0010395640, -0.0010644867, -0.0010887809,
--0.0011124369, -0.0011354454, -0.0011577974, -0.0011794844, -0.0012004980,
--0.0012208306, -0.0012404746, -0.0012594229, -0.0012776687, -0.0012952058,
--0.0013120281, -0.0013281301, -0.0013435065, -0.0013581526, -0.0013720639,
--0.0013852363, -0.0013976662, -0.0014093503, -0.0014202856, -0.0014304698,
--0.0014399006, -0.0014485764, -0.0014564957, -0.0014636576, -0.0014700615,
--0.0014757072, -0.0014805949, -0.0014847251, -0.0014880988, -0.0014907172,
--0.0014925821, -0.0014936955, -0.0014940597, -0.0014936777, -0.0014925524,
--0.0014906875, -0.0014880868, -0.0014847545, -0.0014806951, -0.0014759136,
--0.0014704152, -0.0014642055, -0.0014572904, -0.0014496762, -0.0014413695,
--0.0014323770, -0.0014227062, -0.0014123644, -0.0014013595, -0.0013896996,
--0.0013773932, -0.0013644489, -0.0013508758, -0.0013366832, -0.0013218805,
--0.0013064777, -0.0012904848, -0.0012739120, -0.0012567701, -0.0012390699,
--0.0012208223, -0.0012020388, -0.0011827307, -0.0011629099, -0.0011425883,
--0.0011217780, -0.0011004914, -0.0010787410, -0.0010565395, -0.0010338998,
--0.0010108350, -0.0009873583, -0.0009634830, -0.0009392227, -0.0009145911,
--0.0008896018, -0.0008642689, -0.0008386063, -0.0008126283, -0.0007863489,
--0.0007597826, -0.0007329438, -0.0007058470, -0.0006785067, -0.0006509376,
--0.0006231543, -0.0005951717, -0.0005670044, -0.0005386673, -0.0005101753,
--0.0004815431, -0.0004527857, -0.0004239178, -0.0003949545, -0.0003659105,
--0.0003368006, -0.0003076398, -0.0002784426, -0.0002492239, -0.0002199984,
--0.0001907807, -0.0001615854, -0.0001324268, -0.0001033196, -0.0000742779,
--0.0000453161, -0.0000164483, 0.0000123115, 0.0000409493, 0.0000694513,
-0.0000978039, 0.0001259933, 0.0001540064, 0.0001818296, 0.0002094500,
-0.0002368545, 0.0002640303, 0.0002909647, 0.0003176453, 0.0003440598,
-0.0003701960, 0.0003960420, 0.0004215861, 0.0004468167, 0.0004717224,
-0.0004962922, 0.0005205151, 0.0005443804, 0.0005678777, 0.0005909967,
-0.0006137274, 0.0006360599, 0.0006579848, 0.0006794927, 0.0007005745,
-0.0007212216, 0.0007414252, 0.0007611772, 0.0007804694, 0.0007992941,
-0.0008176438, 0.0008355112, 0.0008528894, 0.0008697717, 0.0008861516,
-0.0009020230, 0.0009173801, 0.0009322172, 0.0009465290, 0.0009603105,
-0.0009735571, 0.0009862642, 0.0009984277, 0.0010100437, 0.0010211086,
-0.0010316192, 0.0010415725, 0.0010509657, 0.0010597965, 0.0010680626,
-0.0010757624, 0.0010828942, 0.0010894568, 0.0010954492, 0.0011008708,
-0.0011057211, 0.0011100002, 0.0011137081, 0.0011168454, 0.0011194127,
-0.0011214113, 0.0011228423, 0.0011237074, 0.0011240084, 0.0011237476,
-0.0011229273, 0.0011215502, 0.0011196193, 0.0011171379, 0.0011141094,
-0.0011105375, 0.0011064263, 0.0011017801, 0.0010966033, 0.0010909007,
-0.0010846773, 0.0010779384, 0.0010706894, 0.0010629361, 0.0010546843,
-0.0010459403, 0.0010367105, 0.0010270014, 0.0010168199, 0.0010061729,
-0.0009950678, 0.0009835120, 0.0009715130, 0.0009590787, 0.0009462171,
-0.0009329365, 0.0009192450, 0.0009051513, 0.0008906642, 0.0008757923,
-0.0008605448, 0.0008449308, 0.0008289596, 0.0008126407, 0.0007959837,
-0.0007789982, 0.0007616942, 0.0007440816, 0.0007261704, 0.0007079708,
-0.0006894932, 0.0006707479, 0.0006517454, 0.0006324962, 0.0006130110,
-0.0005933005, 0.0005733755, 0.0005532468, 0.0005329253, 0.0005124220,
-0.0004917479, 0.0004709140, 0.0004499314, 0.0004288111, 0.0004075644,
-0.0003862023, 0.0003647361, 0.0003431768, 0.0003215357, 0.0002998238,
-0.0002780524, 0.0002562326, 0.0002343754, 0.0002124920, 0.0001905934,
-0.0001686906, 0.0001467946, 0.0001249163, 0.0001030665, 0.0000812561,
-0.0000594957, 0.0000377962, 0.0000161680, -0.0000053783, -0.0000268323,
--0.0000481837, -0.0000694222, -0.0000905376, -0.0001115200, -0.0001323593,
--0.0001530458, -0.0001735697, -0.0001939216, -0.0002140918, -0.0002340711,
--0.0002538504, -0.0002734204, -0.0002927724, -0.0003118976, -0.0003307873,
--0.0003494331, -0.0003678267, -0.0003859599, -0.0004038248, -0.0004214136,
--0.0004387185, -0.0004557322, -0.0004724474, -0.0004888569, -0.0005049539,
--0.0005207315, -0.0005361833, -0.0005513028, -0.0005660839, -0.0005805207,
--0.0005946073, -0.0006083382, -0.0006217080, -0.0006347115, -0.0006473437,
--0.0006596000, -0.0006714757, -0.0006829665, -0.0006940683, -0.0007047771,
--0.0007150893, -0.0007250014, -0.0007345100, -0.0007436121, -0.0007523049,
--0.0007605858, -0.0007684523, -0.0007759022, -0.0007829336, -0.0007895447,
--0.0007957340, -0.0008015002, -0.0008068421, -0.0008117589, -0.0008162498,
--0.0008203145, -0.0008239527, -0.0008271644, -0.0008299497, -0.0008323091,
--0.0008342432, -0.0008357529, -0.0008368390, -0.0008375030, -0.0008377461,
--0.0008375702, -0.0008369770, -0.0008359687, -0.0008345473, -0.0008327155,
--0.0008304759, -0.0008278313, -0.0008247847, -0.0008213393, -0.0008174987,
--0.0008132662, -0.0008086459, -0.0008036415, -0.0007982572, -0.0007924973,
--0.0007863663, -0.0007798688, -0.0007730096, -0.0007657937, -0.0007582263,
--0.0007503124, -0.0007420577, -0.0007334676, -0.0007245480, -0.0007153045,
--0.0007057433, -0.0006958705, -0.0006856923, -0.0006752151, -0.0006644455,
--0.0006533899, -0.0006420553, -0.0006304484, -0.0006185763, -0.0006064459,
--0.0005940644, -0.0005814391, -0.0005685774, -0.0005554866, -0.0005421744,
--0.0005286483, -0.0005149159, -0.0005009850, -0.0004868635, -0.0004725592,
--0.0004580801, -0.0004434340, -0.0004286292, -0.0004136736, -0.0003985753,
--0.0003833426, -0.0003679835, -0.0003525065, -0.0003369196, -0.0003212311,
--0.0003054494, -0.0002895827, -0.0002736393, -0.0002576275, -0.0002415556,
--0.0002254319, -0.0002092648, -0.0001930624, -0.0001768330, -0.0001605849,
--0.0001443262, -0.0001280652, -0.0001118099, -0.0000955685, -0.0000793491,
--0.0000631597, -0.0000470081, -0.0000309025, -0.0000148505, 0.0000011400,
-0.0000170612, 0.0000329055, 0.0000486653, 0.0000643331, 0.0000799015,
-0.0000953630, 0.0001107104, 0.0001259365, 0.0001410343, 0.0001559967,
-0.0001708168, 0.0001854879, 0.0002000031, 0.0002143560, 0.0002285401,
-0.0002425489, 0.0002563763, 0.0002700161, 0.0002834622, 0.0002967089,
-0.0003097503, 0.0003225808, 0.0003351948, 0.0003475871, 0.0003597523,
-0.0003716854, 0.0003833814, 0.0003948354, 0.0004060428, 0.0004169991,
-0.0004276998, 0.0004381406, 0.0004483176, 0.0004582267, 0.0004678642,
-0.0004772264, 0.0004863097, 0.0004951109, 0.0005036269, 0.0005118544,
-0.0005197908, 0.0005274332, 0.0005347792, 0.0005418263, 0.0005485724,
-0.0005550152, 0.0005611530, 0.0005669840, 0.0005725066, 0.0005777193,
-0.0005826210, 0.0005872105, 0.0005914868, 0.0005954492, 0.0005990971,
-0.0006024300, 0.0006054476, 0.0006081498, 0.0006105366, 0.0006126081,
-0.0006143647, 0.0006158069, 0.0006169354, 0.0006177508, 0.0006182543,
-0.0006184469, 0.0006183298, 0.0006179045, 0.0006171725, 0.0006161355,
-0.0006147954, 0.0006131542, 0.0006112139, 0.0006089769, 0.0006064456,
-0.0006036225, 0.0006005103, 0.0005971119, 0.0005934301, 0.0005894681,
-0.0005852291, 0.0005807164, 0.0005759334, 0.0005708838, 0.0005655712,
-0.0005599994, 0.0005541724, 0.0005480941, 0.0005417688, 0.0005352006,
-0.0005283939, 0.0005213533, 0.0005140831, 0.0005065881, 0.0004988729,
-0.0004909425, 0.0004828018, 0.0004744556, 0.0004659092, 0.0004571676,
-0.0004482360, 0.0004391199, 0.0004298245, 0.0004203554, 0.0004107179,
-0.0004009177, 0.0003909603, 0.0003808515, 0.0003705970, 0.0003602026,
-0.0003496739, 0.0003390171, 0.0003282378, 0.0003173421, 0.0003063359,
-0.0002952252, 0.0002840160, 0.0002727144, 0.0002613264, 0.0002498582,
-0.0002383157, 0.0002267052, 0.0002150326, 0.0002033042, 0.0001915261,
-0.0001797043, 0.0001678449, 0.0001559542, 0.0001440381, 0.0001321027,
-0.0001201541, 0.0001081984, 0.0000962415, 0.0000842894, 0.0000723481,
-0.0000604235, 0.0000485216, 0.0000366481, 0.0000248089, 0.0000130097,
-0.0000012563, -0.0000104456, -0.0000220904, -0.0000336725, -0.0000451865,
--0.0000566268, -0.0000679881, -0.0000792650, -0.0000904522, -0.0001015446,
--0.0001125370, -0.0001234244, -0.0001342017, -0.0001448641, -0.0001554068,
--0.0001658250, -0.0001761140, -0.0001862693, -0.0001962863, -0.0002061608,
--0.0002158883, -0.0002254646, -0.0002348857, -0.0002441476, -0.0002532462,
--0.0002621777, -0.0002709385, -0.0002795249, -0.0002879334, -0.0002961605,
--0.0003042030, -0.0003120577, -0.0003197214, -0.0003271912, -0.0003344642,
--0.0003415377, -0.0003484089, -0.0003550754, -0.0003615348, -0.0003677846,
--0.0003738228, -0.0003796473, -0.0003852560, -0.0003906472, -0.0003958191,
--0.0004007702, -0.0004054988, -0.0004100037, -0.0004142837, -0.0004183374,
--0.0004221641, -0.0004257626, -0.0004291324, -0.0004322726, -0.0004351828,
--0.0004378626, -0.0004403116, -0.0004425296, -0.0004445166, -0.0004462725,
--0.0004477977, -0.0004490922, -0.0004501566, -0.0004509913, -0.0004515970,
--0.0004519743, -0.0004521241, -0.0004520473, -0.0004517450, -0.0004512184,
--0.0004504687, -0.0004494974, -0.0004483058, -0.0004468956, -0.0004452685,
--0.0004434263, -0.0004413708, -0.0004391040, -0.0004366281, -0.0004339452,
--0.0004310576, -0.0004279676, -0.0004246778, -0.0004211906, -0.0004175087,
--0.0004136348, -0.0004095717, -0.0004053224, -0.0004008897, -0.0003962768,
--0.0003914867, -0.0003865227, -0.0003813879, -0.0003760859, -0.0003706199,
--0.0003649934, -0.0003592101, -0.0003532734, -0.0003471871, -0.0003409549,
--0.0003345805, -0.0003280679, -0.0003214208, -0.0003146432, -0.0003077392,
--0.0003007127, -0.0002935678, -0.0002863086, -0.0002789393, -0.0002714641,
--0.0002638872, -0.0002562128, -0.0002484452, -0.0002405888, -0.0002326478,
--0.0002246267, -0.0002165298, -0.0002083615, -0.0002001262, -0.0001918284,
--0.0001834725, -0.0001750629, -0.0001666042, -0.0001581006, -0.0001495568,
--0.0001409772, -0.0001323662, -0.0001237283, -0.0001150680, -0.0001063896,
--0.0000976976, -0.0000889965, -0.0000802906, -0.0000715842, -0.0000628818,
--0.0000541878, -0.0000455063, -0.0000368418, -0.0000281984, -0.0000195804,
--0.0000109920, -0.0000024374, 0.0000060793, 0.0000145541, 0.0000229828,
-0.0000313614, 0.0000396861, 0.0000479528, 0.0000561577, 0.0000642970,
-0.0000723668, 0.0000803636, 0.0000882835, 0.0000961230, 0.0001038785,
-0.0001115465, 0.0001191237, 0.0001266065, 0.0001339917, 0.0001412761,
-0.0001484564, 0.0001555296, 0.0001624925, 0.0001693423, 0.0001760759,
-0.0001826906, 0.0001891836, 0.0001955522, 0.0002017938, 0.0002079058,
-0.0002138857, 0.0002197313, 0.0002254401, 0.0002310100, 0.0002364387,
-0.0002417243, 0.0002468647, 0.0002518580, 0.0002567025, 0.0002613963,
-0.0002659378, 0.0002703254, 0.0002745577, 0.0002786332, 0.0002825506,
-0.0002863087, 0.0002899064, 0.0002933425, 0.0002966162, 0.0002997264,
-0.0003026725, 0.0003054536, 0.0003080692, 0.0003105187, 0.0003128017,
-0.0003149178, 0.0003168666, 0.0003186480, 0.0003202619, 0.0003217083,
-0.0003229871, 0.0003240985, 0.0003250428, 0.0003258202, 0.0003264312,
-0.0003268761, 0.0003271556, 0.0003272702, 0.0003272206, 0.0003270078,
-0.0003266324, 0.0003260955, 0.0003253981, 0.0003245412, 0.0003235261,
-0.0003223540, 0.0003210261, 0.0003195440, 0.0003179089, 0.0003161226,
-0.0003141865, 0.0003121023, 0.0003098718, 0.0003074968, 0.0003049791,
-0.0003023207, 0.0002995235, 0.0002965895, 0.0002935210, 0.0002903200,
-0.0002869888, 0.0002835296, 0.0002799448, 0.0002762367, 0.0002724079,
-0.0002684607, 0.0002643977, 0.0002602215, 0.0002559347, 0.0002515399,
-0.0002470399, 0.0002424374, 0.0002377352, 0.0002329361, 0.0002280430,
-0.0002230587, 0.0002179862, 0.0002128285, 0.0002075885, 0.0002022692,
-0.0001968736, 0.0001914049, 0.0001858661, 0.0001802603, 0.0001745906,
-0.0001688602, 0.0001630723, 0.0001572299, 0.0001513363, 0.0001453946,
-0.0001394082, 0.0001333801, 0.0001273136, 0.0001212119, 0.0001150782,
-0.0001089158, 0.0001027279, 0.0000965177, 0.0000902884, 0.0000840433,
-0.0000777854, 0.0000715181, 0.0000652446, 0.0000589678, 0.0000526912,
-0.0000464177, 0.0000401505, 0.0000338928, 0.0000276476, 0.0000214180,
-0.0000152070, 0.0000090176, 0.0000028530, -0.0000032841, -0.0000093905,
--0.0000154635, -0.0000215001, -0.0000274975, -0.0000334528, -0.0000393633,
--0.0000452261, -0.0000510387, -0.0000567983, -0.0000625023, -0.0000681481,
--0.0000737331, -0.0000792549, -0.0000847109, -0.0000900988, -0.0000954161,
--0.0001006605, -0.0001058298, -0.0001109216, -0.0001159339, -0.0001208645,
--0.0001257113, -0.0001304723, -0.0001351454, -0.0001397288, -0.0001442206,
--0.0001486190, -0.0001529222, -0.0001571285, -0.0001612363, -0.0001652439,
--0.0001691499, -0.0001729527, -0.0001766509, -0.0001802433, -0.0001837284,
--0.0001871051, -0.0001903722, -0.0001935285, -0.0001965730, -0.0001995047,
--0.0002023227, -0.0002050261, -0.0002076141, -0.0002100859, -0.0002124409,
--0.0002146784, -0.0002167979, -0.0002187988, -0.0002206808, -0.0002224434,
--0.0002240864, -0.0002256094, -0.0002270123, -0.0002282950, -0.0002294574,
--0.0002304995, -0.0002314213, -0.0002322229, -0.0002329046, -0.0002334665,
--0.0002339089, -0.0002342322, -0.0002344368, -0.0002345232, -0.0002344918,
--0.0002343433, -0.0002340783, -0.0002336975, -0.0002332015, -0.0002325913,
--0.0002318677, -0.0002310316, -0.0002300839, -0.0002290256, -0.0002278578,
--0.0002265817, -0.0002251983, -0.0002237089, -0.0002221147, -0.0002204171,
--0.0002186173, -0.0002167169, -0.0002147171, -0.0002126195, -0.0002104256,
--0.0002081370, -0.0002057553, -0.0002032820, -0.0002007190, -0.0001980679,
--0.0001953304, -0.0001925083, -0.0001896036, -0.0001866179, -0.0001835533,
--0.0001804116, -0.0001771947, -0.0001739047, -0.0001705435, -0.0001671132,
--0.0001636158, -0.0001600534, -0.0001564281, -0.0001527420, -0.0001489973,
--0.0001451961, -0.0001413406, -0.0001374329, -0.0001334754, -0.0001294702,
--0.0001254195, -0.0001213257, -0.0001171909, -0.0001130175, -0.0001088077,
--0.0001045638, -0.0001002881, -0.0000959829, -0.0000916505, -0.0000872932,
--0.0000829133, -0.0000785131, -0.0000740949, -0.0000696610, -0.0000652138,
--0.0000607554, -0.0000562883, -0.0000518146, -0.0000473367, -0.0000428568,
--0.0000383772, -0.0000339001, -0.0000294277, -0.0000249624, -0.0000205062,
--0.0000160614, -0.0000116301, -0.0000072145, -0.0000028167, 0.0000015611,
-0.0000059168, 0.0000102485, 0.0000145539, 0.0000188311, 0.0000230781,
-0.0000272929, 0.0000314736, 0.0000356181, 0.0000397247, 0.0000437914,
-0.0000478164, 0.0000517978, 0.0000557339, 0.0000596230, 0.0000634633,
-0.0000672531, 0.0000709908, 0.0000746747, 0.0000783033, 0.0000818750,
-0.0000853883, 0.0000888417, 0.0000922338, 0.0000955632, 0.0000988286,
-0.0001020285, 0.0001051617, 0.0001082270, 0.0001112231, 0.0001141489,
-0.0001170033, 0.0001197852, 0.0001224936, 0.0001251273, 0.0001276856,
-0.0001301674, 0.0001325720, 0.0001348984, 0.0001371460, 0.0001393138,
-0.0001414014, 0.0001434079, 0.0001453328, 0.0001471756, 0.0001489356,
-0.0001506125, 0.0001522058, 0.0001537151, 0.0001551400, 0.0001564803,
-0.0001577357, 0.0001589060, 0.0001599910, 0.0001609906, 0.0001619047,
-0.0001627333, 0.0001634764, 0.0001641339, 0.0001647061, 0.0001651931,
-0.0001655949, 0.0001659120, 0.0001661444, 0.0001662924, 0.0001663566,
-0.0001663371, 0.0001662345, 0.0001660492, 0.0001657817, 0.0001654325,
-0.0001650023, 0.0001644915, 0.0001639010, 0.0001632313, 0.0001624832,
-0.0001616575, 0.0001607549, 0.0001597764, 0.0001587227, 0.0001575947,
-0.0001563934, 0.0001551198, 0.0001537748, 0.0001523595, 0.0001508749,
-0.0001493222, 0.0001477024, 0.0001460166, 0.0001442661, 0.0001424521,
-0.0001405757, 0.0001386382, 0.0001366410, 0.0001345852, 0.0001324722,
-0.0001303034, 0.0001280801, 0.0001258038, 0.0001234757, 0.0001210974,
-0.0001186702, 0.0001161957, 0.0001136753, 0.0001111105, 0.0001085028,
-0.0001058537, 0.0001031648, 0.0001004377, 0.0000976737, 0.0000948747,
-0.0000920420, 0.0000891774, 0.0000862823, 0.0000833585, 0.0000804075,
-0.0000774309, 0.0000744303, 0.0000714075, 0.0000683639, 0.0000653013,
-0.0000622212, 0.0000591253, 0.0000560153, 0.0000528927, 0.0000497592,
-0.0000466164, 0.0000434660, 0.0000403095, 0.0000371486, 0.0000339848,
-0.0000308199, 0.0000276553, 0.0000244926, 0.0000213335, 0.0000181796,
-0.0000150322, 0.0000118931, 0.0000087637, 0.0000056456, 0.0000025402,
--0.0000005509, -0.0000036262, -0.0000066844, -0.0000097239, -0.0000127433,
--0.0000157412, -0.0000187162, -0.0000216669, -0.0000245920, -0.0000274901,
--0.0000303599, -0.0000332001, -0.0000360095, -0.0000387867, -0.0000415306,
--0.0000442399, -0.0000469135, -0.0000495501, -0.0000521487, -0.0000547082,
--0.0000572273, -0.0000597052, -0.0000621407, -0.0000645329, -0.0000668807,
--0.0000691832, -0.0000714395, -0.0000736486, -0.0000758098, -0.0000779221,
--0.0000799848, -0.0000819970, -0.0000839581, -0.0000858672, -0.0000877237,
--0.0000895269, -0.0000912761, -0.0000929709, -0.0000946105, -0.0000961945,
--0.0000977224, -0.0000991935, -0.0001006076, -0.0001019642, -0.0001032628,
--0.0001045032, -0.0001056850, -0.0001068078, -0.0001078715, -0.0001088758,
--0.0001098205, -0.0001107055, -0.0001115305, -0.0001122954, -0.0001130003,
--0.0001136450, -0.0001142295, -0.0001147539, -0.0001152181, -0.0001156222,
--0.0001159664, -0.0001162508, -0.0001164755, -0.0001166408, -0.0001167467,
--0.0001167937, -0.0001167819, -0.0001167117, -0.0001165834, -0.0001163974,
--0.0001161540, -0.0001158536, -0.0001154968, -0.0001150839, -0.0001146154,
--0.0001140920, -0.0001135140, -0.0001128821, -0.0001121969, -0.0001114590,
--0.0001106690, -0.0001098276, -0.0001089354, -0.0001079932, -0.0001070018,
--0.0001059617, -0.0001048739, -0.0001037391, -0.0001025581, -0.0001013318,
--0.0001000609, -0.0000987464, -0.0000973892, -0.0000959901, -0.0000945500,
--0.0000930699, -0.0000915507, -0.0000899935, -0.0000883990, -0.0000867685,
--0.0000851028, -0.0000834030, -0.0000816701, -0.0000799051, -0.0000781091,
--0.0000762832, -0.0000744284, -0.0000725458, -0.0000706365, -0.0000687015,
--0.0000667421, -0.0000647592, -0.0000627541, -0.0000607277, -0.0000586814,
--0.0000566161, -0.0000545330, -0.0000524333, -0.0000503180, -0.0000481885,
--0.0000460456, -0.0000438907, -0.0000417249, -0.0000395493, -0.0000373650,
--0.0000351732, -0.0000329751, -0.0000307717, -0.0000285642, -0.0000263537,
--0.0000241414, -0.0000219284, -0.0000197157, -0.0000175046, -0.0000152960,
--0.0000130912, -0.0000108911, -0.0000086969, -0.0000065096, -0.0000043304,
--0.0000021601, -0.0000000000
-};
/* DO NOT USE THE PRECOMPILED HEADER FOR THIS FILE! */
-#include <stdarg.h>
-
#define WIN32_NO_STATUS
#define _INC_WINDOWS
#define COM_NO_WINDOWS_H
#include <windef.h>
-#include <winbase.h>
-#include <wingdi.h>
-#include <objbase.h>
+#include <mmddk.h>
+#include <dsound.h>
#include <initguid.h>
-#include <mmdeviceapi.h>
-#include <audioclient.h>
-#include <devpkey.h>
+#include <dsdriver.h>
/* NO CODE HERE, THIS IS JUST REQUIRED FOR THE GUID DEFINITIONS */
#include "dsound_private.h"
-#include "fir.h"
-
void DSOUND_RecalcVolPan(PDSVOLUMEPAN volpan)
{
double temp;
TRACE("Vol=%d Pan=%d\n", volpan->lVolume, volpan->lPan);
}
+/** Convert a primary buffer position to a pointer position for device->mix_buffer
+ * device: DirectSoundDevice for which to calculate
+ * pos: Primary buffer position to converts
+ * Returns: Offset for mix_buffer
+ */
+DWORD DSOUND_bufpos_to_mixpos(const DirectSoundDevice* device, DWORD pos)
+{
+ DWORD ret = pos * 32 / device->pwfx->wBitsPerSample;
+ if (device->pwfx->wBitsPerSample == 32)
+ ret *= 2;
+ return ret;
+}
+
+/* NOTE: Not all secpos have to always be mapped to a bufpos, other way around is always the case
+ * DWORD64 is used here because a single DWORD wouldn't be big enough to fit the freqAcc for big buffers
+ */
+/** This function converts a 'native' sample pointer to a resampled pointer that fits for primary
+ * secmixpos is used to decide which freqAcc is needed
+ * overshot tells what the 'actual' secpos is now (optional)
+ */
+DWORD DSOUND_secpos_to_bufpos(const IDirectSoundBufferImpl *dsb, DWORD secpos, DWORD secmixpos, DWORD* overshot)
+{
+ DWORD64 framelen = secpos / dsb->pwfx->nBlockAlign;
+ DWORD64 freqAdjust = dsb->freqAdjust;
+ DWORD64 acc, freqAcc;
+
+ if (secpos < secmixpos)
+ freqAcc = dsb->freqAccNext;
+ else freqAcc = dsb->freqAcc;
+ acc = (framelen << DSOUND_FREQSHIFT) + (freqAdjust - 1 - freqAcc);
+ acc /= freqAdjust;
+ if (overshot)
+ {
+ DWORD64 oshot = acc * freqAdjust + freqAcc;
+ assert(oshot >= framelen << DSOUND_FREQSHIFT);
+ oshot -= framelen << DSOUND_FREQSHIFT;
+ *overshot = (DWORD)oshot;
+ assert(*overshot < dsb->freqAdjust);
+ }
+ return (DWORD)acc * dsb->device->pwfx->nBlockAlign;
+}
+
+/** Convert a resampled pointer that fits for primary to a 'native' sample pointer
+ * freqAccNext is used here rather than freqAcc: In case the app wants to fill up to
+ * the play position it won't overwrite it
+ */
+static DWORD DSOUND_bufpos_to_secpos(const IDirectSoundBufferImpl *dsb, DWORD bufpos)
+{
+ DWORD oAdv = dsb->device->pwfx->nBlockAlign, iAdv = dsb->pwfx->nBlockAlign, pos;
+ DWORD64 framelen;
+ DWORD64 acc;
+
+ framelen = bufpos/oAdv;
+ acc = framelen * (DWORD64)dsb->freqAdjust + (DWORD64)dsb->freqAccNext;
+ acc = acc >> DSOUND_FREQSHIFT;
+ pos = (DWORD)acc * iAdv;
+ if (pos >= dsb->buflen)
+ /* Because of differences between freqAcc and freqAccNext, this might happen */
+ pos = dsb->buflen - iAdv;
+ TRACE("Converted %d/%d to %d/%d\n", bufpos, dsb->tmp_buffer_len, pos, dsb->buflen);
+ return pos;
+}
+
+/**
+ * Move freqAccNext to freqAcc, and find new values for buffer length and freqAccNext
+ */
+static void DSOUND_RecalcFreqAcc(IDirectSoundBufferImpl *dsb)
+{
+ if (!dsb->freqneeded) return;
+ dsb->freqAcc = dsb->freqAccNext;
+ dsb->tmp_buffer_len = DSOUND_secpos_to_bufpos(dsb, dsb->buflen, 0, &dsb->freqAccNext);
+ TRACE("New freqadjust: %04x, new buflen: %d\n", dsb->freqAccNext, dsb->tmp_buffer_len);
+}
+
/**
* Recalculate the size for temporary buffer, and new writelead
* Should be called when one of the following things occur:
* - Primary buffer format is changed
* - This buffer format (frequency) is changed
+ *
+ * After this, DSOUND_MixToTemporary(dsb, 0, dsb->buflen) should
+ * be called to refill the temporary buffer with data.
*/
void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb)
{
- DWORD ichannels = dsb->pwfx->nChannels;
- DWORD ochannels = dsb->device->pwfx->nChannels;
+ BOOL needremix = TRUE, needresample = (dsb->freq != dsb->device->pwfx->nSamplesPerSec);
+ DWORD bAlign = dsb->pwfx->nBlockAlign, pAlign = dsb->device->pwfx->nBlockAlign;
WAVEFORMATEXTENSIBLE *pwfxe;
BOOL ieee = FALSE;
TRACE("(%p)\n",dsb);
pwfxe = (WAVEFORMATEXTENSIBLE *) dsb->pwfx;
- dsb->freqAdjust = (float)dsb->freq / dsb->device->pwfx->nSamplesPerSec;
if ((pwfxe->Format.wFormatTag == WAVE_FORMAT_IEEE_FLOAT) || ((pwfxe->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE)
&& (IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))))
ieee = TRUE;
- /**
- * Recalculate FIR step and gain.
- *
- * firstep says how many points of the FIR exist per one
- * sample in the secondary buffer. firgain specifies what
- * to multiply the FIR output by in order to attenuate it correctly.
- */
- if (dsb->freqAdjust > 1.0f) {
- /**
- * Yes, round it a bit to make sure that the
- * linear interpolation factor never changes.
- */
- dsb->firstep = ceil(fir_step / dsb->freqAdjust);
- } else {
- dsb->firstep = fir_step;
- }
- dsb->firgain = (float)dsb->firstep / fir_step;
-
/* calculate the 10ms write lead */
dsb->writelead = (dsb->freq / 100) * dsb->pwfx->nBlockAlign;
- dsb->freqAcc = 0;
+ if ((dsb->pwfx->wBitsPerSample == dsb->device->pwfx->wBitsPerSample) &&
+ (dsb->pwfx->nChannels == dsb->device->pwfx->nChannels) && !needresample && !ieee)
+ needremix = FALSE;
+ HeapFree(GetProcessHeap(), 0, dsb->tmp_buffer);
+ dsb->tmp_buffer = NULL;
+ dsb->max_buffer_len = dsb->freqAcc = dsb->freqAccNext = 0;
+ dsb->freqneeded = needresample;
- dsb->get_aux = ieee ? getbpp[4] : getbpp[dsb->pwfx->wBitsPerSample/8 - 1];
- dsb->put_aux = putieee32;
+ if (ieee)
+ dsb->convert = convertbpp[4][dsb->device->pwfx->wBitsPerSample/8 - 1];
+ else
+ dsb->convert = convertbpp[dsb->pwfx->wBitsPerSample/8 - 1][dsb->device->pwfx->wBitsPerSample/8 - 1];
- dsb->get = dsb->get_aux;
- dsb->put = dsb->put_aux;
+ dsb->resampleinmixer = FALSE;
- if (ichannels == ochannels)
+ if (needremix)
{
- dsb->mix_channels = ichannels;
- if (ichannels > 32) {
- FIXME("Copying %u channels is unsupported, limiting to first 32\n", ichannels);
- dsb->mix_channels = 32;
- }
- }
- else if (ichannels == 1)
- {
- dsb->mix_channels = 1;
- dsb->put = put_mono2stereo;
- }
- else if (ochannels == 1)
- {
- dsb->mix_channels = 1;
- dsb->get = get_mono;
- }
- else
- {
- if (ichannels > 2)
- FIXME("Conversion from %u to %u channels is not implemented, falling back to stereo\n", ichannels, ochannels);
- dsb->mix_channels = 2;
+ if (needresample)
+ DSOUND_RecalcFreqAcc(dsb);
+ else
+ dsb->tmp_buffer_len = dsb->buflen / bAlign * pAlign;
+ dsb->max_buffer_len = dsb->tmp_buffer_len;
+ if ((dsb->max_buffer_len <= dsb->device->buflen || dsb->max_buffer_len < ds_snd_shadow_maxsize * 1024 * 1024) && ds_snd_shadow_maxsize >= 0)
+ dsb->tmp_buffer = HeapAlloc(GetProcessHeap(), 0, dsb->max_buffer_len);
+ if (dsb->tmp_buffer)
+ FillMemory(dsb->tmp_buffer, dsb->tmp_buffer_len, dsb->device->pwfx->wBitsPerSample == 8 ? 128 : 0);
+ else
+ dsb->resampleinmixer = TRUE;
}
+ else dsb->max_buffer_len = dsb->tmp_buffer_len = dsb->buflen;
+ dsb->buf_mixpos = DSOUND_secpos_to_bufpos(dsb, dsb->sec_mixpos, 0, NULL);
}
/**
}
}
-static inline float get_current_sample(const IDirectSoundBufferImpl *dsb,
- DWORD mixpos, DWORD channel)
-{
- if (mixpos >= dsb->buflen && !(dsb->playflags & DSBPLAY_LOOPING))
- return 0.0f;
- return dsb->get(dsb, mixpos % dsb->buflen, channel);
-}
-
-static UINT cp_fields_noresample(IDirectSoundBufferImpl *dsb, UINT count)
-{
- UINT istride = dsb->pwfx->nBlockAlign;
- UINT ostride = dsb->device->pwfx->nChannels * sizeof(float);
- DWORD channel, i;
- for (i = 0; i < count; i++)
- for (channel = 0; channel < dsb->mix_channels; channel++)
- dsb->put(dsb, i * ostride, channel, get_current_sample(dsb,
- dsb->sec_mixpos + i * istride, channel));
- return count;
-}
-
-static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count, float *freqAcc)
+/**
+ * Copy a single frame from the given input buffer to the given output buffer.
+ * Translate 8 <-> 16 bits and mono <-> stereo
+ */
+static inline void cp_fields(const IDirectSoundBufferImpl *dsb, const BYTE *ibuf, BYTE *obuf,
+ UINT istride, UINT ostride, UINT count, UINT freqAcc, UINT adj)
{
- UINT i, channel;
- UINT istride = dsb->pwfx->nBlockAlign;
- UINT ostride = dsb->device->pwfx->nChannels * sizeof(float);
-
- float freqAdjust = dsb->freqAdjust;
- float freqAcc_start = *freqAcc;
- float freqAcc_end = freqAcc_start + count * freqAdjust;
- UINT dsbfirstep = dsb->firstep;
- UINT channels = dsb->mix_channels;
- UINT max_ipos = freqAcc_start + count * freqAdjust;
-
- UINT fir_cachesize = (fir_len + dsbfirstep - 2) / dsbfirstep;
- UINT required_input = max_ipos + fir_cachesize;
-
- float* intermediate = HeapAlloc(GetProcessHeap(), 0,
- sizeof(float) * required_input * channels);
-
- float* fir_copy = HeapAlloc(GetProcessHeap(), 0,
- sizeof(float) * fir_cachesize);
-
- /* Important: this buffer MUST be non-interleaved
- * if you want -msse3 to have any effect.
- * This is good for CPU cache effects, too.
- */
- float* itmp = intermediate;
- for (channel = 0; channel < channels; channel++)
- for (i = 0; i < required_input; i++)
- *(itmp++) = get_current_sample(dsb,
- dsb->sec_mixpos + i * istride, channel);
-
- for(i = 0; i < count; ++i) {
- float total_fir_steps = (freqAcc_start + i * freqAdjust) * dsbfirstep;
- UINT int_fir_steps = total_fir_steps;
- UINT ipos = int_fir_steps / dsbfirstep;
-
- UINT idx = (ipos + 1) * dsbfirstep - int_fir_steps - 1;
- float rem = int_fir_steps + 1.0 - total_fir_steps;
-
- int fir_used = 0;
- while (idx < fir_len - 1) {
- fir_copy[fir_used++] = fir[idx] * (1.0 - rem) + fir[idx + 1] * rem;
- idx += dsb->firstep;
- }
-
- assert(fir_used <= fir_cachesize);
- assert(ipos + fir_used <= required_input);
-
- for (channel = 0; channel < dsb->mix_channels; channel++) {
- int j;
- float sum = 0.0;
- float* cache = &intermediate[channel * required_input + ipos];
- for (j = 0; j < fir_used; j++)
- sum += fir_copy[j] * cache[j];
- dsb->put(dsb, i * ostride, channel, sum * dsb->firgain);
- }
+ DirectSoundDevice *device = dsb->device;
+ INT istep = dsb->pwfx->wBitsPerSample / 8, ostep = device->pwfx->wBitsPerSample / 8;
+
+ if (device->pwfx->nChannels == dsb->pwfx->nChannels ||
+ (device->pwfx->nChannels == 2 && dsb->pwfx->nChannels == 6) ||
+ (device->pwfx->nChannels == 8 && dsb->pwfx->nChannels == 2) ||
+ (device->pwfx->nChannels == 6 && dsb->pwfx->nChannels == 2)) {
+ dsb->convert(ibuf, obuf, istride, ostride, count, freqAcc, adj);
+ if (device->pwfx->nChannels == 2 || dsb->pwfx->nChannels == 2)
+ dsb->convert(ibuf + istep, obuf + ostep, istride, ostride, count, freqAcc, adj);
+ return;
}
- freqAcc_end -= (int)freqAcc_end;
- *freqAcc = freqAcc_end;
-
- HeapFree(GetProcessHeap(), 0, fir_copy);
- HeapFree(GetProcessHeap(), 0, intermediate);
-
- return max_ipos;
-}
-
-static void cp_fields(IDirectSoundBufferImpl *dsb, UINT count, float *freqAcc)
-{
- DWORD ipos, adv;
+ if (device->pwfx->nChannels == 1 && dsb->pwfx->nChannels == 2)
+ {
+ dsb->convert(ibuf, obuf, istride, ostride, count, freqAcc, adj);
+ return;
+ }
- if (dsb->freqAdjust == 1.0)
- adv = cp_fields_noresample(dsb, count); /* *freqAcc is unmodified */
- else
- adv = cp_fields_resample(dsb, count, freqAcc);
-
- ipos = dsb->sec_mixpos + adv * dsb->pwfx->nBlockAlign;
- if (ipos >= dsb->buflen) {
- if (dsb->playflags & DSBPLAY_LOOPING)
- ipos %= dsb->buflen;
- else {
- ipos = 0;
- dsb->state = STATE_STOPPED;
- }
+ if (device->pwfx->nChannels == 2 && dsb->pwfx->nChannels == 1)
+ {
+ dsb->convert(ibuf, obuf, istride, ostride, count, freqAcc, adj);
+ dsb->convert(ibuf, obuf + ostep, istride, ostride, count, freqAcc, adj);
+ return;
}
- dsb->sec_mixpos = ipos;
+ WARN("Unable to remap channels: device=%u, buffer=%u\n", device->pwfx->nChannels,
+ dsb->pwfx->nChannels);
}
/**
*
* NOTE: writepos + len <= buflen. When called by mixer, MixOne makes sure of this.
*/
-static void DSOUND_MixToTemporary(IDirectSoundBufferImpl *dsb, DWORD frames)
+void DSOUND_MixToTemporary(const IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD len, BOOL inmixer)
{
- UINT size_bytes = frames * sizeof(float) * dsb->device->pwfx->nChannels;
+ INT size;
+ BYTE *ibp, *obp, *obp_begin;
+ INT iAdvance = dsb->pwfx->nBlockAlign;
+ INT oAdvance = dsb->device->pwfx->nBlockAlign;
+ DWORD freqAcc, target_writepos = 0, overshot, maxlen;
+
+ /* We resample only when needed */
+ if ((dsb->tmp_buffer && inmixer) || (!dsb->tmp_buffer && !inmixer) || dsb->resampleinmixer != inmixer)
+ return;
+
+ assert(writepos + len <= dsb->buflen);
+ if (inmixer && writepos + len < dsb->buflen)
+ len += dsb->pwfx->nBlockAlign;
+
+ maxlen = DSOUND_secpos_to_bufpos(dsb, len, 0, NULL);
- if (dsb->device->tmp_buffer_len < size_bytes || !dsb->device->tmp_buffer)
+ ibp = dsb->buffer->memory + writepos;
+ if (!inmixer)
+ obp_begin = dsb->tmp_buffer;
+ else if (dsb->device->tmp_buffer_len < maxlen || !dsb->device->tmp_buffer)
{
- dsb->device->tmp_buffer_len = size_bytes;
+ dsb->device->tmp_buffer_len = maxlen;
if (dsb->device->tmp_buffer)
- dsb->device->tmp_buffer = HeapReAlloc(GetProcessHeap(), 0, dsb->device->tmp_buffer, size_bytes);
+ dsb->device->tmp_buffer = HeapReAlloc(GetProcessHeap(), 0, dsb->device->tmp_buffer, maxlen);
else
- dsb->device->tmp_buffer = HeapAlloc(GetProcessHeap(), 0, size_bytes);
+ dsb->device->tmp_buffer = HeapAlloc(GetProcessHeap(), 0, maxlen);
+ obp_begin = dsb->device->tmp_buffer;
+ }
+ else
+ obp_begin = dsb->device->tmp_buffer;
+
+ TRACE("(%p, %p)\n", dsb, ibp);
+ size = len / iAdvance;
+
+ /* Check for same sample rate */
+ if (dsb->freq == dsb->device->pwfx->nSamplesPerSec) {
+ TRACE("(%p) Same sample rate %d = primary %d\n", dsb,
+ dsb->freq, dsb->device->pwfx->nSamplesPerSec);
+ obp = obp_begin;
+ if (!inmixer)
+ obp += writepos/iAdvance*oAdvance;
+
+ cp_fields(dsb, ibp, obp, iAdvance, oAdvance, size, 0, 1 << DSOUND_FREQSHIFT);
+ return;
+ }
+
+ /* Mix in different sample rates */
+ TRACE("(%p) Adjusting frequency: %d -> %d\n", dsb, dsb->freq, dsb->device->pwfx->nSamplesPerSec);
+
+ target_writepos = DSOUND_secpos_to_bufpos(dsb, writepos, dsb->sec_mixpos, &freqAcc);
+ overshot = freqAcc >> DSOUND_FREQSHIFT;
+ if (overshot)
+ {
+ if (overshot >= size)
+ return;
+ size -= overshot;
+ writepos += overshot * iAdvance;
+ if (writepos >= dsb->buflen)
+ return;
+ ibp = dsb->buffer->memory + writepos;
+ freqAcc &= (1 << DSOUND_FREQSHIFT) - 1;
+ TRACE("Overshot: %d, freqAcc: %04x\n", overshot, freqAcc);
}
- cp_fields(dsb, frames, &dsb->freqAcc);
+ if (!inmixer)
+ obp = obp_begin + target_writepos;
+ else obp = obp_begin;
+
+ /* FIXME: Small problem here when we're overwriting buf_mixpos, it then STILL uses old freqAcc, not sure if it matters or not */
+ cp_fields(dsb, ibp, obp, iAdvance, oAdvance, size, freqAcc, dsb->freqAdjust);
}
-static void DSOUND_MixerVol(const IDirectSoundBufferImpl *dsb, INT frames)
+/** Apply volume to the given soundbuffer from (primary) position writepos and length len
+ * Returns: NULL if no volume needs to be applied
+ * or else a memory handle that holds 'len' volume adjusted buffer */
+static LPBYTE DSOUND_MixerVol(const IDirectSoundBufferImpl *dsb, INT len)
{
INT i;
- float vLeft, vRight;
- UINT channels = dsb->device->pwfx->nChannels, chan;
+ BYTE *bpc;
+ INT16 *bps, *mems;
+ DWORD vLeft, vRight;
+ INT nChannels = dsb->device->pwfx->nChannels;
+ LPBYTE mem = (dsb->tmp_buffer ? dsb->tmp_buffer : dsb->buffer->memory) + dsb->buf_mixpos;
- TRACE("(%p,%d)\n",dsb,frames);
+ if (dsb->resampleinmixer)
+ mem = dsb->device->tmp_buffer;
+
+ TRACE("(%p,%d)\n",dsb,len);
TRACE("left = %x, right = %x\n", dsb->volpan.dwTotalLeftAmpFactor,
dsb->volpan.dwTotalRightAmpFactor);
if ((!(dsb->dsbd.dwFlags & DSBCAPS_CTRLPAN) || (dsb->volpan.lPan == 0)) &&
(!(dsb->dsbd.dwFlags & DSBCAPS_CTRLVOLUME) || (dsb->volpan.lVolume == 0)) &&
!(dsb->dsbd.dwFlags & DSBCAPS_CTRL3D))
- return; /* Nothing to do */
+ return NULL; /* Nothing to do */
- if (channels != 1 && channels != 2)
+ if (nChannels != 1 && nChannels != 2)
{
- FIXME("There is no support for %u channels\n", channels);
- return;
+ FIXME("There is no support for %d channels\n", nChannels);
+ return NULL;
}
- vLeft = dsb->volpan.dwTotalLeftAmpFactor / ((float)0xFFFF);
- vRight = dsb->volpan.dwTotalRightAmpFactor / ((float)0xFFFF);
- for(i = 0; i < frames; ++i){
- for(chan = 0; chan < channels; ++chan){
- if(chan == 0)
- dsb->device->tmp_buffer[i * channels + chan] *= vLeft;
- else
- dsb->device->tmp_buffer[i * channels + chan] *= vRight;
+ if (dsb->device->pwfx->wBitsPerSample != 8 && dsb->device->pwfx->wBitsPerSample != 16)
+ {
+ FIXME("There is no support for %d bpp\n", dsb->device->pwfx->wBitsPerSample);
+ return NULL;
+ }
+
+ if (dsb->device->tmp_buffer_len < len || !dsb->device->tmp_buffer)
+ {
+ /* If we just resampled in DSOUND_MixToTemporary, we shouldn't need to resize here */
+ assert(!dsb->resampleinmixer);
+ dsb->device->tmp_buffer_len = len;
+ if (dsb->device->tmp_buffer)
+ dsb->device->tmp_buffer = HeapReAlloc(GetProcessHeap(), 0, dsb->device->tmp_buffer, len);
+ else
+ dsb->device->tmp_buffer = HeapAlloc(GetProcessHeap(), 0, len);
+ }
+
+ bpc = dsb->device->tmp_buffer;
+ bps = (INT16 *)bpc;
+ mems = (INT16 *)mem;
+ vLeft = dsb->volpan.dwTotalLeftAmpFactor;
+ if (nChannels > 1)
+ vRight = dsb->volpan.dwTotalRightAmpFactor;
+ else
+ vRight = vLeft;
+
+ switch (dsb->device->pwfx->wBitsPerSample) {
+ case 8:
+ /* 8-bit WAV is unsigned, but we need to operate */
+ /* on signed data for this to work properly */
+ for (i = 0; i < len-1; i+=2) {
+ *(bpc++) = (((*(mem++) - 128) * vLeft) >> 16) + 128;
+ *(bpc++) = (((*(mem++) - 128) * vRight) >> 16) + 128;
}
+ if (len % 2 == 1 && nChannels == 1)
+ *(bpc++) = (((*(mem++) - 128) * vLeft) >> 16) + 128;
+ break;
+ case 16:
+ /* 16-bit WAV is signed -- much better */
+ for (i = 0; i < len-3; i += 4) {
+ *(bps++) = (*(mems++) * vLeft) >> 16;
+ *(bps++) = (*(mems++) * vRight) >> 16;
+ }
+ if (len % 4 == 2 && nChannels == 1)
+ *(bps++) = ((INT)*(mems++) * vLeft) >> 16;
+ break;
}
+ return dsb->device->tmp_buffer;
}
/**
*/
static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD fraglen)
{
- INT len = fraglen;
- float *ibuf;
- DWORD oldpos;
- UINT frames = fraglen / dsb->device->pwfx->nBlockAlign;
+ INT len = fraglen, ilen;
+ BYTE *ibuf = (dsb->tmp_buffer ? dsb->tmp_buffer : dsb->buffer->memory) + dsb->buf_mixpos, *volbuf;
+ DWORD oldpos, mixbufpos;
- TRACE("sec_mixpos=%d/%d\n", dsb->sec_mixpos, dsb->buflen);
+ TRACE("buf_mixpos=%d/%d sec_mixpos=%d/%d\n", dsb->buf_mixpos, dsb->tmp_buffer_len, dsb->sec_mixpos, dsb->buflen);
TRACE("(%p,%d,%d)\n",dsb,writepos,fraglen);
+ assert(dsb->buf_mixpos + len <= dsb->tmp_buffer_len);
+
if (len % dsb->device->pwfx->nBlockAlign) {
INT nBlockAlign = dsb->device->pwfx->nBlockAlign;
ERR("length not a multiple of block size, len = %d, block size = %d\n", len, nBlockAlign);
}
/* Resample buffer to temporary buffer specifically allocated for this purpose, if needed */
- oldpos = dsb->sec_mixpos;
-
- DSOUND_MixToTemporary(dsb, frames);
- ibuf = dsb->device->tmp_buffer;
+ DSOUND_MixToTemporary(dsb, dsb->sec_mixpos, DSOUND_bufpos_to_secpos(dsb, dsb->buf_mixpos+len) - dsb->sec_mixpos, TRUE);
+ if (dsb->resampleinmixer)
+ ibuf = dsb->device->tmp_buffer;
/* Apply volume if needed */
- DSOUND_MixerVol(dsb, frames);
+ volbuf = DSOUND_MixerVol(dsb, len);
+ if (volbuf)
+ ibuf = volbuf;
+
+ mixbufpos = DSOUND_bufpos_to_mixpos(dsb->device, writepos);
+ /* Now mix the temporary buffer into the devices main buffer */
+ if ((writepos + len) <= dsb->device->buflen)
+ dsb->device->mixfunction(ibuf, dsb->device->mix_buffer + mixbufpos, len);
+ else
+ {
+ DWORD todo = dsb->device->buflen - writepos;
+ dsb->device->mixfunction(ibuf, dsb->device->mix_buffer + mixbufpos, todo);
+ dsb->device->mixfunction(ibuf + todo, dsb->device->mix_buffer, len - todo);
+ }
- mixieee32(ibuf, dsb->device->mix_buffer, frames * dsb->device->pwfx->nChannels);
+ oldpos = dsb->sec_mixpos;
+ dsb->buf_mixpos += len;
+
+ if (dsb->buf_mixpos >= dsb->tmp_buffer_len) {
+ if (dsb->buf_mixpos > dsb->tmp_buffer_len)
+ ERR("Mixpos (%u) past buflen (%u), capping...\n", dsb->buf_mixpos, dsb->tmp_buffer_len);
+ if (dsb->playflags & DSBPLAY_LOOPING) {
+ dsb->buf_mixpos -= dsb->tmp_buffer_len;
+ } else if (dsb->buf_mixpos >= dsb->tmp_buffer_len) {
+ dsb->buf_mixpos = dsb->sec_mixpos = 0;
+ dsb->state = STATE_STOPPED;
+ }
+ DSOUND_RecalcFreqAcc(dsb);
+ }
+ dsb->sec_mixpos = DSOUND_bufpos_to_secpos(dsb, dsb->buf_mixpos);
+ ilen = DSOUND_BufPtrDiff(dsb->buflen, dsb->sec_mixpos, oldpos);
/* check for notification positions */
if (dsb->dsbd.dwFlags & DSBCAPS_CTRLPOSITIONNOTIFY &&
dsb->state != STATE_STARTING) {
- INT ilen = DSOUND_BufPtrDiff(dsb->buflen, dsb->sec_mixpos, oldpos);
DSOUND_CheckEvent(dsb, oldpos, ilen);
}
+ /* increase mix position */
+ dsb->primary_mixpos += len;
+ if (dsb->primary_mixpos >= dsb->device->buflen)
+ dsb->primary_mixpos -= dsb->device->buflen;
return len;
}
*/
static DWORD DSOUND_MixOne(IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD mixlen)
{
- DWORD primary_done = 0;
+ /* The buffer's primary_mixpos may be before or after the device
+ * buffer's mixpos, but both must be ahead of writepos. */
+ DWORD primary_done;
TRACE("(%p,%d,%d)\n",dsb,writepos,mixlen);
- TRACE("writepos=%d, mixlen=%d\n", writepos, mixlen);
- TRACE("looping=%d, leadin=%d\n", dsb->playflags, dsb->leadin);
+ TRACE("writepos=%d, buf_mixpos=%d, primary_mixpos=%d, mixlen=%d\n", writepos, dsb->buf_mixpos, dsb->primary_mixpos, mixlen);
+ TRACE("looping=%d, leadin=%d, buflen=%d\n", dsb->playflags, dsb->leadin, dsb->tmp_buffer_len);
/* If leading in, only mix about 20 ms, and 'skip' mixing the rest, for more fluid pointer advancement */
- /* FIXME: Is this needed? */
- if (dsb->leadin && dsb->state == STATE_STARTING) {
- if (mixlen > 2 * dsb->device->fraglen) {
- primary_done = mixlen - 2 * dsb->device->fraglen;
- mixlen = 2 * dsb->device->fraglen;
- writepos += primary_done;
- dsb->sec_mixpos += (primary_done / dsb->device->pwfx->nBlockAlign) *
- dsb->pwfx->nBlockAlign * dsb->freqAdjust;
+ if (dsb->leadin && dsb->state == STATE_STARTING)
+ {
+ if (mixlen > 2 * dsb->device->fraglen)
+ {
+ dsb->primary_mixpos += mixlen - 2 * dsb->device->fraglen;
+ dsb->primary_mixpos %= dsb->device->buflen;
}
}
-
dsb->leadin = FALSE;
- TRACE("mixlen (primary) = %i\n", mixlen);
+ /* calculate how much pre-buffering has already been done for this buffer */
+ primary_done = DSOUND_BufPtrDiff(dsb->device->buflen, dsb->primary_mixpos, writepos);
+
+ /* sanity */
+ if(mixlen < primary_done)
+ {
+ /* Should *NEVER* happen */
+ ERR("Fatal error. Under/Overflow? primary_done=%d, mixpos=%d/%d (%d/%d), primary_mixpos=%d, writepos=%d, mixlen=%d\n", primary_done,dsb->buf_mixpos,dsb->tmp_buffer_len,dsb->sec_mixpos, dsb->buflen, dsb->primary_mixpos, writepos, mixlen);
+ dsb->primary_mixpos = writepos + mixlen;
+ dsb->primary_mixpos %= dsb->device->buflen;
+ return mixlen;
+ }
+
+ /* take into account already mixed data */
+ mixlen -= primary_done;
+
+ TRACE("primary_done=%d, mixlen (primary) = %i\n", primary_done, mixlen);
+
+ if (!mixlen)
+ return primary_done;
/* First try to mix to the end of the buffer if possible
* Theoretically it would allow for better optimization
*/
- primary_done += DSOUND_MixInBuffer(dsb, writepos, mixlen);
+ if (mixlen + dsb->buf_mixpos >= dsb->tmp_buffer_len)
+ {
+ DWORD newmixed, mixfirst = dsb->tmp_buffer_len - dsb->buf_mixpos;
+ newmixed = DSOUND_MixInBuffer(dsb, dsb->primary_mixpos, mixfirst);
+ mixlen -= newmixed;
+
+ if (dsb->playflags & DSBPLAY_LOOPING)
+ while (newmixed && mixlen)
+ {
+ mixfirst = (dsb->tmp_buffer_len < mixlen ? dsb->tmp_buffer_len : mixlen);
+ newmixed = DSOUND_MixInBuffer(dsb, dsb->primary_mixpos, mixfirst);
+ mixlen -= newmixed;
+ }
+ }
+ else DSOUND_MixInBuffer(dsb, dsb->primary_mixpos, mixlen);
+
+ /* re-calculate the primary done */
+ primary_done = DSOUND_BufPtrDiff(dsb->device->buflen, dsb->primary_mixpos, writepos);
- TRACE("total mixed data=%d\n", primary_done);
+ TRACE("new primary_mixpos=%d, total mixed data=%d\n", dsb->primary_mixpos, primary_done);
/* Report back the total prebuffered amount for this buffer */
return primary_done;
* Returns: the length beyond the writepos that was mixed to.
*/
-static void DSOUND_MixToPrimary(const DirectSoundDevice *device, DWORD writepos, DWORD mixlen, BOOL recover, BOOL *all_stopped)
+static DWORD DSOUND_MixToPrimary(const DirectSoundDevice *device, DWORD writepos, DWORD mixlen, BOOL recover, BOOL *all_stopped)
{
- INT i;
+ INT i, len;
+ DWORD minlen = 0;
IDirectSoundBufferImpl *dsb;
/* unless we find a running buffer, all have stopped */
TRACE("MixToPrimary for %p, state=%d\n", dsb, dsb->state);
- if (dsb->buflen && dsb->state) {
+ if (dsb->buflen && dsb->state && !dsb->hwbuf) {
TRACE("Checking %p, mixlen=%d\n", dsb, mixlen);
RtlAcquireResourceShared(&dsb->lock, TRUE);
/* if buffer is stopping it is stopped now */
DSOUND_CheckEvent(dsb, 0, 0);
} else if (dsb->state != STATE_STOPPED) {
+ /* if recovering, reset the mix position */
+ if ((dsb->state == STATE_STARTING) || recover) {
+ dsb->primary_mixpos = writepos;
+ }
+
/* if the buffer was starting, it must be playing now */
if (dsb->state == STATE_STARTING)
dsb->state = STATE_PLAYING;
/* mix next buffer into the main buffer */
- DSOUND_MixOne(dsb, writepos, mixlen);
+ len = DSOUND_MixOne(dsb, writepos, mixlen);
+
+ if (!minlen) minlen = len;
+
+ /* record the minimum length mixed from all buffers */
+ /* we only want to return the length which *all* buffers have mixed */
+ else if (len) minlen = (len < minlen) ? len : minlen;
*all_stopped = FALSE;
}
RtlReleaseResource(&dsb->lock);
}
}
+
+ TRACE("Mixed at least %d from all buffers\n", minlen);
+ return minlen;
}
/**
static void DSOUND_WaveQueue(DirectSoundDevice *device, BOOL force)
{
- DWORD prebuf_frames, prebuf_bytes, read_offs_bytes;
- BYTE *buffer;
- HRESULT hr;
-
+ DWORD prebuf_frags, wave_writepos, wave_fragpos, i;
TRACE("(%p)\n", device);
- read_offs_bytes = (device->playing_offs_bytes + device->in_mmdev_bytes) % device->buflen;
+ /* calculate the current wave frag position */
+ wave_fragpos = (device->pwplay + device->pwqueue) % device->helfrags;
- TRACE("read_offs_bytes = %u, playing_offs_bytes = %u, in_mmdev_bytes: %u, prebuf = %u\n",
- read_offs_bytes, device->playing_offs_bytes, device->in_mmdev_bytes, device->prebuf);
+ /* calculate the current wave write position */
+ wave_writepos = wave_fragpos * device->fraglen;
+
+ TRACE("wave_fragpos = %i, wave_writepos = %i, pwqueue = %i, prebuf = %i\n",
+ wave_fragpos, wave_writepos, device->pwqueue, device->prebuf);
if (!force)
{
- if(device->mixpos < device->playing_offs_bytes)
- prebuf_bytes = device->mixpos + device->buflen - device->playing_offs_bytes;
- else
- prebuf_bytes = device->mixpos - device->playing_offs_bytes;
+ /* check remaining prebuffered frags */
+ prebuf_frags = device->mixpos / device->fraglen;
+ if (prebuf_frags == device->helfrags)
+ --prebuf_frags;
+ TRACE("wave_fragpos = %d, mixpos_frags = %d\n", wave_fragpos, prebuf_frags);
+ if (prebuf_frags < wave_fragpos)
+ prebuf_frags += device->helfrags;
+ prebuf_frags -= wave_fragpos;
+ TRACE("wanted prebuf_frags = %d\n", prebuf_frags);
}
else
/* buffer the maximum amount of frags */
- prebuf_bytes = device->prebuf * device->fraglen;
+ prebuf_frags = device->prebuf;
/* limit to the queue we have left */
- if(device->in_mmdev_bytes + prebuf_bytes > device->prebuf * device->fraglen)
- prebuf_bytes = device->prebuf * device->fraglen - device->in_mmdev_bytes;
+ if ((prebuf_frags + device->pwqueue) > device->prebuf)
+ prebuf_frags = device->prebuf - device->pwqueue;
- TRACE("prebuf_bytes = %u\n", prebuf_bytes);
+ TRACE("prebuf_frags = %i\n", prebuf_frags);
- if(!prebuf_bytes)
- return;
+ /* adjust queue */
+ device->pwqueue += prebuf_frags;
- device->in_mmdev_bytes += prebuf_bytes;
-
- if(prebuf_bytes + read_offs_bytes > device->buflen){
- DWORD chunk_bytes = device->buflen - read_offs_bytes;
- prebuf_frames = chunk_bytes / device->pwfx->nBlockAlign;
- prebuf_bytes -= chunk_bytes;
- }else{
- prebuf_frames = prebuf_bytes / device->pwfx->nBlockAlign;
- prebuf_bytes = 0;
- }
-
- hr = IAudioRenderClient_GetBuffer(device->render, prebuf_frames, &buffer);
- if(FAILED(hr)){
- WARN("GetBuffer failed: %08x\n", hr);
- return;
- }
-
- memcpy(buffer, device->buffer + read_offs_bytes,
- prebuf_frames * device->pwfx->nBlockAlign);
+ /* get out of CS when calling the wave system */
+ LeaveCriticalSection(&(device->mixlock));
+ /* **** */
- hr = IAudioRenderClient_ReleaseBuffer(device->render, prebuf_frames, 0);
- if(FAILED(hr)){
- WARN("ReleaseBuffer failed: %08x\n", hr);
- return;
+ /* queue up the new buffers */
+ for(i=0; i<prebuf_frags; i++){
+ TRACE("queueing wave buffer %i\n", wave_fragpos);
+ waveOutWrite(device->hwo, &device->pwave[wave_fragpos], sizeof(WAVEHDR));
+ wave_fragpos++;
+ wave_fragpos %= device->helfrags;
}
- /* check if anything wrapped */
- if(prebuf_bytes > 0){
- prebuf_frames = prebuf_bytes / device->pwfx->nBlockAlign;
-
- hr = IAudioRenderClient_GetBuffer(device->render, prebuf_frames, &buffer);
- if(FAILED(hr)){
- WARN("GetBuffer failed: %08x\n", hr);
- return;
- }
-
- memcpy(buffer, device->buffer, prebuf_frames * device->pwfx->nBlockAlign);
-
- hr = IAudioRenderClient_ReleaseBuffer(device->render, prebuf_frames, 0);
- if(FAILED(hr)){
- WARN("ReleaseBuffer failed: %08x\n", hr);
- return;
- }
- }
+ /* **** */
+ EnterCriticalSection(&(device->mixlock));
- TRACE("in_mmdev_bytes now = %i\n", device->in_mmdev_bytes);
+ TRACE("queue now = %i\n", device->pwqueue);
}
/**
* Perform mixing for a Direct Sound device. That is, go through all the
* secondary buffers (the sound bites currently playing) and mix them in
* to the primary buffer (the device buffer).
- *
- * The mixing procedure goes:
- *
- * secondary->buffer (secondary format)
- * =[Resample]=> device->tmp_buffer (float format)
- * =[Volume]=> device->tmp_buffer (float format)
- * =[Mix]=> device->mix_buffer (float format)
- * =[Reformat]=> device->buffer (device format)
*/
static void DSOUND_PerformMix(DirectSoundDevice *device)
{
- UINT32 pad, to_mix_frags, to_mix_bytes;
- HRESULT hr;
-
TRACE("(%p)\n", device);
/* **** */
- EnterCriticalSection(&device->mixlock);
-
- hr = IAudioClient_GetCurrentPadding(device->client, &pad);
- if(FAILED(hr)){
- WARN("GetCurrentPadding failed: %08x\n", hr);
- LeaveCriticalSection(&device->mixlock);
- return;
- }
-
- to_mix_frags = device->prebuf - (pad * device->pwfx->nBlockAlign + device->fraglen - 1) / device->fraglen;
-
- to_mix_bytes = to_mix_frags * device->fraglen;
-
- if(device->in_mmdev_bytes > 0){
- DWORD delta_bytes = min(to_mix_bytes, device->in_mmdev_bytes);
- device->in_mmdev_bytes -= delta_bytes;
- device->playing_offs_bytes += delta_bytes;
- device->playing_offs_bytes %= device->buflen;
- }
+ EnterCriticalSection(&(device->mixlock));
if (device->priolevel != DSSCL_WRITEPRIMARY) {
BOOL recover = FALSE, all_stopped = FALSE;
- DWORD playpos, writepos, writelead, maxq, prebuff_max, prebuff_left, size1, size2;
+ DWORD playpos, writepos, writelead, maxq, frag, prebuff_max, prebuff_left, size1, size2, mixplaypos, mixplaypos2;
LPVOID buf1, buf2;
+ BOOL lock = (device->hwbuf && !(device->drvdesc.dwFlags & DSDDESC_DONTNEEDPRIMARYLOCK));
int nfiller;
/* the sound of silence */
}
TRACE("primary playpos=%d, writepos=%d, clrpos=%d, mixpos=%d, buflen=%d\n",
- playpos,writepos,device->playpos,device->mixpos,device->buflen);
+ playpos,writepos,device->playpos,device->mixpos,device->buflen);
assert(device->playpos < device->buflen);
+ mixplaypos = DSOUND_bufpos_to_mixpos(device, device->playpos);
+ mixplaypos2 = DSOUND_bufpos_to_mixpos(device, playpos);
+
/* calc maximum prebuff */
prebuff_max = (device->prebuf * device->fraglen);
+ if (!device->hwbuf && playpos + prebuff_max >= device->helfrags * device->fraglen)
+ prebuff_max += device->buflen - device->helfrags * device->fraglen;
/* check how close we are to an underrun. It occurs when the writepos overtakes the mixpos */
prebuff_left = DSOUND_BufPtrDiff(device->buflen, device->mixpos, playpos);
/* reset mix position to write position */
device->mixpos = writepos;
+ ZeroMemory(device->mix_buffer, device->mix_buffer_len);
ZeroMemory(device->buffer, device->buflen);
} else if (playpos < device->playpos) {
buf1 = device->buffer + device->playpos;
buf2 = device->buffer;
size1 = device->buflen - device->playpos;
size2 = playpos;
+ FillMemory(device->mix_buffer + mixplaypos, device->mix_buffer_len - mixplaypos, 0);
+ FillMemory(device->mix_buffer, mixplaypos2, 0);
+ if (lock)
+ IDsDriverBuffer_Lock(device->hwbuf, &buf1, &size1, &buf2, &size2, device->playpos, size1+size2, 0);
FillMemory(buf1, size1, nfiller);
if (playpos && (!buf2 || !size2))
FIXME("%d: (%d, %d)=>(%d, %d) There should be an additional buffer here!!\n", __LINE__, device->playpos, device->mixpos, playpos, writepos);
FillMemory(buf2, size2, nfiller);
+ if (lock)
+ IDsDriverBuffer_Unlock(device->hwbuf, buf1, size1, buf2, size2);
} else {
buf1 = device->buffer + device->playpos;
buf2 = NULL;
size1 = playpos - device->playpos;
size2 = 0;
+ FillMemory(device->mix_buffer + mixplaypos, mixplaypos2 - mixplaypos, 0);
+ if (lock)
+ IDsDriverBuffer_Lock(device->hwbuf, &buf1, &size1, &buf2, &size2, device->playpos, size1+size2, 0);
FillMemory(buf1, size1, nfiller);
+ if (buf2 && size2)
+ {
+ FIXME("%d: There should be no additional buffer here!!\n", __LINE__);
+ FillMemory(buf2, size2, nfiller);
+ }
+ if (lock)
+ IDsDriverBuffer_Unlock(device->hwbuf, buf1, size1, buf2, size2);
}
device->playpos = playpos;
TRACE("prebuff_left = %d, prebuff_max = %dx%d=%d, writelead=%d\n",
prebuff_left, device->prebuf, device->fraglen, prebuff_max, writelead);
- ZeroMemory(device->mix_buffer, device->mix_buffer_len);
+ if (lock)
+ IDsDriverBuffer_Lock(device->hwbuf, &buf1, &size1, &buf2, &size2, writepos, maxq, 0);
/* do the mixing */
- DSOUND_MixToPrimary(device, writepos, maxq, recover, &all_stopped);
+ frag = DSOUND_MixToPrimary(device, writepos, maxq, recover, &all_stopped);
- if (maxq + writepos > device->buflen)
+ if (frag + writepos > device->buflen)
{
DWORD todo = device->buflen - writepos;
- DWORD offs_float = (todo / device->pwfx->nBlockAlign) * device->pwfx->nChannels;
- device->normfunction(device->mix_buffer, device->buffer + writepos, todo);
- device->normfunction(device->mix_buffer + offs_float, device->buffer, maxq - todo);
+ device->normfunction(device->mix_buffer + DSOUND_bufpos_to_mixpos(device, writepos), device->buffer + writepos, todo);
+ device->normfunction(device->mix_buffer, device->buffer, frag - todo);
}
else
- device->normfunction(device->mix_buffer, device->buffer + writepos, maxq);
+ device->normfunction(device->mix_buffer + DSOUND_bufpos_to_mixpos(device, writepos), device->buffer + writepos, frag);
/* update the mix position, taking wrap-around into account */
- device->mixpos = writepos + maxq;
+ device->mixpos = writepos + frag;
device->mixpos %= device->buflen;
+ if (lock)
+ {
+ DWORD frag2 = (frag > size1 ? frag - size1 : 0);
+ frag -= frag2;
+ if (frag2 > size2)
+ {
+ FIXME("Buffering too much! (%d, %d, %d, %d)\n", maxq, frag, size2, frag2 - size2);
+ frag2 = size2;
+ }
+ IDsDriverBuffer_Unlock(device->hwbuf, buf1, frag, buf2, frag2);
+ }
+
/* update prebuff left */
prebuff_left = DSOUND_BufPtrDiff(device->buflen, device->mixpos, playpos);
/* check if have a whole fragment */
if (prebuff_left >= device->fraglen){
- /* update the wave queue */
- DSOUND_WaveQueue(device, FALSE);
+ /* update the wave queue if using wave system */
+ if (!device->hwbuf)
+ DSOUND_WaveQueue(device, FALSE);
/* buffers are full. start playing if applicable */
if(device->state == STATE_STARTING){
DSOUND_PrimaryStop(device);
}
- } else if (device->state != STATE_STOPPED) {
+ } else {
- DSOUND_WaveQueue(device, TRUE);
+ /* update the wave queue if using wave system */
+ if (!device->hwbuf)
+ DSOUND_WaveQueue(device, TRUE);
+ else
+ /* Keep alsa happy, which needs GetPosition called once every 10 ms */
+ IDsDriverBuffer_GetPosition(device->hwbuf, NULL, NULL);
/* in the DSSCL_WRITEPRIMARY mode, the app is totally in charge... */
if (device->state == STATE_STARTING) {
/* **** */
}
-DWORD CALLBACK DSOUND_mixthread(void *p)
+void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD_PTR dwUser,
+ DWORD_PTR dw1, DWORD_PTR dw2)
+{
+ DirectSoundDevice * device = (DirectSoundDevice*)dwUser;
+ DWORD start_time = GetTickCount();
+ DWORD end_time;
+ TRACE("(%d,%d,0x%lx,0x%lx,0x%lx)\n",timerID,msg,dwUser,dw1,dw2);
+ TRACE("entering at %d\n", start_time);
+
+ if (DSOUND_renderer[device->drvdesc.dnDevNode] != device) {
+ ERR("dsound died without killing us?\n");
+ timeKillEvent(timerID);
+ timeEndPeriod(DS_TIME_RES);
+ return;
+ }
+
+ RtlAcquireResourceShared(&(device->buffer_list_lock), TRUE);
+
+ if (device->ref)
+ DSOUND_PerformMix(device);
+
+ RtlReleaseResource(&(device->buffer_list_lock));
+
+ end_time = GetTickCount();
+ TRACE("completed processing at %d, duration = %d\n", end_time, end_time - start_time);
+}
+
+void CALLBACK DSOUND_callback(HWAVEOUT hwo, UINT msg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
{
- DirectSoundDevice *dev = p;
- TRACE("(%p)\n", dev);
-
- while (dev->ref) {
- DWORD ret;
-
- /*
- * Some audio drivers are retarded and won't fire after being
- * stopped, add a timeout to handle this.
- */
- ret = WaitForSingleObject(dev->sleepev, dev->sleeptime);
- if (ret == WAIT_FAILED)
- WARN("wait returned error %u %08x!\n", GetLastError(), GetLastError());
- else if (ret != WAIT_OBJECT_0)
- WARN("wait returned %08x!\n", ret);
- if (!dev->ref)
- break;
-
- RtlAcquireResourceShared(&(dev->buffer_list_lock), TRUE);
- DSOUND_PerformMix(dev);
- RtlReleaseResource(&(dev->buffer_list_lock));
+ DirectSoundDevice * device = (DirectSoundDevice*)dwUser;
+ TRACE("(%p,%x,%lx,%lx,%lx)\n",hwo,msg,dwUser,dw1,dw2);
+ TRACE("entering at %d, msg=%08x(%s)\n", GetTickCount(), msg,
+ msg==MM_WOM_DONE ? "MM_WOM_DONE" : msg==MM_WOM_CLOSE ? "MM_WOM_CLOSE" :
+ msg==MM_WOM_OPEN ? "MM_WOM_OPEN" : "UNKNOWN");
+
+ /* check if packet completed from wave driver */
+ if (msg == MM_WOM_DONE) {
+
+ /* **** */
+ EnterCriticalSection(&(device->mixlock));
+
+ TRACE("done playing primary pos=%d\n", device->pwplay * device->fraglen);
+
+ /* update playpos */
+ device->pwplay++;
+ device->pwplay %= device->helfrags;
+
+ /* sanity */
+ if(device->pwqueue == 0){
+ ERR("Wave queue corrupted!\n");
+ }
+
+ /* update queue */
+ device->pwqueue--;
+
+ LeaveCriticalSection(&(device->mixlock));
+ /* **** */
}
- return 0;
+ TRACE("completed\n");
}
#include "dsound_private.h"
-static DWORD DSOUND_fraglen(DirectSoundDevice *device)
+/** Calculate how long a fragment length of about 10 ms should be in frames
+ *
+ * nSamplesPerSec: Frequency rate in samples per second
+ * nBlockAlign: Size of a single blockalign
+ *
+ * Returns:
+ * Size in bytes of a single fragment
+ */
+DWORD DSOUND_fraglen(DWORD nSamplesPerSec, DWORD nBlockAlign)
{
- REFERENCE_TIME period;
- HRESULT hr;
- DWORD ret;
-
- hr = IAudioClient_GetDevicePeriod(device->client, &period, NULL);
- if(FAILED(hr)){
- /* just guess at 10ms */
- WARN("GetDevicePeriod failed: %08x\n", hr);
- ret = MulDiv(device->pwfx->nBlockAlign, device->pwfx->nSamplesPerSec, 100);
- }else
- ret = MulDiv(device->pwfx->nSamplesPerSec * device->pwfx->nBlockAlign, period, 10000000);
-
- ret -= ret % device->pwfx->nBlockAlign;
- return ret;
+ /* Given a timer delay of 10ms, the fragment size is approximately:
+ * fraglen = (nSamplesPerSec * 10 / 1000) * nBlockAlign
+ * ==> fraglen = (nSamplesPerSec / 100) * nBlockSize
+ *
+ * ALSA uses buffers that are powers of 2. Because of this, fraglen
+ * is rounded up to the nearest power of 2:
+ */
+
+ if (nSamplesPerSec <= 12800)
+ return 128 * nBlockAlign;
+
+ if (nSamplesPerSec <= 25600)
+ return 256 * nBlockAlign;
+
+ if (nSamplesPerSec <= 51200)
+ return 512 * nBlockAlign;
+
+ return 1024 * nBlockAlign;
}
-static HRESULT DSOUND_WaveFormat(DirectSoundDevice *device, IAudioClient *client,
- BOOL forcewave, WAVEFORMATEX **wfx)
+static void DSOUND_RecalcPrimary(DirectSoundDevice *device)
{
- WAVEFORMATEXTENSIBLE *retwfe = NULL;
- WAVEFORMATEX *w;
- HRESULT hr;
-
- if (!forcewave) {
- WAVEFORMATEXTENSIBLE *mixwfe;
- hr = IAudioClient_GetMixFormat(client, (WAVEFORMATEX**)&mixwfe);
-
- if (FAILED(hr))
- return hr;
-
- if (mixwfe->Format.nChannels > 2) {
- static int once;
- if (!once++)
- FIXME("Limiting channels to 2 due to lack of multichannel support\n");
-
- mixwfe->Format.nChannels = 2;
- mixwfe->Format.nBlockAlign = mixwfe->Format.nChannels * mixwfe->Format.wBitsPerSample / 8;
- mixwfe->Format.nAvgBytesPerSec = mixwfe->Format.nSamplesPerSec * mixwfe->Format.nBlockAlign;
- mixwfe->dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
- }
+ TRACE("(%p)\n", device);
- if (!IsEqualGUID(&mixwfe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) {
- WAVEFORMATEXTENSIBLE testwfe = *mixwfe;
-
- testwfe.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
- testwfe.Samples.wValidBitsPerSample = testwfe.Format.wBitsPerSample = 32;
- testwfe.Format.nBlockAlign = testwfe.Format.nChannels * testwfe.Format.wBitsPerSample / 8;
- testwfe.Format.nAvgBytesPerSec = testwfe.Format.nSamplesPerSec * testwfe.Format.nBlockAlign;
-
- if (FAILED(IAudioClient_IsFormatSupported(client, AUDCLNT_SHAREMODE_SHARED, &testwfe.Format, (WAVEFORMATEX**)&retwfe)))
- w = DSOUND_CopyFormat(&mixwfe->Format);
- else if (retwfe)
- w = DSOUND_CopyFormat(&retwfe->Format);
- else
- w = DSOUND_CopyFormat(&testwfe.Format);
- CoTaskMemFree(retwfe);
- retwfe = NULL;
- } else
- w = DSOUND_CopyFormat(&mixwfe->Format);
- CoTaskMemFree(mixwfe);
- } else if (device->primary_pwfx->wFormatTag == WAVE_FORMAT_PCM ||
- device->primary_pwfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) {
- WAVEFORMATEX *wi = device->primary_pwfx;
- WAVEFORMATEXTENSIBLE *wfe;
-
- /* Convert to WAVEFORMATEXTENSIBLE */
- w = HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEFORMATEXTENSIBLE));
- wfe = (WAVEFORMATEXTENSIBLE*)w;
- if (!wfe)
- return DSERR_OUTOFMEMORY;
-
- wfe->Format = *wi;
- w->wFormatTag = WAVE_FORMAT_EXTENSIBLE;
- w->cbSize = sizeof(*wfe) - sizeof(*w);
- w->nBlockAlign = w->nChannels * w->wBitsPerSample / 8;
- w->nAvgBytesPerSec = w->nSamplesPerSec * w->nBlockAlign;
-
- wfe->dwChannelMask = 0;
- if (wi->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) {
- w->wBitsPerSample = 32;
- wfe->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
- } else
- wfe->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
- wfe->Samples.wValidBitsPerSample = w->wBitsPerSample;
- } else
- w = DSOUND_CopyFormat(device->primary_pwfx);
-
- if (!w)
- return DSERR_OUTOFMEMORY;
-
- hr = IAudioClient_IsFormatSupported(client, AUDCLNT_SHAREMODE_SHARED, w, (WAVEFORMATEX**)&retwfe);
- if (retwfe) {
- memcpy(w, retwfe, sizeof(WAVEFORMATEX) + retwfe->Format.cbSize);
- CoTaskMemFree(retwfe);
- }
- if (FAILED(hr)) {
- WARN("IsFormatSupported failed: %08x\n", hr);
- HeapFree(GetProcessHeap(), 0, w);
- return hr;
- }
- *wfx = w;
- return S_OK;
+ device->fraglen = DSOUND_fraglen(device->pwfx->nSamplesPerSec, device->pwfx->nBlockAlign);
+ device->helfrags = device->buflen / device->fraglen;
+ TRACE("fraglen=%d helfrags=%d\n", device->fraglen, device->helfrags);
+
+ if (device->hwbuf && device->drvdesc.dwFlags & DSDDESC_DONTNEEDWRITELEAD)
+ device->writelead = 0;
+ else
+ /* calculate the 10ms write lead */
+ device->writelead = (device->pwfx->nSamplesPerSec / 100) * device->pwfx->nBlockAlign;
}
HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave)
{
- UINT prebuf_frames;
- REFERENCE_TIME prebuf_rt;
- WAVEFORMATEX *wfx = NULL;
- HRESULT hres;
- REFERENCE_TIME period;
- DWORD period_ms;
-
- TRACE("(%p, %d)\n", device, forcewave);
-
- if(device->client){
- IAudioClient_Release(device->client);
- device->client = NULL;
- }
- if(device->render){
- IAudioRenderClient_Release(device->render);
- device->render = NULL;
- }
- if(device->clock){
- IAudioClock_Release(device->clock);
- device->clock = NULL;
- }
- if(device->volume){
- IAudioStreamVolume_Release(device->volume);
- device->volume = NULL;
- }
+ HRESULT hres = DS_OK;
+ TRACE("(%p, %d)\n", device, forcewave);
+
+ if (device->driver)
+ {
+ IDsDriver_Close(device->driver);
+ if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
+ waveOutClose(device->hwo);
+ IDsDriver_Release(device->driver);
+ device->driver = NULL;
+ device->buffer = NULL;
+ device->hwo = 0;
+ }
+ else if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
+ waveOutClose(device->hwo);
+
+ /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
+ if (ds_hw_accel != DS_HW_ACCEL_EMULATION && !forcewave)
+ waveOutMessage((HWAVEOUT)device->drvdesc.dnDevNode, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&device->driver, 0);
+
+ /* Get driver description */
+ if (device->driver) {
+ DWORD wod = device->drvdesc.dnDevNode;
+ hres = IDsDriver_GetDriverDesc(device->driver,&(device->drvdesc));
+ device->drvdesc.dnDevNode = wod;
+ if (FAILED(hres)) {
+ WARN("IDsDriver_GetDriverDesc failed: %08x\n", hres);
+ IDsDriver_Release(device->driver);
+ device->driver = NULL;
+ }
+ }
- hres = IMMDevice_Activate(device->mmdevice, &IID_IAudioClient,
- CLSCTX_INPROC_SERVER, NULL, (void **)&device->client);
- if(FAILED(hres)) {
- WARN("Activate failed: %08x\n", hres);
- return hres;
- }
+ /* if no DirectSound interface available, use WINMM API instead */
+ if (!device->driver)
+ device->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
- hres = DSOUND_WaveFormat(device, device->client, forcewave, &wfx);
- if (FAILED(hres)) {
- IAudioClient_Release(device->client);
- device->client = NULL;
- return hres;
- }
- HeapFree(GetProcessHeap(), 0, device->pwfx);
- device->pwfx = wfx;
-
- prebuf_frames = device->prebuf * DSOUND_fraglen(device) / device->pwfx->nBlockAlign;
- prebuf_rt = (10000000 * (UINT64)prebuf_frames) / device->pwfx->nSamplesPerSec;
-
- hres = IAudioClient_Initialize(device->client,
- AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_NOPERSIST |
- AUDCLNT_STREAMFLAGS_EVENTCALLBACK, prebuf_rt, 0, device->pwfx, NULL);
- if(FAILED(hres)){
- IAudioClient_Release(device->client);
- device->client = NULL;
- WARN("Initialize failed: %08x\n", hres);
- return hres;
- }
- IAudioClient_SetEventHandle(device->client, device->sleepev);
-
- hres = IAudioClient_GetService(device->client, &IID_IAudioRenderClient,
- (void**)&device->render);
- if(FAILED(hres)){
- IAudioClient_Release(device->client);
- device->client = NULL;
- WARN("GetService failed: %08x\n", hres);
- return hres;
- }
+ if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
+ {
+ DWORD flags = CALLBACK_FUNCTION | WAVE_MAPPED;
- hres = IAudioClient_GetService(device->client, &IID_IAudioClock,
- (void**)&device->clock);
- if(FAILED(hres)){
- IAudioClient_Release(device->client);
- IAudioRenderClient_Release(device->render);
- device->client = NULL;
- device->render = NULL;
- WARN("GetService failed: %08x\n", hres);
- return hres;
- }
+ if (device->driver)
+ flags |= WAVE_DIRECTSOUND;
- hres = IAudioClient_GetService(device->client, &IID_IAudioStreamVolume,
- (void**)&device->volume);
- if(FAILED(hres)){
- IAudioClient_Release(device->client);
- IAudioRenderClient_Release(device->render);
- IAudioClock_Release(device->clock);
- device->client = NULL;
- device->render = NULL;
- device->clock = NULL;
- WARN("GetService failed: %08x\n", hres);
- return hres;
- }
+ hres = mmErr(waveOutOpen(&(device->hwo), device->drvdesc.dnDevNode, device->pwfx, (DWORD_PTR)DSOUND_callback, (DWORD_PTR)device, flags));
+ if (FAILED(hres)) {
+ WARN("waveOutOpen failed\n");
+ if (device->driver)
+ {
+ IDsDriver_Release(device->driver);
+ device->driver = NULL;
+ }
+ return hres;
+ }
+ }
- /* Now kick off the timer so the event fires periodically */
- hres = IAudioClient_Start(device->client);
- if (FAILED(hres))
- WARN("starting failed with %08x\n", hres);
-
- hres = IAudioClient_GetStreamLatency(device->client, &period);
- if (FAILED(hres)) {
- WARN("GetStreamLatency failed with %08x\n", hres);
- period_ms = 10;
- } else
- period_ms = (period + 9999) / 10000;
- TRACE("period %u ms fraglen %u prebuf %u\n", period_ms, device->fraglen, device->prebuf);
-
- if (period_ms < 3)
- device->sleeptime = 5;
- else
- device->sleeptime = period_ms * 5 / 2;
+ if (device->driver)
+ hres = IDsDriver_Open(device->driver);
- return S_OK;
+ return hres;
}
-HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
+static HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
{
- IDirectSoundBufferImpl** dsb = device->buffers;
- LPBYTE newbuf;
- int i;
-
+ DWORD buflen;
+ HRESULT err = DS_OK;
TRACE("(%p)\n", device);
- device->fraglen = DSOUND_fraglen(device);
-
/* on original windows, the buffer it set to a fixed size, no matter what the settings are.
on windows this size is always fixed (tested on win-xp) */
if (!device->buflen)
device->buflen = ds_hel_buflen;
- device->buflen -= device->buflen % device->pwfx->nBlockAlign;
- while(device->buflen < device->fraglen * device->prebuf){
- device->buflen += ds_hel_buflen;
- device->buflen -= device->buflen % device->pwfx->nBlockAlign;
+ buflen = device->buflen;
+ buflen -= buflen % device->pwfx->nBlockAlign;
+ device->buflen = buflen;
+
+ if (device->driver)
+ {
+ err = IDsDriver_CreateSoundBuffer(device->driver,device->pwfx,
+ DSBCAPS_PRIMARYBUFFER,0,
+ &(device->buflen),&(device->buffer),
+ (LPVOID*)&(device->hwbuf));
+
+ if (err != DS_OK) {
+ WARN("IDsDriver_CreateSoundBuffer failed (%08x), falling back to waveout\n", err);
+ err = DSOUND_ReopenDevice(device, TRUE);
+ if (FAILED(err))
+ {
+ WARN("Falling back to waveout failed too! Giving up\n");
+ return err;
+ }
+ }
+ if (device->hwbuf)
+ IDsDriverBuffer_SetVolumePan(device->hwbuf, &device->volpan);
+
+ DSOUND_RecalcPrimary(device);
+ device->prebuf = ds_snd_queue_max;
+ if (device->helfrags < ds_snd_queue_min)
+ {
+ WARN("Too little sound buffer to be effective (%d/%d) falling back to waveout\n", device->buflen, ds_snd_queue_min * device->fraglen);
+ device->buflen = buflen;
+ IDsDriverBuffer_Release(device->hwbuf);
+ device->hwbuf = NULL;
+ err = DSOUND_ReopenDevice(device, TRUE);
+ if (FAILED(err))
+ {
+ WARN("Falling back to waveout failed too! Giving up\n");
+ return err;
+ }
+ }
+ else if (device->helfrags < ds_snd_queue_max)
+ device->prebuf = device->helfrags;
}
- HeapFree(GetProcessHeap(), 0, device->mix_buffer);
- device->mix_buffer_len = (device->buflen / (device->pwfx->wBitsPerSample / 8)) * sizeof(float);
- device->mix_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, device->mix_buffer_len);
+ device->mix_buffer_len = DSOUND_bufpos_to_mixpos(device, device->buflen);
+ device->mix_buffer = HeapAlloc(GetProcessHeap(), 0, device->mix_buffer_len);
if (!device->mix_buffer)
+ {
+ if (device->hwbuf)
+ IDsDriverBuffer_Release(device->hwbuf);
+ device->hwbuf = NULL;
return DSERR_OUTOFMEMORY;
+ }
if (device->state == STATE_PLAYING) device->state = STATE_STARTING;
else if (device->state == STATE_STOPPING) device->state = STATE_STOPPED;
- /* reallocate emulated primary buffer */
- if (device->buffer)
- newbuf = HeapReAlloc(GetProcessHeap(),0,device->buffer, device->buflen);
- else
- newbuf = HeapAlloc(GetProcessHeap(),0, device->buflen);
+ /* are we using waveOut stuff? */
+ if (!device->driver) {
+ LPBYTE newbuf;
+ LPWAVEHDR headers = NULL;
+ DWORD overshot;
+ unsigned int c;
- if (!newbuf) {
- ERR("failed to allocate primary buffer\n");
- return DSERR_OUTOFMEMORY;
- /* but the old buffer might still exist and must be re-prepared */
- }
+ /* Start in pause mode, to allow buffers to get filled */
+ waveOutPause(device->hwo);
- device->writelead = (device->pwfx->nSamplesPerSec / 100) * device->pwfx->nBlockAlign;
+ TRACE("desired buflen=%d, old buffer=%p\n", buflen, device->buffer);
- device->buffer = newbuf;
+ /* reallocate emulated primary buffer */
+ if (device->buffer)
+ newbuf = HeapReAlloc(GetProcessHeap(),0,device->buffer, buflen);
+ else
+ newbuf = HeapAlloc(GetProcessHeap(),0, buflen);
- TRACE("buflen: %u, fraglen: %u, mix_buffer_len: %u\n",
- device->buflen, device->fraglen, device->mix_buffer_len);
+ if (!newbuf) {
+ ERR("failed to allocate primary buffer\n");
+ return DSERR_OUTOFMEMORY;
+ /* but the old buffer might still exist and must be re-prepared */
+ }
- if(device->pwfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
- (device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
- IsEqualGUID(&((WAVEFORMATEXTENSIBLE*)device->pwfx)->SubFormat,
- &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)))
- device->normfunction = normfunctions[4];
- else
- device->normfunction = normfunctions[device->pwfx->wBitsPerSample/8 - 1];
+ DSOUND_RecalcPrimary(device);
+ if (device->pwave)
+ headers = HeapReAlloc(GetProcessHeap(),0,device->pwave, device->helfrags * sizeof(WAVEHDR));
+ else
+ headers = HeapAlloc(GetProcessHeap(),0,device->helfrags * sizeof(WAVEHDR));
- FillMemory(device->buffer, device->buflen, (device->pwfx->wBitsPerSample == 8) ? 128 : 0);
- FillMemory(device->mix_buffer, device->mix_buffer_len, 0);
- device->playpos = 0;
+ if (!headers) {
+ ERR("failed to allocate wave headers\n");
+ HeapFree(GetProcessHeap(), 0, newbuf);
+ DSOUND_RecalcPrimary(device);
+ return DSERR_OUTOFMEMORY;
+ }
- if (device->pwfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
- (device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
- IsEqualGUID(&((WAVEFORMATEXTENSIBLE*)device->pwfx)->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)))
- device->normfunction = normfunctions[4];
- else
- device->normfunction = normfunctions[device->pwfx->wBitsPerSample/8 - 1];
+ device->buffer = newbuf;
+ device->pwave = headers;
+
+ /* prepare fragment headers */
+ for (c=0; c<device->helfrags; c++) {
+ device->pwave[c].lpData = (char*)device->buffer + c*device->fraglen;
+ device->pwave[c].dwBufferLength = device->fraglen;
+ device->pwave[c].dwUser = (DWORD_PTR)device;
+ device->pwave[c].dwFlags = 0;
+ device->pwave[c].dwLoops = 0;
+ err = mmErr(waveOutPrepareHeader(device->hwo,&device->pwave[c],sizeof(WAVEHDR)));
+ if (err != DS_OK) {
+ while (c--)
+ waveOutUnprepareHeader(device->hwo,&device->pwave[c],sizeof(WAVEHDR));
+ break;
+ }
+ }
- for (i = 0; i < device->nrofbuffers; i++) {
- RtlAcquireResourceExclusive(&dsb[i]->lock, TRUE);
- DSOUND_RecalcFormat(dsb[i]);
- RtlReleaseResource(&dsb[i]->lock);
- }
+ overshot = device->buflen % device->fraglen;
+ /* sanity */
+ if(overshot)
+ {
+ overshot -= overshot % device->pwfx->nBlockAlign;
+ device->pwave[device->helfrags - 1].dwBufferLength += overshot;
+ }
- return DS_OK;
+ TRACE("fraglen=%d, overshot=%d\n", device->fraglen, overshot);
+ }
+ device->mixfunction = mixfunctions[device->pwfx->wBitsPerSample/8 - 1];
+ device->normfunction = normfunctions[device->pwfx->wBitsPerSample/8 - 1];
+ FillMemory(device->buffer, device->buflen, (device->pwfx->wBitsPerSample == 8) ? 128 : 0);
+ FillMemory(device->mix_buffer, device->mix_buffer_len, 0);
+ device->pwplay = device->pwqueue = device->playpos = device->mixpos = 0;
+ return err;
}
static void DSOUND_PrimaryClose(DirectSoundDevice *device)
{
- HRESULT hr;
-
- TRACE("(%p)\n", device);
+ TRACE("(%p)\n", device);
- if(device->client){
- hr = IAudioClient_Stop(device->client);
- if(FAILED(hr))
- WARN("Stop failed: %08x\n", hr);
- }
+ /* are we using waveOut stuff? */
+ if (!device->hwbuf) {
+ unsigned c;
- /* clear the queue */
- device->in_mmdev_bytes = 0;
+ /* get out of CS when calling the wave system */
+ LeaveCriticalSection(&(device->mixlock));
+ /* **** */
+ device->pwqueue = (DWORD)-1; /* resetting queues */
+ waveOutReset(device->hwo);
+ for (c=0; c<device->helfrags; c++)
+ waveOutUnprepareHeader(device->hwo, &device->pwave[c], sizeof(WAVEHDR));
+ /* **** */
+ EnterCriticalSection(&(device->mixlock));
+
+ /* clear the queue */
+ device->pwqueue = 0;
+ } else {
+ ULONG ref = IDsDriverBuffer_Release(device->hwbuf);
+ if (!ref)
+ device->hwbuf = 0;
+ else
+ ERR("Still %d references on primary buffer, refcount leak?\n", ref);
+ }
}
HRESULT DSOUND_PrimaryCreate(DirectSoundDevice *device)
EnterCriticalSection(&(device->mixlock));
DSOUND_PrimaryClose(device);
-
- if(device->primary && (device->primary->ref || device->primary->numIfaces))
- WARN("Destroying primary buffer while references held (%u %u)\n", device->primary->ref, device->primary->numIfaces);
-
- HeapFree(GetProcessHeap(), 0, device->primary);
- device->primary = NULL;
-
- HeapFree(GetProcessHeap(),0,device->primary_pwfx);
- HeapFree(GetProcessHeap(),0,device->pwfx);
- device->pwfx=NULL;
+ if (device->driver) {
+ if (device->hwbuf) {
+ if (IDsDriverBuffer_Release(device->hwbuf) == 0)
+ device->hwbuf = 0;
+ }
+ } else
+ HeapFree(GetProcessHeap(),0,device->pwave);
+ HeapFree(GetProcessHeap(),0,device->pwfx);
+ device->pwfx=NULL;
LeaveCriticalSection(&(device->mixlock));
/* **** */
HRESULT DSOUND_PrimaryPlay(DirectSoundDevice *device)
{
- HRESULT hr;
-
- TRACE("(%p)\n", device);
+ HRESULT err = DS_OK;
+ TRACE("(%p)\n", device);
- hr = IAudioClient_Start(device->client);
- if(FAILED(hr) && hr != AUDCLNT_E_NOT_STOPPED){
- WARN("Start failed: %08x\n", hr);
- return hr;
- }
+ if (device->hwbuf) {
+ err = IDsDriverBuffer_Play(device->hwbuf, 0, 0, DSBPLAY_LOOPING);
+ if (err != DS_OK)
+ WARN("IDsDriverBuffer_Play failed\n");
+ } else {
+ err = mmErr(waveOutRestart(device->hwo));
+ if (err != DS_OK)
+ WARN("waveOutRestart failed\n");
+ }
- return DS_OK;
+ return err;
}
HRESULT DSOUND_PrimaryStop(DirectSoundDevice *device)
{
- HRESULT hr;
+ HRESULT err = DS_OK;
+ TRACE("(%p)\n", device);
- TRACE("(%p)\n", device);
+ if (device->hwbuf) {
+ err = IDsDriverBuffer_Stop(device->hwbuf);
+ if (err == DSERR_BUFFERLOST) {
+ DSOUND_PrimaryClose(device);
+ err = DSOUND_ReopenDevice(device, FALSE);
+ if (FAILED(err))
+ ERR("DSOUND_ReopenDevice failed\n");
+ else
+ {
+ err = DSOUND_PrimaryOpen(device);
+ if (FAILED(err))
+ WARN("DSOUND_PrimaryOpen failed\n");
+ }
+ } else if (err != DS_OK) {
+ WARN("IDsDriverBuffer_Stop failed\n");
+ }
+ } else {
- hr = IAudioClient_Stop(device->client);
- if(FAILED(hr)){
- WARN("Stop failed: %08x\n", hr);
- return hr;
- }
+ /* don't call the wave system with the lock set */
+ LeaveCriticalSection(&(device->mixlock));
+ /* **** */
- return DS_OK;
+ err = mmErr(waveOutPause(device->hwo));
+
+ /* **** */
+ EnterCriticalSection(&(device->mixlock));
+
+ if (err != DS_OK)
+ WARN("waveOutPause failed\n");
+ }
+
+ return err;
}
HRESULT DSOUND_PrimaryGetPosition(DirectSoundDevice *device, LPDWORD playpos, LPDWORD writepos)
{
TRACE("(%p,%p,%p)\n", device, playpos, writepos);
- /* check if playpos was requested */
- if (playpos)
- *playpos = device->playing_offs_bytes;
+ if (device->hwbuf) {
+ HRESULT err=IDsDriverBuffer_GetPosition(device->hwbuf,playpos,writepos);
+ if (err != S_OK) {
+ WARN("IDsDriverBuffer_GetPosition failed\n");
+ return err;
+ }
+ } else {
+ TRACE("pwplay=%i, pwqueue=%i\n", device->pwplay, device->pwqueue);
- /* check if writepos was requested */
- if (writepos)
- /* the writepos is the first non-queued position */
- *writepos = (device->playing_offs_bytes + device->in_mmdev_bytes) % device->buflen;
+ /* check if playpos was requested */
+ if (playpos)
+ /* use the cached play position */
+ *playpos = device->pwplay * device->fraglen;
+ /* check if writepos was requested */
+ if (writepos)
+ /* the writepos is the first non-queued position */
+ *writepos = ((device->pwplay + device->pwqueue) % device->helfrags) * device->fraglen;
+ }
TRACE("playpos = %d, writepos = %d (%p, time=%d)\n", playpos?*playpos:-1, writepos?*writepos:-1, device, GetTickCount());
return DS_OK;
}
return pwfx;
}
-HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX passed_fmt)
+HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex)
{
- HRESULT err = S_OK;
- WAVEFORMATEX *old_fmt;
- WAVEFORMATEXTENSIBLE *fmtex, *passed_fmtex = (WAVEFORMATEXTENSIBLE*)passed_fmt;
- BOOL forced = (device->priolevel == DSSCL_WRITEPRIMARY);
+ HRESULT err = DSERR_BUFFERLOST;
+ int i;
+ DWORD nSamplesPerSec, bpp, chans;
+ LPWAVEFORMATEX oldpwfx;
+ BOOL forced = device->priolevel == DSSCL_WRITEPRIMARY;
- TRACE("(%p,%p)\n", device, passed_fmt);
+ TRACE("(%p,%p)\n", device, wfex);
if (device->priolevel == DSSCL_NORMAL) {
WARN("failed priority check!\n");
}
/* Let's be pedantic! */
- if (passed_fmt == NULL) {
- WARN("invalid parameter: passed_fmt==NULL!\n");
+ if (wfex == NULL) {
+ WARN("invalid parameter: wfex==NULL!\n");
return DSERR_INVALIDPARAM;
}
TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
- "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
- passed_fmt->wFormatTag, passed_fmt->nChannels, passed_fmt->nSamplesPerSec,
- passed_fmt->nAvgBytesPerSec, passed_fmt->nBlockAlign,
- passed_fmt->wBitsPerSample, passed_fmt->cbSize);
-
- if(passed_fmt->wBitsPerSample < 8 || passed_fmt->wBitsPerSample % 8 != 0 ||
- passed_fmt->nChannels == 0 || passed_fmt->nSamplesPerSec == 0 ||
- passed_fmt->nAvgBytesPerSec == 0 ||
- passed_fmt->nBlockAlign != passed_fmt->nChannels * passed_fmt->wBitsPerSample / 8)
- return DSERR_INVALIDPARAM;
-
- if(passed_fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE){
- if(passed_fmtex->Samples.wValidBitsPerSample > passed_fmtex->Format.wBitsPerSample)
- return DSERR_INVALIDPARAM;
- }
+ "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
+ wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec,
+ wfex->nAvgBytesPerSec, wfex->nBlockAlign,
+ wfex->wBitsPerSample, wfex->cbSize);
/* **** */
RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE);
EnterCriticalSection(&(device->mixlock));
- if (device->priolevel == DSSCL_WRITEPRIMARY) {
- old_fmt = device->primary_pwfx;
- device->primary_pwfx = DSOUND_CopyFormat(passed_fmt);
- fmtex = (WAVEFORMATEXTENSIBLE *)device->primary_pwfx;
- if (device->primary_pwfx == NULL) {
- err = DSERR_OUTOFMEMORY;
- goto out;
+ nSamplesPerSec = device->pwfx->nSamplesPerSec;
+ bpp = device->pwfx->wBitsPerSample;
+ chans = device->pwfx->nChannels;
+
+ oldpwfx = device->pwfx;
+ device->pwfx = DSOUND_CopyFormat(wfex);
+ if (device->pwfx == NULL) {
+ device->pwfx = oldpwfx;
+ oldpwfx = NULL;
+ err = DSERR_OUTOFMEMORY;
+ goto done;
+ }
+
+ if (!(device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMSETFORMAT) && device->hwbuf) {
+ err = IDsDriverBuffer_SetFormat(device->hwbuf, device->pwfx);
+
+ /* On bad format, try to re-create, big chance it will work then, only do this if we <HAVE> to */
+ if (forced && (device->pwfx->nSamplesPerSec/100 != wfex->nSamplesPerSec/100 || err == DSERR_BADFORMAT))
+ {
+ DWORD cp_size = wfex->wFormatTag == WAVE_FORMAT_PCM ?
+ sizeof(PCMWAVEFORMAT) : sizeof(WAVEFORMATEX) + wfex->cbSize;
+ err = DSERR_BUFFERLOST;
+ CopyMemory(device->pwfx, wfex, cp_size);
}
- if (fmtex->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
- fmtex->Samples.wValidBitsPerSample == 0) {
- TRACE("Correcting 0 valid bits per sample\n");
- fmtex->Samples.wValidBitsPerSample = fmtex->Format.wBitsPerSample;
+ if (err != DSERR_BUFFERLOST && FAILED(err)) {
+ DWORD size = DSOUND_GetFormatSize(oldpwfx);
+ WARN("IDsDriverBuffer_SetFormat failed\n");
+ if (!forced) {
+ CopyMemory(device->pwfx, oldpwfx, size);
+ err = DS_OK;
+ }
+ goto done;
}
+ if (err == S_FALSE)
+ {
+ /* ALSA specific: S_FALSE tells that recreation was successful,
+ * but size and location may be changed, and buffer has to be restarted
+ * I put it here, so if frequency doesn't match the error will be changed to DSERR_BUFFERLOST
+ * and the entire re-initialization will occur anyway
+ */
+ IDsDriverBuffer_Lock(device->hwbuf, (LPVOID *)&device->buffer, &device->buflen, NULL, NULL, 0, 0, DSBLOCK_ENTIREBUFFER);
+ IDsDriverBuffer_Unlock(device->hwbuf, device->buffer, 0, NULL, 0);
+
+ if (device->state == STATE_PLAYING) device->state = STATE_STARTING;
+ else if (device->state == STATE_STOPPING) device->state = STATE_STOPPED;
+ device->pwplay = device->pwqueue = device->playpos = device->mixpos = 0;
+ err = DS_OK;
+ }
+ DSOUND_RecalcPrimary(device);
+ }
+
+ if (err == DSERR_BUFFERLOST)
+ {
DSOUND_PrimaryClose(device);
- err = DSOUND_ReopenDevice(device, forced);
- if (FAILED(err)) {
- ERR("No formats could be opened\n");
+ err = DSOUND_ReopenDevice(device, FALSE);
+ if (FAILED(err))
+ {
+ WARN("DSOUND_ReopenDevice failed: %08x\n", err);
goto done;
}
-
err = DSOUND_PrimaryOpen(device);
if (err != DS_OK) {
- ERR("DSOUND_PrimaryOpen failed\n");
+ WARN("DSOUND_PrimaryOpen failed\n");
goto done;
}
-done:
- if (err != DS_OK)
- device->primary_pwfx = old_fmt;
- else
- HeapFree(GetProcessHeap(), 0, old_fmt);
- } else if (passed_fmt->wFormatTag == WAVE_FORMAT_PCM ||
- passed_fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) {
- /* Fill in "real" values to primary_pwfx */
- WAVEFORMATEX *fmt = device->primary_pwfx;
-
- *fmt = *device->pwfx;
- fmtex = (void*)device->pwfx;
-
- if (IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) &&
- passed_fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) {
- fmt->wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
- } else {
- fmt->wFormatTag = WAVE_FORMAT_PCM;
- fmt->wBitsPerSample = 16;
+ if (wfex->nSamplesPerSec/100 != device->pwfx->nSamplesPerSec/100 && forced && device->buffer)
+ {
+ DSOUND_PrimaryClose(device);
+ device->pwfx->nSamplesPerSec = wfex->nSamplesPerSec;
+ err = DSOUND_ReopenDevice(device, TRUE);
+ if (FAILED(err))
+ WARN("DSOUND_ReopenDevice(2) failed: %08x\n", err);
+ else if (FAILED((err = DSOUND_PrimaryOpen(device))))
+ WARN("DSOUND_PrimaryOpen(2) failed: %08x\n", err);
+ }
+ }
+
+ device->mix_buffer_len = DSOUND_bufpos_to_mixpos(device, device->buflen);
+ device->mix_buffer = HeapReAlloc(GetProcessHeap(), 0, device->mix_buffer, device->mix_buffer_len);
+ FillMemory(device->mix_buffer, device->mix_buffer_len, 0);
+ device->mixfunction = mixfunctions[device->pwfx->wBitsPerSample/8 - 1];
+ device->normfunction = normfunctions[device->pwfx->wBitsPerSample/8 - 1];
+
+ if (nSamplesPerSec != device->pwfx->nSamplesPerSec || bpp != device->pwfx->wBitsPerSample || chans != device->pwfx->nChannels) {
+ IDirectSoundBufferImpl** dsb = device->buffers;
+ for (i = 0; i < device->nrofbuffers; i++, dsb++) {
+ /* **** */
+ RtlAcquireResourceExclusive(&(*dsb)->lock, TRUE);
+
+ (*dsb)->freqAdjust = ((DWORD64)(*dsb)->freq << DSOUND_FREQSHIFT) / device->pwfx->nSamplesPerSec;
+ DSOUND_RecalcFormat((*dsb));
+ DSOUND_MixToTemporary((*dsb), 0, (*dsb)->buflen, FALSE);
+ (*dsb)->primary_mixpos = 0;
+
+ RtlReleaseResource(&(*dsb)->lock);
+ /* **** */
}
- fmt->nBlockAlign = fmt->nChannels * fmt->wBitsPerSample / 8;
- fmt->nAvgBytesPerSec = fmt->nBlockAlign * fmt->nSamplesPerSec;
- fmt->cbSize = 0;
- } else {
- device->primary_pwfx = HeapReAlloc(GetProcessHeap(), 0, device->primary_pwfx, sizeof(*fmtex));
- memcpy(device->primary_pwfx, device->pwfx, sizeof(*fmtex));
}
-out:
+done:
LeaveCriticalSection(&(device->mixlock));
RtlReleaseResource(&(device->buffer_list_lock));
/* **** */
+ HeapFree(GetProcessHeap(), 0, oldpwfx);
return err;
}
return CONTAINING_RECORD(iface, IDirectSoundBufferImpl, IDirectSoundBuffer8_iface);
}
-/* This sets this format for the primary buffer only */
-static HRESULT WINAPI PrimaryBufferImpl_SetFormat(IDirectSoundBuffer *iface,
- const WAVEFORMATEX *wfex)
+/* This sets this format for the <em>Primary Buffer Only</em> */
+/* See file:///cdrom/sdk52/docs/worddoc/dsound.doc page 120 */
+static HRESULT WINAPI PrimaryBufferImpl_SetFormat(
+ LPDIRECTSOUNDBUFFER iface,
+ LPCWAVEFORMATEX wfex)
{
IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
TRACE("(%p,%p)\n", iface, wfex);
return primarybuffer_SetFormat(This->device, wfex);
}
-static HRESULT WINAPI PrimaryBufferImpl_SetVolume(IDirectSoundBuffer *iface, LONG vol)
-{
- IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
- DirectSoundDevice *device = This->device;
- HRESULT hr;
- float lvol, rvol;
-
+static HRESULT WINAPI PrimaryBufferImpl_SetVolume(
+ LPDIRECTSOUNDBUFFER iface,LONG vol
+) {
+ IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
+ DirectSoundDevice *device = This->device;
+ DWORD ampfactors;
+ HRESULT hres = DS_OK;
TRACE("(%p,%d)\n", iface, vol);
if (!(This->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
}
/* **** */
- EnterCriticalSection(&device->mixlock);
-
- hr = IAudioStreamVolume_GetChannelVolume(device->volume, 0, &lvol);
- if(FAILED(hr)){
- LeaveCriticalSection(&device->mixlock);
- WARN("GetChannelVolume failed: %08x\n", hr);
- return hr;
- }
-
- if(device->pwfx->nChannels > 1){
- hr = IAudioStreamVolume_GetChannelVolume(device->volume, 1, &rvol);
- if(FAILED(hr)){
- LeaveCriticalSection(&device->mixlock);
- WARN("GetChannelVolume failed: %08x\n", hr);
- return hr;
- }
- }else
- rvol = 1;
-
- device->volpan.dwTotalLeftAmpFactor = ((UINT16)(lvol * (DWORD)0xFFFF));
- device->volpan.dwTotalRightAmpFactor = ((UINT16)(rvol * (DWORD)0xFFFF));
-
- DSOUND_AmpFactorToVolPan(&device->volpan);
- if (vol != device->volpan.lVolume) {
- device->volpan.lVolume=vol;
- DSOUND_RecalcVolPan(&device->volpan);
- lvol = (float)((DWORD)(device->volpan.dwTotalLeftAmpFactor & 0xFFFF) / (float)0xFFFF);
- hr = IAudioStreamVolume_SetChannelVolume(device->volume, 0, lvol);
- if(FAILED(hr)){
- LeaveCriticalSection(&device->mixlock);
- WARN("SetChannelVolume failed: %08x\n", hr);
- return hr;
- }
+ EnterCriticalSection(&(device->mixlock));
- if(device->pwfx->nChannels > 1){
- rvol = (float)((DWORD)(device->volpan.dwTotalRightAmpFactor & 0xFFFF) / (float)0xFFFF);
- hr = IAudioStreamVolume_SetChannelVolume(device->volume, 1, rvol);
- if(FAILED(hr)){
- LeaveCriticalSection(&device->mixlock);
- WARN("SetChannelVolume failed: %08x\n", hr);
- return hr;
- }
- }
- }
+ waveOutGetVolume(device->hwo, &factors);
+ device->volpan.dwTotalLeftAmpFactor=ampfactors & 0xffff;
+ device->volpan.dwTotalRightAmpFactor=ampfactors >> 16;
+ DSOUND_AmpFactorToVolPan(&device->volpan);
+ if (vol != device->volpan.lVolume) {
+ device->volpan.lVolume=vol;
+ DSOUND_RecalcVolPan(&device->volpan);
+ if (device->hwbuf) {
+ hres = IDsDriverBuffer_SetVolumePan(device->hwbuf, &device->volpan);
+ if (hres != DS_OK)
+ WARN("IDsDriverBuffer_SetVolumePan failed\n");
+ } else {
+ ampfactors = (device->volpan.dwTotalLeftAmpFactor & 0xffff) | (device->volpan.dwTotalRightAmpFactor << 16);
+ waveOutSetVolume(device->hwo, ampfactors);
+ }
+ }
LeaveCriticalSection(&(device->mixlock));
/* **** */
- return DS_OK;
+ return hres;
}
-static HRESULT WINAPI PrimaryBufferImpl_GetVolume(IDirectSoundBuffer *iface, LONG *vol)
-{
- IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
- DirectSoundDevice *device = This->device;
- float lvol, rvol;
- HRESULT hr;
+static HRESULT WINAPI PrimaryBufferImpl_GetVolume(
+ LPDIRECTSOUNDBUFFER iface,LPLONG vol
+) {
+ IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
+ DirectSoundDevice *device = This->device;
+ DWORD ampfactors;
TRACE("(%p,%p)\n", iface, vol);
if (!(This->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
return DSERR_INVALIDPARAM;
}
- EnterCriticalSection(&device->mixlock);
-
- hr = IAudioStreamVolume_GetChannelVolume(device->volume, 0, &lvol);
- if(FAILED(hr)){
- LeaveCriticalSection(&device->mixlock);
- WARN("GetChannelVolume failed: %08x\n", hr);
- return hr;
- }
-
- if(device->pwfx->nChannels > 1){
- hr = IAudioStreamVolume_GetChannelVolume(device->volume, 1, &rvol);
- if(FAILED(hr)){
- LeaveCriticalSection(&device->mixlock);
- WARN("GetChannelVolume failed: %08x\n", hr);
- return hr;
- }
- }else
- rvol = 1;
-
- device->volpan.dwTotalLeftAmpFactor = ((UINT16)(lvol * (DWORD)0xFFFF));
- device->volpan.dwTotalRightAmpFactor = ((UINT16)(rvol * (DWORD)0xFFFF));
-
- DSOUND_AmpFactorToVolPan(&device->volpan);
- *vol = device->volpan.lVolume;
-
- LeaveCriticalSection(&device->mixlock);
-
+ if (!device->hwbuf)
+ {
+ waveOutGetVolume(device->hwo, &factors);
+ device->volpan.dwTotalLeftAmpFactor=ampfactors & 0xffff;
+ device->volpan.dwTotalRightAmpFactor=ampfactors >> 16;
+ DSOUND_AmpFactorToVolPan(&device->volpan);
+ }
+ *vol = device->volpan.lVolume;
return DS_OK;
}
-static HRESULT WINAPI PrimaryBufferImpl_SetFrequency(IDirectSoundBuffer *iface, DWORD freq)
-{
+static HRESULT WINAPI PrimaryBufferImpl_SetFrequency(
+ LPDIRECTSOUNDBUFFER iface,DWORD freq
+) {
IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
TRACE("(%p,%d)\n",This,freq);
return DSERR_CONTROLUNAVAIL;
}
-static HRESULT WINAPI PrimaryBufferImpl_Play(IDirectSoundBuffer *iface, DWORD reserved1,
- DWORD reserved2, DWORD flags)
-{
+static HRESULT WINAPI PrimaryBufferImpl_Play(
+ LPDIRECTSOUNDBUFFER iface,DWORD reserved1,DWORD reserved2,DWORD flags
+) {
IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
DirectSoundDevice *device = This->device;
TRACE("(%p,%08x,%08x,%08x)\n", iface, reserved1, reserved2, flags);
return DS_OK;
}
-static HRESULT WINAPI PrimaryBufferImpl_Stop(IDirectSoundBuffer *iface)
+static HRESULT WINAPI PrimaryBufferImpl_Stop(LPDIRECTSOUNDBUFFER iface)
{
IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
DirectSoundDevice *device = This->device;
return DS_OK;
}
-static ULONG WINAPI PrimaryBufferImpl_AddRef(IDirectSoundBuffer *iface)
+static ULONG WINAPI PrimaryBufferImpl_AddRef(LPDIRECTSOUNDBUFFER iface)
{
IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
ULONG ref = InterlockedIncrement(&(This->ref));
return ref;
}
-/* Decreases *out by 1 to no less than 0.
- * Returns the new value of *out. */
-LONG capped_refcount_dec(LONG *out)
+void primarybuffer_destroy(IDirectSoundBufferImpl *This)
{
- LONG ref, oldref;
- do {
- ref = *out;
- if(!ref)
- return 0;
- oldref = InterlockedCompareExchange(out, ref - 1, ref);
- } while(oldref != ref);
- return ref - 1;
+ This->device->primary = NULL;
+ HeapFree(GetProcessHeap(), 0, This);
+ TRACE("(%p) released\n", This);
}
-static ULONG WINAPI PrimaryBufferImpl_Release(IDirectSoundBuffer *iface)
+static ULONG WINAPI PrimaryBufferImpl_Release(LPDIRECTSOUNDBUFFER iface)
{
IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
- ULONG ref;
-
- ref = capped_refcount_dec(&This->ref);
- if(!ref)
- capped_refcount_dec(&This->numIfaces);
-
- TRACE("(%p) primary ref is now %d\n", This, ref);
+ DWORD ref = InterlockedDecrement(&(This->ref));
+ TRACE("(%p) ref was %d\n", This, ref + 1);
+ if (!ref && !InterlockedDecrement(&This->numIfaces))
+ primarybuffer_destroy(This);
return ref;
}
-static HRESULT WINAPI PrimaryBufferImpl_GetCurrentPosition(IDirectSoundBuffer *iface,
- DWORD *playpos, DWORD *writepos)
-{
+static HRESULT WINAPI PrimaryBufferImpl_GetCurrentPosition(
+ LPDIRECTSOUNDBUFFER iface,LPDWORD playpos,LPDWORD writepos
+) {
HRESULT hres;
IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
DirectSoundDevice *device = This->device;
return DS_OK;
}
-static HRESULT WINAPI PrimaryBufferImpl_GetStatus(IDirectSoundBuffer *iface, DWORD *status)
-{
+static HRESULT WINAPI PrimaryBufferImpl_GetStatus(
+ LPDIRECTSOUNDBUFFER iface,LPDWORD status
+) {
IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
DirectSoundDevice *device = This->device;
TRACE("(%p,%p)\n", iface, status);
}
-static HRESULT WINAPI PrimaryBufferImpl_GetFormat(IDirectSoundBuffer *iface, WAVEFORMATEX *lpwf,
- DWORD wfsize, DWORD *wfwritten)
+static HRESULT WINAPI PrimaryBufferImpl_GetFormat(
+ LPDIRECTSOUNDBUFFER iface,
+ LPWAVEFORMATEX lpwf,
+ DWORD wfsize,
+ LPDWORD wfwritten)
{
DWORD size;
IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
DirectSoundDevice *device = This->device;
TRACE("(%p,%p,%d,%p)\n", iface, lpwf, wfsize, wfwritten);
- size = sizeof(WAVEFORMATEX) + device->primary_pwfx->cbSize;
+ size = sizeof(WAVEFORMATEX) + device->pwfx->cbSize;
if (lpwf) { /* NULL is valid */
if (wfsize >= size) {
- CopyMemory(lpwf,device->primary_pwfx,size);
+ CopyMemory(lpwf,device->pwfx,size);
if (wfwritten)
*wfwritten = size;
} else {
}
} else {
if (wfwritten)
- *wfwritten = sizeof(WAVEFORMATEX) + device->primary_pwfx->cbSize;
+ *wfwritten = sizeof(WAVEFORMATEX) + device->pwfx->cbSize;
else {
WARN("invalid parameter: wfwritten == NULL\n");
return DSERR_INVALIDPARAM;
return DS_OK;
}
-static HRESULT WINAPI PrimaryBufferImpl_Lock(IDirectSoundBuffer *iface, DWORD writecursor,
- DWORD writebytes, void **lplpaudioptr1, DWORD *audiobytes1, void **lplpaudioptr2,
- DWORD *audiobytes2, DWORD flags)
-{
+static HRESULT WINAPI PrimaryBufferImpl_Lock(
+ LPDIRECTSOUNDBUFFER iface,DWORD writecursor,DWORD writebytes,LPVOID *lplpaudioptr1,LPDWORD audiobytes1,LPVOID *lplpaudioptr2,LPDWORD audiobytes2,DWORD flags
+) {
HRESULT hres;
IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
DirectSoundDevice *device = This->device;
return DSERR_INVALIDPARAM;
}
- if (writecursor+writebytes <= device->buflen) {
- *(LPBYTE*)lplpaudioptr1 = device->buffer+writecursor;
- *audiobytes1 = writebytes;
- if (lplpaudioptr2)
- *(LPBYTE*)lplpaudioptr2 = NULL;
- if (audiobytes2)
- *audiobytes2 = 0;
- TRACE("->%d.0\n",writebytes);
+ if (!(device->drvdesc.dwFlags & DSDDESC_DONTNEEDPRIMARYLOCK) && device->hwbuf) {
+ hres = IDsDriverBuffer_Lock(device->hwbuf,
+ lplpaudioptr1, audiobytes1,
+ lplpaudioptr2, audiobytes2,
+ writecursor, writebytes,
+ 0);
+ if (hres != DS_OK) {
+ WARN("IDsDriverBuffer_Lock failed\n");
+ return hres;
+ }
} else {
- *(LPBYTE*)lplpaudioptr1 = device->buffer+writecursor;
- *audiobytes1 = device->buflen-writecursor;
- if (lplpaudioptr2)
- *(LPBYTE*)lplpaudioptr2 = device->buffer;
- if (audiobytes2)
- *audiobytes2 = writebytes-(device->buflen-writecursor);
- TRACE("->%d.%d\n",*audiobytes1,audiobytes2?*audiobytes2:0);
+ if (writecursor+writebytes <= device->buflen) {
+ *(LPBYTE*)lplpaudioptr1 = device->buffer+writecursor;
+ *audiobytes1 = writebytes;
+ if (lplpaudioptr2)
+ *(LPBYTE*)lplpaudioptr2 = NULL;
+ if (audiobytes2)
+ *audiobytes2 = 0;
+ TRACE("->%d.0\n",writebytes);
+ } else {
+ *(LPBYTE*)lplpaudioptr1 = device->buffer+writecursor;
+ *audiobytes1 = device->buflen-writecursor;
+ if (lplpaudioptr2)
+ *(LPBYTE*)lplpaudioptr2 = device->buffer;
+ if (audiobytes2)
+ *audiobytes2 = writebytes-(device->buflen-writecursor);
+ TRACE("->%d.%d\n",*audiobytes1,audiobytes2?*audiobytes2:0);
+ }
}
return DS_OK;
}
-static HRESULT WINAPI PrimaryBufferImpl_SetCurrentPosition(IDirectSoundBuffer *iface, DWORD newpos)
-{
+static HRESULT WINAPI PrimaryBufferImpl_SetCurrentPosition(
+ LPDIRECTSOUNDBUFFER iface,DWORD newpos
+) {
IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
TRACE("(%p,%d)\n",This,newpos);
return DSERR_INVALIDCALL;
}
-static HRESULT WINAPI PrimaryBufferImpl_SetPan(IDirectSoundBuffer *iface, LONG pan)
-{
- IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
- DirectSoundDevice *device = This->device;
- float lvol, rvol;
- HRESULT hr;
+static HRESULT WINAPI PrimaryBufferImpl_SetPan(
+ LPDIRECTSOUNDBUFFER iface,LONG pan
+) {
+ IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
+ DirectSoundDevice *device = This->device;
+ DWORD ampfactors;
+ HRESULT hres = DS_OK;
TRACE("(%p,%d)\n", iface, pan);
if (!(This->dsbd.dwFlags & DSBCAPS_CTRLPAN)) {
}
/* **** */
- EnterCriticalSection(&device->mixlock);
-
- hr = IAudioStreamVolume_GetChannelVolume(device->volume, 0, &lvol);
- if(FAILED(hr)){
- LeaveCriticalSection(&device->mixlock);
- WARN("GetChannelVolume failed: %08x\n", hr);
- return hr;
- }
-
- if(device->pwfx->nChannels > 1){
- hr = IAudioStreamVolume_GetChannelVolume(device->volume, 1, &rvol);
- if(FAILED(hr)){
- LeaveCriticalSection(&device->mixlock);
- WARN("GetChannelVolume failed: %08x\n", hr);
- return hr;
- }
- }else
- rvol = 1;
-
- device->volpan.dwTotalLeftAmpFactor = ((UINT16)(lvol * (DWORD)0xFFFF));
- device->volpan.dwTotalRightAmpFactor = ((UINT16)(rvol * (DWORD)0xFFFF));
-
- DSOUND_AmpFactorToVolPan(&device->volpan);
- if (pan != device->volpan.lPan) {
- device->volpan.lPan=pan;
- DSOUND_RecalcVolPan(&device->volpan);
-
- lvol = (float)((DWORD)(device->volpan.dwTotalLeftAmpFactor & 0xFFFF) / (float)0xFFFF);
- hr = IAudioStreamVolume_SetChannelVolume(device->volume, 0, lvol);
- if(FAILED(hr)){
- LeaveCriticalSection(&device->mixlock);
- WARN("SetChannelVolume failed: %08x\n", hr);
- return hr;
- }
+ EnterCriticalSection(&(device->mixlock));
- if(device->pwfx->nChannels > 1){
- rvol = (float)((DWORD)(device->volpan.dwTotalRightAmpFactor & 0xFFFF) / (float)0xFFFF);
- hr = IAudioStreamVolume_SetChannelVolume(device->volume, 1, rvol);
- if(FAILED(hr)){
- LeaveCriticalSection(&device->mixlock);
- WARN("SetChannelVolume failed: %08x\n", hr);
- return hr;
- }
- }
- }
+ if (!device->hwbuf)
+ {
+ waveOutGetVolume(device->hwo, &factors);
+ device->volpan.dwTotalLeftAmpFactor=ampfactors & 0xffff;
+ device->volpan.dwTotalRightAmpFactor=ampfactors >> 16;
+ DSOUND_AmpFactorToVolPan(&device->volpan);
+ }
+ if (pan != device->volpan.lPan) {
+ device->volpan.lPan=pan;
+ DSOUND_RecalcVolPan(&device->volpan);
+ if (device->hwbuf) {
+ hres = IDsDriverBuffer_SetVolumePan(device->hwbuf, &device->volpan);
+ if (hres != DS_OK)
+ WARN("IDsDriverBuffer_SetVolumePan failed\n");
+ } else {
+ ampfactors = (device->volpan.dwTotalLeftAmpFactor & 0xffff) | (device->volpan.dwTotalRightAmpFactor << 16);
+ waveOutSetVolume(device->hwo, ampfactors);
+ }
+ }
- LeaveCriticalSection(&device->mixlock);
+ LeaveCriticalSection(&(device->mixlock));
/* **** */
- return DS_OK;
+ return hres;
}
-static HRESULT WINAPI PrimaryBufferImpl_GetPan(IDirectSoundBuffer *iface, LONG *pan)
-{
- IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
- DirectSoundDevice *device = This->device;
- float lvol, rvol;
- HRESULT hr;
+static HRESULT WINAPI PrimaryBufferImpl_GetPan(
+ LPDIRECTSOUNDBUFFER iface,LPLONG pan
+) {
+ IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
+ DirectSoundDevice *device = This->device;
+ DWORD ampfactors;
TRACE("(%p,%p)\n", iface, pan);
if (!(This->dsbd.dwFlags & DSBCAPS_CTRLPAN)) {
return DSERR_INVALIDPARAM;
}
- EnterCriticalSection(&device->mixlock);
-
- hr = IAudioStreamVolume_GetChannelVolume(device->volume, 0, &lvol);
- if(FAILED(hr)){
- LeaveCriticalSection(&device->mixlock);
- WARN("GetChannelVolume failed: %08x\n", hr);
- return hr;
- }
-
- if(device->pwfx->nChannels > 1){
- hr = IAudioStreamVolume_GetChannelVolume(device->volume, 1, &rvol);
- if(FAILED(hr)){
- LeaveCriticalSection(&device->mixlock);
- WARN("GetChannelVolume failed: %08x\n", hr);
- return hr;
- }
- }else
- rvol = 1;
-
- device->volpan.dwTotalLeftAmpFactor = ((UINT16)(lvol * (DWORD)0xFFFF));
- device->volpan.dwTotalRightAmpFactor = ((UINT16)(rvol * (DWORD)0xFFFF));
-
- DSOUND_AmpFactorToVolPan(&device->volpan);
+ if (!device->hwbuf)
+ {
+ waveOutGetVolume(device->hwo, &factors);
+ device->volpan.dwTotalLeftAmpFactor=ampfactors & 0xffff;
+ device->volpan.dwTotalRightAmpFactor=ampfactors >> 16;
+ DSOUND_AmpFactorToVolPan(&device->volpan);
+ }
*pan = device->volpan.lPan;
-
- LeaveCriticalSection(&device->mixlock);
-
return DS_OK;
}
-static HRESULT WINAPI PrimaryBufferImpl_Unlock(IDirectSoundBuffer *iface, void *p1, DWORD x1,
- void *p2, DWORD x2)
-{
+static HRESULT WINAPI PrimaryBufferImpl_Unlock(
+ LPDIRECTSOUNDBUFFER iface,LPVOID p1,DWORD x1,LPVOID p2,DWORD x2
+) {
IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
DirectSoundDevice *device = This->device;
TRACE("(%p,%p,%d,%p,%d)\n", iface, p1, x1, p2, x2);
return DSERR_PRIOLEVELNEEDED;
}
- if ((p1 && ((BYTE*)p1 < device->buffer || (BYTE*)p1 >= device->buffer + device->buflen)) ||
- (p2 && ((BYTE*)p2 < device->buffer || (BYTE*)p2 >= device->buffer + device->buflen)))
- return DSERR_INVALIDPARAM;
+ if (!(device->drvdesc.dwFlags & DSDDESC_DONTNEEDPRIMARYLOCK) && device->hwbuf) {
+ HRESULT hres;
+
+ if ((char *)p1 - (char *)device->buffer + x1 > device->buflen)
+ hres = DSERR_INVALIDPARAM;
+ else
+ hres = IDsDriverBuffer_Unlock(device->hwbuf, p1, x1, p2, x2);
+
+ if (hres != DS_OK) {
+ WARN("IDsDriverBuffer_Unlock failed\n");
+ return hres;
+ }
+ }
return DS_OK;
}
-static HRESULT WINAPI PrimaryBufferImpl_Restore(IDirectSoundBuffer *iface)
-{
+static HRESULT WINAPI PrimaryBufferImpl_Restore(
+ LPDIRECTSOUNDBUFFER iface
+) {
IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
FIXME("(%p):stub\n",This);
return DS_OK;
}
-static HRESULT WINAPI PrimaryBufferImpl_GetFrequency(IDirectSoundBuffer *iface, DWORD *freq)
-{
+static HRESULT WINAPI PrimaryBufferImpl_GetFrequency(
+ LPDIRECTSOUNDBUFFER iface,LPDWORD freq
+) {
IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
DirectSoundDevice *device = This->device;
TRACE("(%p,%p)\n", iface, freq);
return DS_OK;
}
-static HRESULT WINAPI PrimaryBufferImpl_Initialize(IDirectSoundBuffer *iface, IDirectSound *dsound,
- const DSBUFFERDESC *dbsd)
-{
+static HRESULT WINAPI PrimaryBufferImpl_Initialize(
+ LPDIRECTSOUNDBUFFER iface,LPDIRECTSOUND dsound,LPCDSBUFFERDESC dbsd
+) {
IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
WARN("(%p) already initialized\n", This);
return DSERR_ALREADYINITIALIZED;
}
-static HRESULT WINAPI PrimaryBufferImpl_GetCaps(IDirectSoundBuffer *iface, DSBCAPS *caps)
-{
+static HRESULT WINAPI PrimaryBufferImpl_GetCaps(
+ LPDIRECTSOUNDBUFFER iface,LPDSBCAPS caps
+) {
IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
DirectSoundDevice *device = This->device;
TRACE("(%p,%p)\n", iface, caps);
return DS_OK;
}
-static HRESULT WINAPI PrimaryBufferImpl_QueryInterface(IDirectSoundBuffer *iface, REFIID riid,
- void **ppobj)
-{
+static HRESULT WINAPI PrimaryBufferImpl_QueryInterface(
+ LPDIRECTSOUNDBUFFER iface,REFIID riid,LPVOID *ppobj
+) {
IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
-
+ DirectSoundDevice *device = This->device;
TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppobj);
if (ppobj == NULL) {
if ( IsEqualGUID(riid, &IID_IUnknown) ||
IsEqualGUID(riid, &IID_IDirectSoundBuffer) ) {
- IDirectSoundBuffer_AddRef(iface);
- *ppobj = iface;
+ IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)This);
+ *ppobj = This;
return S_OK;
}
}
if ( IsEqualGUID( &IID_IDirectSound3DListener, riid ) ) {
- *ppobj = &This->IDirectSound3DListener_iface;
- IDirectSound3DListener_AddRef(&This->IDirectSound3DListener_iface);
- return S_OK;
+ if (!device->listener)
+ IDirectSound3DListenerImpl_Create(device, &device->listener);
+ if (device->listener) {
+ *ppobj = device->listener;
+ IDirectSound3DListener_AddRef((LPDIRECTSOUND3DLISTENER)*ppobj);
+ return S_OK;
+ }
+
+ WARN("IID_IDirectSound3DListener failed\n");
+ return E_NOINTERFACE;
}
if ( IsEqualGUID( &IID_IKsPropertySet, riid ) ) {
- *ppobj = &This->IKsPropertySet_iface;
- IKsPropertySet_AddRef(&This->IKsPropertySet_iface);
- return S_OK;
+ FIXME("app requested IKsPropertySet on primary buffer\n");
+ return E_NOINTERFACE;
}
FIXME( "Unknown IID %s\n", debugstr_guid( riid ) );
return DSERR_OUTOFMEMORY;
}
- dsb->ref = 0;
- dsb->ref3D = 0;
- dsb->refiks = 0;
- dsb->numIfaces = 0;
+ dsb->ref = 1;
+ dsb->numIfaces = 1;
dsb->device = device;
dsb->IDirectSoundBuffer8_iface.lpVtbl = (IDirectSoundBuffer8Vtbl *)&dspbvt;
- dsb->IDirectSound3DListener_iface.lpVtbl = &ds3dlvt;
- dsb->IKsPropertySet_iface.lpVtbl = &iksbvt;
dsb->dsbd = *dsbd;
- /* IDirectSound3DListener */
- device->ds3dl.dwSize = sizeof(DS3DLISTENER);
- device->ds3dl.vPosition.x = 0.0;
- device->ds3dl.vPosition.y = 0.0;
- device->ds3dl.vPosition.z = 0.0;
- device->ds3dl.vVelocity.x = 0.0;
- device->ds3dl.vVelocity.y = 0.0;
- device->ds3dl.vVelocity.z = 0.0;
- device->ds3dl.vOrientFront.x = 0.0;
- device->ds3dl.vOrientFront.y = 0.0;
- device->ds3dl.vOrientFront.z = 1.0;
- device->ds3dl.vOrientTop.x = 0.0;
- device->ds3dl.vOrientTop.y = 1.0;
- device->ds3dl.vOrientTop.z = 0.0;
- device->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
- device->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
- device->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
- device->ds3dl_need_recalc = TRUE;
-
TRACE("Created primary buffer at %p\n", dsb);
TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
"bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
device->pwfx->nBlockAlign, device->pwfx->wBitsPerSample,
device->pwfx->cbSize);
- IDirectSoundBuffer_AddRef(&dsb->IDirectSoundBuffer8_iface);
*ppdsb = dsb;
return S_OK;
}
#include "dsound_private.h"
-static WCHAR wInterface[] = { 'I','n','t','e','r','f','a','c','e',0 };
-
typedef struct IKsPrivatePropertySetImpl
{
IKsPropertySet IKsPropertySet_iface;
/* IUnknown methods */
static HRESULT WINAPI IKsPrivatePropertySetImpl_QueryInterface(
- IKsPropertySet *iface, REFIID riid, void **ppobj)
+ LPKSPROPERTYSET iface,
+ REFIID riid,
+ LPVOID *ppobj )
{
IKsPrivatePropertySetImpl *This = impl_from_IKsPropertySet(iface);
TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
if (IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_IKsPropertySet)) {
*ppobj = iface;
- IKsPropertySet_AddRef(iface);
+ IUnknown_AddRef(iface);
return S_OK;
}
*ppobj = NULL;
return ref;
}
-struct search_data {
- const WCHAR *tgt_name;
- GUID *found_guid;
-};
-
-static BOOL CALLBACK search_callback(GUID *guid, const WCHAR *desc,
- const WCHAR *module, void *user)
-{
- struct search_data *search = user;
-
- if(!lstrcmpW(desc, search->tgt_name)){
- *search->found_guid = *guid;
- return FALSE;
- }
-
- return TRUE;
-}
-
static HRESULT DSPROPERTY_WaveDeviceMappingW(
LPVOID pPropData,
ULONG cbPropData,
PULONG pcbReturned )
{
- HRESULT hr;
- PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W_DATA ppd = pPropData;
- struct search_data search;
-
+ HRESULT hr = DSERR_INVALIDPARAM;
+ PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W_DATA ppd;
TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
- pPropData,cbPropData,pcbReturned);
+ pPropData,cbPropData,pcbReturned);
+
+ ppd = pPropData;
if (!ppd) {
- WARN("invalid parameter: pPropData\n");
- return DSERR_INVALIDPARAM;
+ WARN("invalid parameter: pPropData\n");
+ return DSERR_INVALIDPARAM;
}
- search.tgt_name = ppd->DeviceName;
- search.found_guid = &ppd->DeviceId;
-
- if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER)
- hr = enumerate_mmdevices(eRender, DSOUND_renderer_guids,
- search_callback, &search);
- else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE)
- hr = enumerate_mmdevices(eCapture, DSOUND_capture_guids,
- search_callback, &search);
- else
- return DSERR_INVALIDPARAM;
-
- if(hr != S_FALSE)
- /* device was not found */
- return DSERR_INVALIDPARAM;
+ if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) {
+ ULONG wod;
+ unsigned int wodn;
+ TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
+ wodn = waveOutGetNumDevs();
+ for (wod = 0; wod < wodn; wod++) {
+ WAVEOUTCAPSW capsW;
+ MMRESULT res;
+ res = waveOutGetDevCapsW(wod, &capsW, sizeof(capsW));
+ if (res == MMSYSERR_NOERROR) {
+ if (lstrcmpW(capsW.szPname, ppd->DeviceName) == 0) {
+ ppd->DeviceId = DSOUND_renderer_guids[wod];
+ hr = DS_OK;
+ TRACE("found %s for %s\n", debugstr_guid(&ppd->DeviceId),
+ debugstr_w(ppd->DeviceName));
+ break;
+ }
+ }
+ }
+ } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) {
+ ULONG wid;
+ unsigned int widn;
+ TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n");
+ widn = waveInGetNumDevs();
+ for (wid = 0; wid < widn; wid++) {
+ WAVEINCAPSW capsW;
+ MMRESULT res;
+ res = waveInGetDevCapsW(wid, &capsW, sizeof(capsW));
+ if (res == MMSYSERR_NOERROR) {
+ if (lstrcmpW(capsW.szPname, ppd->DeviceName) == 0) {
+ ppd->DeviceId = DSOUND_capture_guids[wid];
+ hr = DS_OK;
+ TRACE("found %s for %s\n", debugstr_guid(&ppd->DeviceId),
+ debugstr_w(ppd->DeviceName));
+ break;
+ }
+ }
+ }
+ }
if (pcbReturned)
*pcbReturned = cbPropData;
- return DS_OK;
+ return hr;
}
static HRESULT DSPROPERTY_WaveDeviceMappingA(
PULONG pcbReturned )
{
PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA ppd = pPropData;
+ HRESULT err;
GUID dev_guid;
- IMMDevice *mmdevice;
- IPropertyStore *ps;
- PROPVARIANT pv;
- DWORD desclen;
- HRESULT hr;
+ ULONG wod, wid, wodn, widn;
+ DSDRIVERDESC desc;
TRACE("pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
pPropData,cbPropData,pcbReturned);
GetDeviceID(&ppd->DeviceId, &dev_guid);
- hr = get_mmdevice(eRender, &dev_guid, &mmdevice);
- if(FAILED(hr)){
- hr = get_mmdevice(eCapture, &dev_guid, &mmdevice);
- if(FAILED(hr))
- return hr;
+ wodn = waveOutGetNumDevs();
+ widn = waveInGetNumDevs();
+ wid = wod = dev_guid.Data4[7];
+ if (!memcmp(&dev_guid, &DSOUND_renderer_guids[0], sizeof(GUID)-1)
+ && wod < wodn)
+ {
+ ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
+ ppd->WaveDeviceId = wod;
+ }
+ else if (!memcmp(&dev_guid, &DSOUND_capture_guids[0], sizeof(GUID)-1)
+ && wid < widn)
+ {
+ ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE;
+ ppd->WaveDeviceId = wid;
+ }
+ else
+ {
+ WARN("Device not found\n");
+ return E_PROP_ID_UNSUPPORTED;
}
- hr = IMMDevice_OpenPropertyStore(mmdevice, STGM_READ, &ps);
- if(FAILED(hr)){
- IMMDevice_Release(mmdevice);
- WARN("OpenPropertyStore failed: %08x\n", hr);
- return hr;
+ if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER)
+ err = waveOutMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,ds_hw_accel);
+ else
+ err = waveInMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,ds_hw_accel);
+
+ if (err != MMSYSERR_NOERROR)
+ {
+ WARN("waveMessage(DRV_QUERYDSOUNDDESC) failed!\n");
+ return E_PROP_ID_UNSUPPORTED;
}
+ else
+ {
+ /* FIXME: Still a memory leak.. */
+ int desclen, modlen;
+ static WCHAR wInterface[] = { 'I','n','t','e','r','f','a','c','e',0 };
+
+ modlen = MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, NULL, 0 );
+ desclen = MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, NULL, 0 );
+ ppd->Module = HeapAlloc(GetProcessHeap(),0,modlen*sizeof(WCHAR));
+ ppd->Description = HeapAlloc(GetProcessHeap(),0,desclen*sizeof(WCHAR));
+ ppd->Interface = wInterface;
+ if (!ppd->Description || !ppd->Module)
+ {
+ WARN("Out of memory\n");
+ HeapFree(GetProcessHeap(), 0, ppd->Description);
+ HeapFree(GetProcessHeap(), 0, ppd->Module);
+ ppd->Description = ppd->Module = NULL;
+ return E_OUTOFMEMORY;
+ }
- hr = IPropertyStore_GetValue(ps,
- (const PROPERTYKEY *)&DEVPKEY_Device_FriendlyName, &pv);
- if(FAILED(hr)){
- IPropertyStore_Release(ps);
- IMMDevice_Release(mmdevice);
- WARN("GetValue(FriendlyName) failed: %08x\n", hr);
- return hr;
+ MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, ppd->Module, modlen );
+ MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->Description, desclen );
}
- desclen = lstrlenW(pv.u.pwszVal) + 1;
- /* FIXME: Still a memory leak.. */
- ppd->Description = HeapAlloc(GetProcessHeap(), 0, desclen * sizeof(WCHAR));
- memcpy(ppd->Description, pv.u.pwszVal, desclen * sizeof(WCHAR));
- ppd->Module = wine_vxd_drv;
- ppd->Interface = wInterface;
ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
- PropVariantClear(&pv);
- IPropertyStore_Release(ps);
- IMMDevice_Release(mmdevice);
-
if (pcbReturned) {
*pcbReturned = sizeof(*ppd);
TRACE("*pcbReturned=%d\n", *pcbReturned);
return S_OK;
}
-static
-BOOL CALLBACK enum_callback(GUID *guid, const WCHAR *desc, const WCHAR *module,
- void *user)
-{
- PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA ppd = user;
- DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data;
- DWORD len;
- BOOL ret;
-
- TRACE("%s %s %s %p\n", wine_dbgstr_guid(guid), wine_dbgstr_w(desc),
- wine_dbgstr_w(module), user);
-
- if(!guid)
- return TRUE;
-
- data.DeviceId = *guid;
-
- len = lstrlenW(module) + 1;
- data.Module = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
- memcpy(data.Module, module, len * sizeof(WCHAR));
-
- len = lstrlenW(desc) + 1;
- data.Description = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
- memcpy(data.Description, desc, len * sizeof(WCHAR));
-
- data.Interface = wInterface;
-
- ret = ppd->Callback(&data, ppd->Context);
-
- HeapFree(GetProcessHeap(), 0, data.Module);
- HeapFree(GetProcessHeap(), 0, data.Description);
-
- return ret;
-}
-
static HRESULT DSPROPERTY_EnumerateW(
LPVOID pPropData,
ULONG cbPropData,
PULONG pcbReturned )
{
PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA ppd = pPropData;
- HRESULT hr;
-
+ DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data;
+ BOOL ret;
+ int widn, wodn, i;
TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
pPropData,cbPropData,pcbReturned);
return E_PROP_ID_UNSUPPORTED;
}
- hr = enumerate_mmdevices(eRender, DSOUND_renderer_guids,
- enum_callback, ppd);
+ wodn = waveOutGetNumDevs();
+ widn = waveInGetNumDevs();
- if(hr == S_OK)
- hr = enumerate_mmdevices(eCapture, DSOUND_capture_guids,
- enum_callback, ppd);
+ data.DeviceId = DSOUND_renderer_guids[0];
+ for (i = 0; i < wodn; ++i)
+ {
+ HRESULT hr;
+ data.DeviceId.Data4[7] = i;
+ hr = DSPROPERTY_DescriptionW(&data, sizeof(data), NULL);
+ if (FAILED(hr))
+ {
+ ERR("DescriptionW failed!\n");
+ return S_OK;
+ }
+ ret = ppd->Callback(&data, ppd->Context);
+ HeapFree(GetProcessHeap(), 0, data.Module);
+ HeapFree(GetProcessHeap(), 0, data.Description);
+ if (!ret)
+ return S_OK;
+ }
- return SUCCEEDED(hr) ? DS_OK : hr;
+ data.DeviceId = DSOUND_capture_guids[0];
+ for (i = 0; i < widn; ++i)
+ {
+ HRESULT hr;
+ data.DeviceId.Data4[7] = i;
+ hr = DSPROPERTY_DescriptionW(&data, sizeof(data), NULL);
+ if (FAILED(hr))
+ {
+ ERR("DescriptionW failed!\n");
+ return S_OK;
+ }
+ ret = ppd->Callback(&data, ppd->Context);
+ HeapFree(GetProcessHeap(), 0, data.Module);
+ HeapFree(GetProcessHeap(), 0, data.Description);
+ if (!ret)
+ return S_OK;
+ }
+ return S_OK;
}
static BOOL DSPROPERTY_descWtoA(const DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA *dataW,
IKsPrivatePropertySetImpl_QuerySupport
};
-HRESULT IKsPrivatePropertySetImpl_Create(REFIID riid, void **ppv)
+HRESULT IKsPrivatePropertySetImpl_Create(
+ REFIID riid,
+ IKsPropertySet **piks)
{
IKsPrivatePropertySetImpl *iks;
- HRESULT hr;
+ TRACE("(%s, %p)\n", debugstr_guid(riid), piks);
- TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
-
- iks = HeapAlloc(GetProcessHeap(), 0, sizeof(*iks));
- if (!iks) {
- WARN("out of memory\n");
- return DSERR_OUTOFMEMORY;
+ if (!IsEqualIID(riid, &IID_IUnknown) &&
+ !IsEqualIID(riid, &IID_IKsPropertySet)) {
+ *piks = 0;
+ return E_NOINTERFACE;
}
+ iks = HeapAlloc(GetProcessHeap(),0,sizeof(*iks));
iks->ref = 1;
iks->IKsPropertySet_iface.lpVtbl = &ikspvt;
- hr = IKsPropertySet_QueryInterface(&iks->IKsPropertySet_iface, riid, ppv);
- IKsPropertySet_Release(&iks->IKsPropertySet_iface);
-
- return hr;
+ *piks = &iks->IKsPropertySet_iface;
+ return S_OK;
}
D3DVALUE flAngle;
D3DVECTOR vLeft;
/* doppler shift related stuff */
+#if 0
+ D3DVALUE flFreq, flBufferVel, flListenerVel;
+#endif
TRACE("(%p)\n",dsb);
TRACE("panning: Angle = %f rad, lPan = %d\n", flAngle, dsb->volpan.lPan);
/* FIXME: Doppler Effect disabled since i have no idea which frequency to change and how to do it */
-if(0)
-{
- D3DVALUE flFreq, flBufferVel, flListenerVel;
+#if 0
/* doppler shift*/
- if (!VectorMagnitude(&dsb->ds3db_ds3db.vVelocity) && !VectorMagnitude(&dsb->device->ds3dl.vVelocity))
+ if ((VectorMagnitude(&ds3db_ds3db.vVelocity) == 0) && (VectorMagnitude(&dsb->device->ds3dl.vVelocity) == 0))
{
TRACE("doppler: Buffer and Listener don't have velocities\n");
}
- else if (!(dsb->ds3db_ds3db.vVelocity.x == dsb->device->ds3dl.vVelocity.x &&
- dsb->ds3db_ds3db.vVelocity.y == dsb->device->ds3dl.vVelocity.y &&
- dsb->ds3db_ds3db.vVelocity.z == dsb->device->ds3dl.vVelocity.z))
+ else if (ds3db_ds3db.vVelocity != dsb->device->ds3dl.vVelocity)
{
/* calculate length of ds3db_ds3db.vVelocity component which causes Doppler Effect
NOTE: if buffer moves TOWARDS the listener, it's velocity component is NEGATIVE
/* formula taken from Gianicoli D.: Physics, 4th edition: */
/* FIXME: replace dsb->freq with appropriate frequency ! */
flFreq = dsb->freq * ((DEFAULT_VELOCITY + flListenerVel)/(DEFAULT_VELOCITY + flBufferVel));
- TRACE("doppler: Buffer velocity (component) = %f, Listener velocity (component) = %f => Doppler shift: %d Hz -> %f Hz\n",
- flBufferVel, flListenerVel, dsb->freq, flFreq);
+ TRACE("doppler: Buffer velocity (component) = %lf, Listener velocity (component) = %lf => Doppler shift: %ld Hz -> %lf Hz\n", flBufferVel, flListenerVel,
+ dsb->freq, flFreq);
/* FIXME: replace following line with correct frequency setting ! */
dsb->freq = flFreq;
DSOUND_RecalcFormat(dsb);
+ DSOUND_MixToTemporary(dsb, 0, dsb->buflen);
}
-}
+#endif
/* time for remix */
DSOUND_RecalcVolPan(&dsb->volpan);
DSOUND_Calc3DBuffer(dsb);
}
-static void DSOUND_ChangeListener(IDirectSoundBufferImpl *ds3dl)
+static void DSOUND_ChangeListener(IDirectSound3DListenerImpl *ds3dl)
{
int i;
TRACE("(%p)\n",ds3dl);
/*******************************************************************************
* IDirectSound3DBuffer
*/
-static inline IDirectSoundBufferImpl *impl_from_IDirectSound3DBuffer(IDirectSound3DBuffer *iface)
-{
- return CONTAINING_RECORD(iface, IDirectSoundBufferImpl, IDirectSound3DBuffer_iface);
-}
/* IUnknown methods */
-static HRESULT WINAPI IDirectSound3DBufferImpl_QueryInterface(IDirectSound3DBuffer *iface,
- REFIID riid, void **ppobj)
+static HRESULT WINAPI IDirectSound3DBufferImpl_QueryInterface(
+ LPDIRECTSOUND3DBUFFER iface, REFIID riid, LPVOID *ppobj)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DBuffer(iface);
+ IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
- TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppobj);
-
- return IDirectSoundBuffer8_QueryInterface(&This->IDirectSoundBuffer8_iface, riid, ppobj);
+ TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+ return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb, riid, ppobj);
}
-static ULONG WINAPI IDirectSound3DBufferImpl_AddRef(IDirectSound3DBuffer *iface)
+static ULONG WINAPI IDirectSound3DBufferImpl_AddRef(LPDIRECTSOUND3DBUFFER iface)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DBuffer(iface);
- ULONG ref = InterlockedIncrement(&This->ref3D);
+ IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
+ ULONG ref = InterlockedIncrement(&(This->ref));
TRACE("(%p) ref was %d\n", This, ref - 1);
if(ref == 1)
- InterlockedIncrement(&This->numIfaces);
+ InterlockedIncrement(&This->dsb->numIfaces);
return ref;
}
-static ULONG WINAPI IDirectSound3DBufferImpl_Release(IDirectSound3DBuffer *iface)
+static ULONG WINAPI IDirectSound3DBufferImpl_Release(LPDIRECTSOUND3DBUFFER iface)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DBuffer(iface);
- ULONG ref = InterlockedDecrement(&This->ref3D);
-
+ IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
+ ULONG ref = InterlockedDecrement(&(This->ref));
TRACE("(%p) ref was %d\n", This, ref + 1);
- if (!ref && !InterlockedDecrement(&This->numIfaces))
- secondarybuffer_destroy(This);
-
+ if (!ref) {
+ This->dsb->ds3db = NULL;
+ if (!InterlockedDecrement(&This->dsb->numIfaces))
+ secondarybuffer_destroy(This->dsb);
+ HeapFree(GetProcessHeap(), 0, This);
+ TRACE("(%p) released\n", This);
+ }
return ref;
}
/* IDirectSound3DBuffer methods */
-static HRESULT WINAPI IDirectSound3DBufferImpl_GetAllParameters(IDirectSound3DBuffer *iface,
- DS3DBUFFER *lpDs3dBuffer)
+static HRESULT WINAPI IDirectSound3DBufferImpl_GetAllParameters(
+ LPDIRECTSOUND3DBUFFER iface,
+ LPDS3DBUFFER lpDs3dBuffer)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DBuffer(iface);
-
+ IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
TRACE("(%p,%p)\n",This,lpDs3dBuffer);
if (lpDs3dBuffer == NULL) {
}
TRACE("returning: all parameters\n");
- *lpDs3dBuffer = This->ds3db_ds3db;
+ *lpDs3dBuffer = This->dsb->ds3db_ds3db;
return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeAngles(IDirectSound3DBuffer *iface,
- DWORD *lpdwInsideConeAngle, DWORD *lpdwOutsideConeAngle)
+static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeAngles(
+ LPDIRECTSOUND3DBUFFER iface,
+ LPDWORD lpdwInsideConeAngle,
+ LPDWORD lpdwOutsideConeAngle)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DBuffer(iface);
-
- TRACE("returning: Inside Cone Angle = %d degrees; Outside Cone Angle = %d degrees\n",
- This->ds3db_ds3db.dwInsideConeAngle, This->ds3db_ds3db.dwOutsideConeAngle);
- *lpdwInsideConeAngle = This->ds3db_ds3db.dwInsideConeAngle;
- *lpdwOutsideConeAngle = This->ds3db_ds3db.dwOutsideConeAngle;
- return DS_OK;
+ IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
+ TRACE("returning: Inside Cone Angle = %d degrees; Outside Cone Angle = %d degrees\n",
+ This->dsb->ds3db_ds3db.dwInsideConeAngle, This->dsb->ds3db_ds3db.dwOutsideConeAngle);
+ *lpdwInsideConeAngle = This->dsb->ds3db_ds3db.dwInsideConeAngle;
+ *lpdwOutsideConeAngle = This->dsb->ds3db_ds3db.dwOutsideConeAngle;
+ return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeOrientation(IDirectSound3DBuffer *iface,
- D3DVECTOR *lpvConeOrientation)
+static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeOrientation(
+ LPDIRECTSOUND3DBUFFER iface,
+ LPD3DVECTOR lpvConeOrientation)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DBuffer(iface);
-
- TRACE("returning: Cone Orientation vector = (%f,%f,%f)\n",
- This->ds3db_ds3db.vConeOrientation.x,
- This->ds3db_ds3db.vConeOrientation.y,
- This->ds3db_ds3db.vConeOrientation.z);
- *lpvConeOrientation = This->ds3db_ds3db.vConeOrientation;
- return DS_OK;
+ IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
+ TRACE("returning: Cone Orientation vector = (%f,%f,%f)\n",
+ This->dsb->ds3db_ds3db.vConeOrientation.x,
+ This->dsb->ds3db_ds3db.vConeOrientation.y,
+ This->dsb->ds3db_ds3db.vConeOrientation.z);
+ *lpvConeOrientation = This->dsb->ds3db_ds3db.vConeOrientation;
+ return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeOutsideVolume(IDirectSound3DBuffer *iface,
- LONG *lplConeOutsideVolume)
+static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeOutsideVolume(
+ LPDIRECTSOUND3DBUFFER iface,
+ LPLONG lplConeOutsideVolume)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DBuffer(iface);
-
- TRACE("returning: Cone Outside Volume = %d\n", This->ds3db_ds3db.lConeOutsideVolume);
- *lplConeOutsideVolume = This->ds3db_ds3db.lConeOutsideVolume;
- return DS_OK;
+ IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
+ TRACE("returning: Cone Outside Volume = %d\n", This->dsb->ds3db_ds3db.lConeOutsideVolume);
+ *lplConeOutsideVolume = This->dsb->ds3db_ds3db.lConeOutsideVolume;
+ return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DBufferImpl_GetMaxDistance(IDirectSound3DBuffer *iface,
- D3DVALUE *lpfMaxDistance)
+static HRESULT WINAPI IDirectSound3DBufferImpl_GetMaxDistance(
+ LPDIRECTSOUND3DBUFFER iface,
+ LPD3DVALUE lpfMaxDistance)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DBuffer(iface);
-
- TRACE("returning: Max Distance = %f\n", This->ds3db_ds3db.flMaxDistance);
- *lpfMaxDistance = This->ds3db_ds3db.flMaxDistance;
- return DS_OK;
+ IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
+ TRACE("returning: Max Distance = %f\n", This->dsb->ds3db_ds3db.flMaxDistance);
+ *lpfMaxDistance = This->dsb->ds3db_ds3db.flMaxDistance;
+ return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DBufferImpl_GetMinDistance(IDirectSound3DBuffer *iface,
- D3DVALUE *lpfMinDistance)
+static HRESULT WINAPI IDirectSound3DBufferImpl_GetMinDistance(
+ LPDIRECTSOUND3DBUFFER iface,
+ LPD3DVALUE lpfMinDistance)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DBuffer(iface);
-
- TRACE("returning: Min Distance = %f\n", This->ds3db_ds3db.flMinDistance);
- *lpfMinDistance = This->ds3db_ds3db.flMinDistance;
- return DS_OK;
+ IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
+ TRACE("returning: Min Distance = %f\n", This->dsb->ds3db_ds3db.flMinDistance);
+ *lpfMinDistance = This->dsb->ds3db_ds3db.flMinDistance;
+ return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DBufferImpl_GetMode(IDirectSound3DBuffer *iface,
- DWORD *lpdwMode)
+static HRESULT WINAPI IDirectSound3DBufferImpl_GetMode(
+ LPDIRECTSOUND3DBUFFER iface,
+ LPDWORD lpdwMode)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DBuffer(iface);
-
- TRACE("returning: Mode = %d\n", This->ds3db_ds3db.dwMode);
- *lpdwMode = This->ds3db_ds3db.dwMode;
- return DS_OK;
+ IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
+ TRACE("returning: Mode = %d\n", This->dsb->ds3db_ds3db.dwMode);
+ *lpdwMode = This->dsb->ds3db_ds3db.dwMode;
+ return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DBufferImpl_GetPosition(IDirectSound3DBuffer *iface,
- D3DVECTOR *lpvPosition)
+static HRESULT WINAPI IDirectSound3DBufferImpl_GetPosition(
+ LPDIRECTSOUND3DBUFFER iface,
+ LPD3DVECTOR lpvPosition)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DBuffer(iface);
-
- TRACE("returning: Position vector = (%f,%f,%f)\n", This->ds3db_ds3db.vPosition.x,
- This->ds3db_ds3db.vPosition.y, This->ds3db_ds3db.vPosition.z);
- *lpvPosition = This->ds3db_ds3db.vPosition;
- return DS_OK;
+ IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
+ TRACE("returning: Position vector = (%f,%f,%f)\n",
+ This->dsb->ds3db_ds3db.vPosition.x,
+ This->dsb->ds3db_ds3db.vPosition.y,
+ This->dsb->ds3db_ds3db.vPosition.z);
+ *lpvPosition = This->dsb->ds3db_ds3db.vPosition;
+ return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DBufferImpl_GetVelocity(IDirectSound3DBuffer *iface,
- D3DVECTOR *lpvVelocity)
+static HRESULT WINAPI IDirectSound3DBufferImpl_GetVelocity(
+ LPDIRECTSOUND3DBUFFER iface,
+ LPD3DVECTOR lpvVelocity)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DBuffer(iface);
-
- TRACE("returning: Velocity vector = (%f,%f,%f)\n", This->ds3db_ds3db.vVelocity.x,
- This->ds3db_ds3db.vVelocity.y, This->ds3db_ds3db.vVelocity.z);
- *lpvVelocity = This->ds3db_ds3db.vVelocity;
- return DS_OK;
+ IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
+ TRACE("returning: Velocity vector = (%f,%f,%f)\n",
+ This->dsb->ds3db_ds3db.vVelocity.x,
+ This->dsb->ds3db_ds3db.vVelocity.y,
+ This->dsb->ds3db_ds3db.vVelocity.z);
+ *lpvVelocity = This->dsb->ds3db_ds3db.vVelocity;
+ return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DBufferImpl_SetAllParameters(IDirectSound3DBuffer *iface,
- const DS3DBUFFER *lpcDs3dBuffer, DWORD dwApply)
+static HRESULT WINAPI IDirectSound3DBufferImpl_SetAllParameters(
+ LPDIRECTSOUND3DBUFFER iface,
+ LPCDS3DBUFFER lpcDs3dBuffer,
+ DWORD dwApply)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DBuffer(iface);
+ IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
DWORD status = DSERR_INVALIDPARAM;
-
TRACE("(%p,%p,%x)\n",iface,lpcDs3dBuffer,dwApply);
if (lpcDs3dBuffer == NULL) {
}
TRACE("setting: all parameters; dwApply = %d\n", dwApply);
- This->ds3db_ds3db = *lpcDs3dBuffer;
+ This->dsb->ds3db_ds3db = *lpcDs3dBuffer;
if (dwApply == DS3D_IMMEDIATE)
{
- DSOUND_Mix3DBuffer(This);
+ DSOUND_Mix3DBuffer(This->dsb);
}
- This->ds3db_need_recalc = TRUE;
+ This->dsb->ds3db_need_recalc = TRUE;
status = DS_OK;
return status;
}
-static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeAngles(IDirectSound3DBuffer *iface,
- DWORD dwInsideConeAngle, DWORD dwOutsideConeAngle, DWORD dwApply)
+static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeAngles(
+ LPDIRECTSOUND3DBUFFER iface,
+ DWORD dwInsideConeAngle,
+ DWORD dwOutsideConeAngle,
+ DWORD dwApply)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DBuffer(iface);
-
- TRACE("setting: Inside Cone Angle = %d; Outside Cone Angle = %d; dwApply = %d\n",
- dwInsideConeAngle, dwOutsideConeAngle, dwApply);
- This->ds3db_ds3db.dwInsideConeAngle = dwInsideConeAngle;
- This->ds3db_ds3db.dwOutsideConeAngle = dwOutsideConeAngle;
- if (dwApply == DS3D_IMMEDIATE)
- DSOUND_Mix3DBuffer(This);
- This->ds3db_need_recalc = TRUE;
- return DS_OK;
+ IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
+ TRACE("setting: Inside Cone Angle = %d; Outside Cone Angle = %d; dwApply = %d\n",
+ dwInsideConeAngle, dwOutsideConeAngle, dwApply);
+ This->dsb->ds3db_ds3db.dwInsideConeAngle = dwInsideConeAngle;
+ This->dsb->ds3db_ds3db.dwOutsideConeAngle = dwOutsideConeAngle;
+ if (dwApply == DS3D_IMMEDIATE)
+ {
+ DSOUND_Mix3DBuffer(This->dsb);
+ }
+ This->dsb->ds3db_need_recalc = TRUE;
+ return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeOrientation(IDirectSound3DBuffer *iface,
- D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply)
+static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeOrientation(
+ LPDIRECTSOUND3DBUFFER iface,
+ D3DVALUE x, D3DVALUE y, D3DVALUE z,
+ DWORD dwApply)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DBuffer(iface);
-
- TRACE("setting: Cone Orientation vector = (%f,%f,%f); dwApply = %d\n", x, y, z, dwApply);
- This->ds3db_ds3db.vConeOrientation.x = x;
- This->ds3db_ds3db.vConeOrientation.y = y;
- This->ds3db_ds3db.vConeOrientation.z = z;
- if (dwApply == DS3D_IMMEDIATE)
- {
- This->ds3db_need_recalc = FALSE;
- DSOUND_Mix3DBuffer(This);
- }
- This->ds3db_need_recalc = TRUE;
- return DS_OK;
+ IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
+ TRACE("setting: Cone Orientation vector = (%f,%f,%f); dwApply = %d\n", x, y, z, dwApply);
+ This->dsb->ds3db_ds3db.vConeOrientation.x = x;
+ This->dsb->ds3db_ds3db.vConeOrientation.y = y;
+ This->dsb->ds3db_ds3db.vConeOrientation.z = z;
+ if (dwApply == DS3D_IMMEDIATE)
+ {
+ This->dsb->ds3db_need_recalc = FALSE;
+ DSOUND_Mix3DBuffer(This->dsb);
+ }
+ This->dsb->ds3db_need_recalc = TRUE;
+ return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeOutsideVolume(IDirectSound3DBuffer *iface,
- LONG lConeOutsideVolume, DWORD dwApply)
+static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeOutsideVolume(
+ LPDIRECTSOUND3DBUFFER iface,
+ LONG lConeOutsideVolume,
+ DWORD dwApply)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DBuffer(iface);
-
- TRACE("setting: ConeOutsideVolume = %d; dwApply = %d\n", lConeOutsideVolume, dwApply);
- This->ds3db_ds3db.lConeOutsideVolume = lConeOutsideVolume;
- if (dwApply == DS3D_IMMEDIATE)
- {
- This->ds3db_need_recalc = FALSE;
- DSOUND_Mix3DBuffer(This);
- }
- This->ds3db_need_recalc = TRUE;
- return DS_OK;
+ IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
+ TRACE("setting: ConeOutsideVolume = %d; dwApply = %d\n", lConeOutsideVolume, dwApply);
+ This->dsb->ds3db_ds3db.lConeOutsideVolume = lConeOutsideVolume;
+ if (dwApply == DS3D_IMMEDIATE)
+ {
+ This->dsb->ds3db_need_recalc = FALSE;
+ DSOUND_Mix3DBuffer(This->dsb);
+ }
+ This->dsb->ds3db_need_recalc = TRUE;
+ return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DBufferImpl_SetMaxDistance(IDirectSound3DBuffer *iface,
- D3DVALUE fMaxDistance, DWORD dwApply)
+static HRESULT WINAPI IDirectSound3DBufferImpl_SetMaxDistance(
+ LPDIRECTSOUND3DBUFFER iface,
+ D3DVALUE fMaxDistance,
+ DWORD dwApply)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DBuffer(iface);
-
- TRACE("setting: MaxDistance = %f; dwApply = %d\n", fMaxDistance, dwApply);
- This->ds3db_ds3db.flMaxDistance = fMaxDistance;
- if (dwApply == DS3D_IMMEDIATE)
- {
- This->ds3db_need_recalc = FALSE;
- DSOUND_Mix3DBuffer(This);
- }
- This->ds3db_need_recalc = TRUE;
- return DS_OK;
+ IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
+ TRACE("setting: MaxDistance = %f; dwApply = %d\n", fMaxDistance, dwApply);
+ This->dsb->ds3db_ds3db.flMaxDistance = fMaxDistance;
+ if (dwApply == DS3D_IMMEDIATE)
+ {
+ This->dsb->ds3db_need_recalc = FALSE;
+ DSOUND_Mix3DBuffer(This->dsb);
+ }
+ This->dsb->ds3db_need_recalc = TRUE;
+ return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DBufferImpl_SetMinDistance(IDirectSound3DBuffer *iface,
- D3DVALUE fMinDistance, DWORD dwApply)
+static HRESULT WINAPI IDirectSound3DBufferImpl_SetMinDistance(
+ LPDIRECTSOUND3DBUFFER iface,
+ D3DVALUE fMinDistance,
+ DWORD dwApply)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DBuffer(iface);
-
- TRACE("setting: MinDistance = %f; dwApply = %d\n", fMinDistance, dwApply);
- This->ds3db_ds3db.flMinDistance = fMinDistance;
- if (dwApply == DS3D_IMMEDIATE)
- {
- This->ds3db_need_recalc = FALSE;
- DSOUND_Mix3DBuffer(This);
- }
- This->ds3db_need_recalc = TRUE;
- return DS_OK;
+ IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
+ TRACE("setting: MinDistance = %f; dwApply = %d\n", fMinDistance, dwApply);
+ This->dsb->ds3db_ds3db.flMinDistance = fMinDistance;
+ if (dwApply == DS3D_IMMEDIATE)
+ {
+ This->dsb->ds3db_need_recalc = FALSE;
+ DSOUND_Mix3DBuffer(This->dsb);
+ }
+ This->dsb->ds3db_need_recalc = TRUE;
+ return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DBufferImpl_SetMode(IDirectSound3DBuffer *iface, DWORD dwMode,
- DWORD dwApply)
+static HRESULT WINAPI IDirectSound3DBufferImpl_SetMode(
+ LPDIRECTSOUND3DBUFFER iface,
+ DWORD dwMode,
+ DWORD dwApply)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DBuffer(iface);
-
- TRACE("setting: Mode = %d; dwApply = %d\n", dwMode, dwApply);
- This->ds3db_ds3db.dwMode = dwMode;
- if (dwApply == DS3D_IMMEDIATE)
- {
- This->ds3db_need_recalc = FALSE;
- DSOUND_Mix3DBuffer(This);
- }
- This->ds3db_need_recalc = TRUE;
- return DS_OK;
+ IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
+ TRACE("setting: Mode = %d; dwApply = %d\n", dwMode, dwApply);
+ This->dsb->ds3db_ds3db.dwMode = dwMode;
+ if (dwApply == DS3D_IMMEDIATE)
+ {
+ This->dsb->ds3db_need_recalc = FALSE;
+ DSOUND_Mix3DBuffer(This->dsb);
+ }
+ This->dsb->ds3db_need_recalc = TRUE;
+ return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DBufferImpl_SetPosition(IDirectSound3DBuffer *iface, D3DVALUE x,
- D3DVALUE y, D3DVALUE z, DWORD dwApply)
+static HRESULT WINAPI IDirectSound3DBufferImpl_SetPosition(
+ LPDIRECTSOUND3DBUFFER iface,
+ D3DVALUE x, D3DVALUE y, D3DVALUE z,
+ DWORD dwApply)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DBuffer(iface);
-
- TRACE("setting: Position vector = (%f,%f,%f); dwApply = %d\n", x, y, z, dwApply);
- This->ds3db_ds3db.vPosition.x = x;
- This->ds3db_ds3db.vPosition.y = y;
- This->ds3db_ds3db.vPosition.z = z;
- if (dwApply == DS3D_IMMEDIATE)
- {
- This->ds3db_need_recalc = FALSE;
- DSOUND_Mix3DBuffer(This);
- }
- This->ds3db_need_recalc = TRUE;
- return DS_OK;
+ IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
+ TRACE("setting: Position vector = (%f,%f,%f); dwApply = %d\n", x, y, z, dwApply);
+ This->dsb->ds3db_ds3db.vPosition.x = x;
+ This->dsb->ds3db_ds3db.vPosition.y = y;
+ This->dsb->ds3db_ds3db.vPosition.z = z;
+ if (dwApply == DS3D_IMMEDIATE)
+ {
+ This->dsb->ds3db_need_recalc = FALSE;
+ DSOUND_Mix3DBuffer(This->dsb);
+ }
+ This->dsb->ds3db_need_recalc = TRUE;
+ return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DBufferImpl_SetVelocity(IDirectSound3DBuffer *iface,
- D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply)
+static HRESULT WINAPI IDirectSound3DBufferImpl_SetVelocity(
+ LPDIRECTSOUND3DBUFFER iface,
+ D3DVALUE x, D3DVALUE y, D3DVALUE z,
+ DWORD dwApply)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DBuffer(iface);
-
- TRACE("setting: Velocity vector = (%f,%f,%f); dwApply = %d\n", x, y, z, dwApply);
- This->ds3db_ds3db.vVelocity.x = x;
- This->ds3db_ds3db.vVelocity.y = y;
- This->ds3db_ds3db.vVelocity.z = z;
- if (dwApply == DS3D_IMMEDIATE)
- {
- This->ds3db_need_recalc = FALSE;
- DSOUND_Mix3DBuffer(This);
- }
- This->ds3db_need_recalc = TRUE;
- return DS_OK;
+ IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
+ TRACE("setting: Velocity vector = (%f,%f,%f); dwApply = %d\n", x, y, z, dwApply);
+ This->dsb->ds3db_ds3db.vVelocity.x = x;
+ This->dsb->ds3db_ds3db.vVelocity.y = y;
+ This->dsb->ds3db_ds3db.vVelocity.z = z;
+ if (dwApply == DS3D_IMMEDIATE)
+ {
+ This->dsb->ds3db_need_recalc = FALSE;
+ DSOUND_Mix3DBuffer(This->dsb);
+ }
+ This->dsb->ds3db_need_recalc = TRUE;
+ return DS_OK;
}
-const IDirectSound3DBufferVtbl ds3dbvt =
+static const IDirectSound3DBufferVtbl ds3dbvt =
{
/* IUnknown methods */
IDirectSound3DBufferImpl_QueryInterface,
IDirectSound3DBufferImpl_SetVelocity,
};
+HRESULT IDirectSound3DBufferImpl_Create(
+ IDirectSoundBufferImpl *dsb,
+ IDirectSound3DBufferImpl **pds3db)
+{
+ IDirectSound3DBufferImpl *ds3db;
+ TRACE("(%p,%p)\n",dsb,pds3db);
-/*******************************************************************************
- * IDirectSound3DListener
- */
-static inline IDirectSoundBufferImpl *impl_from_IDirectSound3DListener(IDirectSound3DListener *iface)
+ ds3db = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*ds3db));
+
+ if (ds3db == NULL) {
+ WARN("out of memory\n");
+ *pds3db = 0;
+ return DSERR_OUTOFMEMORY;
+ }
+
+ ds3db->ref = 0;
+ ds3db->dsb = dsb;
+ ds3db->lpVtbl = &ds3dbvt;
+
+ ds3db->dsb->ds3db_ds3db.dwSize = sizeof(DS3DBUFFER);
+ ds3db->dsb->ds3db_ds3db.vPosition.x = 0.0;
+ ds3db->dsb->ds3db_ds3db.vPosition.y = 0.0;
+ ds3db->dsb->ds3db_ds3db.vPosition.z = 0.0;
+ ds3db->dsb->ds3db_ds3db.vVelocity.x = 0.0;
+ ds3db->dsb->ds3db_ds3db.vVelocity.y = 0.0;
+ ds3db->dsb->ds3db_ds3db.vVelocity.z = 0.0;
+ ds3db->dsb->ds3db_ds3db.dwInsideConeAngle = DS3D_DEFAULTCONEANGLE;
+ ds3db->dsb->ds3db_ds3db.dwOutsideConeAngle = DS3D_DEFAULTCONEANGLE;
+ ds3db->dsb->ds3db_ds3db.vConeOrientation.x = 0.0;
+ ds3db->dsb->ds3db_ds3db.vConeOrientation.y = 0.0;
+ ds3db->dsb->ds3db_ds3db.vConeOrientation.z = 0.0;
+ ds3db->dsb->ds3db_ds3db.lConeOutsideVolume = DS3D_DEFAULTCONEOUTSIDEVOLUME;
+ ds3db->dsb->ds3db_ds3db.flMinDistance = DS3D_DEFAULTMINDISTANCE;
+ ds3db->dsb->ds3db_ds3db.flMaxDistance = DS3D_DEFAULTMAXDISTANCE;
+ ds3db->dsb->ds3db_ds3db.dwMode = DS3DMODE_NORMAL;
+
+ ds3db->dsb->ds3db_need_recalc = TRUE;
+
+ *pds3db = ds3db;
+ return S_OK;
+}
+
+HRESULT IDirectSound3DBufferImpl_Destroy(
+ IDirectSound3DBufferImpl *pds3db)
{
- return CONTAINING_RECORD(iface, IDirectSoundBufferImpl, IDirectSound3DListener_iface);
+ TRACE("(%p)\n",pds3db);
+
+ while (IDirectSound3DBufferImpl_Release((LPDIRECTSOUND3DBUFFER)pds3db) > 0);
+
+ return S_OK;
}
+/*******************************************************************************
+ * IDirectSound3DListener
+ */
/* IUnknown methods */
-static HRESULT WINAPI IDirectSound3DListenerImpl_QueryInterface(IDirectSound3DListener *iface,
- REFIID riid, void **ppobj)
+static HRESULT WINAPI IDirectSound3DListenerImpl_QueryInterface(
+ LPDIRECTSOUND3DLISTENER iface, REFIID riid, LPVOID *ppobj)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DListener(iface);
+ IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)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_IDirectSound3DListener ) ) {
+ IDirectSound3DListener_AddRef((LPDIRECTSOUND3DLISTENER)This);
+ *ppobj = This;
+ return S_OK;
+ }
- TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppobj);
+ if ( IsEqualGUID(riid, &IID_IDirectSoundBuffer) ) {
+ *ppobj = &This->device->primary->IDirectSoundBuffer8_iface;
+ IDirectSoundBuffer8_AddRef(&This->device->primary->IDirectSoundBuffer8_iface);
+ return S_OK;
+ }
- return IDirectSoundBuffer_QueryInterface(&This->IDirectSoundBuffer8_iface, riid, ppobj);
+ FIXME( "Unknown IID %s\n", debugstr_guid( riid ) );
+ return E_NOINTERFACE;
}
-static ULONG WINAPI IDirectSound3DListenerImpl_AddRef(IDirectSound3DListener *iface)
+static ULONG WINAPI IDirectSound3DListenerImpl_AddRef(LPDIRECTSOUND3DLISTENER iface)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DListener(iface);
- ULONG ref = InterlockedIncrement(&This->ref3D);
+ IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
+ ULONG ref = InterlockedIncrement(&(This->ref));
TRACE("(%p) ref was %d\n", This, ref - 1);
if(ref == 1)
- InterlockedIncrement(&This->numIfaces);
+ InterlockedIncrement(&This->device->primary->numIfaces);
return ref;
}
-static ULONG WINAPI IDirectSound3DListenerImpl_Release(IDirectSound3DListener *iface)
+static ULONG WINAPI IDirectSound3DListenerImpl_Release(LPDIRECTSOUND3DLISTENER iface)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DListener(iface);
- ULONG ref;
-
- ref = capped_refcount_dec(&This->ref3D);
- if(!ref)
- capped_refcount_dec(&This->numIfaces);
-
- TRACE("(%p) ref is now %d\n", This, ref);
+ IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
+ ULONG ref = InterlockedDecrement(&(This->ref));
+ TRACE("(%p) ref was %d\n", This, ref + 1);
+ if (!ref) {
+ This->device->listener = 0;
+ if (!InterlockedDecrement(&This->device->primary->numIfaces))
+ primarybuffer_destroy(This->device->primary);
+ HeapFree(GetProcessHeap(), 0, This);
+ TRACE("(%p) released\n", This);
+ }
return ref;
}
/* IDirectSound3DListener methods */
-static HRESULT WINAPI IDirectSound3DListenerImpl_GetAllParameter(IDirectSound3DListener *iface,
- DS3DLISTENER *lpDS3DL)
+static HRESULT WINAPI IDirectSound3DListenerImpl_GetAllParameter(
+ LPDIRECTSOUND3DLISTENER iface,
+ LPDS3DLISTENER lpDS3DL)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DListener(iface);
-
+ IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("(%p,%p)\n",This,lpDS3DL);
if (lpDS3DL == NULL) {
return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DListenerImpl_GetDistanceFactor(IDirectSound3DListener *iface,
- D3DVALUE *lpfDistanceFactor)
+static HRESULT WINAPI IDirectSound3DListenerImpl_GetDistanceFactor(
+ LPDIRECTSOUND3DLISTENER iface,
+ LPD3DVALUE lpfDistanceFactor)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DListener(iface);
-
+ IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("returning: Distance Factor = %f\n", This->device->ds3dl.flDistanceFactor);
*lpfDistanceFactor = This->device->ds3dl.flDistanceFactor;
return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DListenerImpl_GetDopplerFactor(IDirectSound3DListener *iface,
- D3DVALUE *lpfDopplerFactor)
+static HRESULT WINAPI IDirectSound3DListenerImpl_GetDopplerFactor(
+ LPDIRECTSOUND3DLISTENER iface,
+ LPD3DVALUE lpfDopplerFactor)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DListener(iface);
-
+ IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("returning: Doppler Factor = %f\n", This->device->ds3dl.flDopplerFactor);
*lpfDopplerFactor = This->device->ds3dl.flDopplerFactor;
return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DListenerImpl_GetOrientation(IDirectSound3DListener *iface,
- D3DVECTOR *lpvOrientFront, D3DVECTOR *lpvOrientTop)
+static HRESULT WINAPI IDirectSound3DListenerImpl_GetOrientation(
+ LPDIRECTSOUND3DLISTENER iface,
+ LPD3DVECTOR lpvOrientFront,
+ LPD3DVECTOR lpvOrientTop)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DListener(iface);
-
+ IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("returning: OrientFront vector = (%f,%f,%f); OrientTop vector = (%f,%f,%f)\n", This->device->ds3dl.vOrientFront.x,
This->device->ds3dl.vOrientFront.y, This->device->ds3dl.vOrientFront.z, This->device->ds3dl.vOrientTop.x, This->device->ds3dl.vOrientTop.y,
This->device->ds3dl.vOrientTop.z);
return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DListenerImpl_GetPosition(IDirectSound3DListener *iface,
- D3DVECTOR *lpvPosition)
+static HRESULT WINAPI IDirectSound3DListenerImpl_GetPosition(
+ LPDIRECTSOUND3DLISTENER iface,
+ LPD3DVECTOR lpvPosition)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DListener(iface);
-
+ IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("returning: Position vector = (%f,%f,%f)\n", This->device->ds3dl.vPosition.x, This->device->ds3dl.vPosition.y, This->device->ds3dl.vPosition.z);
*lpvPosition = This->device->ds3dl.vPosition;
return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DListenerImpl_GetRolloffFactor(IDirectSound3DListener *iface,
- D3DVALUE *lpfRolloffFactor)
+static HRESULT WINAPI IDirectSound3DListenerImpl_GetRolloffFactor(
+ LPDIRECTSOUND3DLISTENER iface,
+ LPD3DVALUE lpfRolloffFactor)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DListener(iface);
-
+ IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("returning: RolloffFactor = %f\n", This->device->ds3dl.flRolloffFactor);
*lpfRolloffFactor = This->device->ds3dl.flRolloffFactor;
return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DListenerImpl_GetVelocity(IDirectSound3DListener *iface,
- D3DVECTOR *lpvVelocity)
+static HRESULT WINAPI IDirectSound3DListenerImpl_GetVelocity(
+ LPDIRECTSOUND3DLISTENER iface,
+ LPD3DVECTOR lpvVelocity)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DListener(iface);
-
+ IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("returning: Velocity vector = (%f,%f,%f)\n", This->device->ds3dl.vVelocity.x, This->device->ds3dl.vVelocity.y, This->device->ds3dl.vVelocity.z);
*lpvVelocity = This->device->ds3dl.vVelocity;
return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DListenerImpl_SetAllParameters(IDirectSound3DListener *iface,
- const DS3DLISTENER *lpcDS3DL, DWORD dwApply)
+static HRESULT WINAPI IDirectSound3DListenerImpl_SetAllParameters(
+ LPDIRECTSOUND3DLISTENER iface,
+ LPCDS3DLISTENER lpcDS3DL,
+ DWORD dwApply)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DListener(iface);
-
+ IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("setting: all parameters; dwApply = %d\n", dwApply);
This->device->ds3dl = *lpcDS3DL;
if (dwApply == DS3D_IMMEDIATE)
return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DListenerImpl_SetDistanceFactor(IDirectSound3DListener *iface,
- D3DVALUE fDistanceFactor, DWORD dwApply)
+static HRESULT WINAPI IDirectSound3DListenerImpl_SetDistanceFactor(
+ LPDIRECTSOUND3DLISTENER iface,
+ D3DVALUE fDistanceFactor,
+ DWORD dwApply)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DListener(iface);
-
+ IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("setting: Distance Factor = %f; dwApply = %d\n", fDistanceFactor, dwApply);
This->device->ds3dl.flDistanceFactor = fDistanceFactor;
if (dwApply == DS3D_IMMEDIATE)
return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DListenerImpl_SetDopplerFactor(IDirectSound3DListener *iface,
- D3DVALUE fDopplerFactor, DWORD dwApply)
+static HRESULT WINAPI IDirectSound3DListenerImpl_SetDopplerFactor(
+ LPDIRECTSOUND3DLISTENER iface,
+ D3DVALUE fDopplerFactor,
+ DWORD dwApply)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DListener(iface);
-
+ IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("setting: Doppler Factor = %f; dwApply = %d\n", fDopplerFactor, dwApply);
This->device->ds3dl.flDopplerFactor = fDopplerFactor;
if (dwApply == DS3D_IMMEDIATE)
return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DListenerImpl_SetOrientation(IDirectSound3DListener *iface,
- D3DVALUE xFront, D3DVALUE yFront, D3DVALUE zFront, D3DVALUE xTop, D3DVALUE yTop,
- D3DVALUE zTop, DWORD dwApply)
+static HRESULT WINAPI IDirectSound3DListenerImpl_SetOrientation(
+ LPDIRECTSOUND3DLISTENER iface,
+ D3DVALUE xFront, D3DVALUE yFront, D3DVALUE zFront,
+ D3DVALUE xTop, D3DVALUE yTop, D3DVALUE zTop,
+ DWORD dwApply)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DListener(iface);
-
+ IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("setting: Front vector = (%f,%f,%f); Top vector = (%f,%f,%f); dwApply = %d\n",
xFront, yFront, zFront, xTop, yTop, zTop, dwApply);
This->device->ds3dl.vOrientFront.x = xFront;
return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DListenerImpl_SetPosition(IDirectSound3DListener *iface,
- D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply)
+static HRESULT WINAPI IDirectSound3DListenerImpl_SetPosition(
+ LPDIRECTSOUND3DLISTENER iface,
+ D3DVALUE x, D3DVALUE y, D3DVALUE z,
+ DWORD dwApply)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DListener(iface);
-
+ IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("setting: Position vector = (%f,%f,%f); dwApply = %d\n", x, y, z, dwApply);
This->device->ds3dl.vPosition.x = x;
This->device->ds3dl.vPosition.y = y;
return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DListenerImpl_SetRolloffFactor(IDirectSound3DListener *iface,
- D3DVALUE fRolloffFactor, DWORD dwApply)
+static HRESULT WINAPI IDirectSound3DListenerImpl_SetRolloffFactor(
+ LPDIRECTSOUND3DLISTENER iface,
+ D3DVALUE fRolloffFactor,
+ DWORD dwApply)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DListener(iface);
-
+ IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("setting: Rolloff Factor = %f; dwApply = %d\n", fRolloffFactor, dwApply);
This->device->ds3dl.flRolloffFactor = fRolloffFactor;
if (dwApply == DS3D_IMMEDIATE)
return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DListenerImpl_SetVelocity(IDirectSound3DListener *iface,
- D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply)
+static HRESULT WINAPI IDirectSound3DListenerImpl_SetVelocity(
+ LPDIRECTSOUND3DLISTENER iface,
+ D3DVALUE x, D3DVALUE y, D3DVALUE z,
+ DWORD dwApply)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DListener(iface);
-
+ IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("setting: Velocity vector = (%f,%f,%f); dwApply = %d\n", x, y, z, dwApply);
This->device->ds3dl.vVelocity.x = x;
This->device->ds3dl.vVelocity.y = y;
return DS_OK;
}
-static HRESULT WINAPI IDirectSound3DListenerImpl_CommitDeferredSettings(IDirectSound3DListener *iface)
+static HRESULT WINAPI IDirectSound3DListenerImpl_CommitDeferredSettings(
+ LPDIRECTSOUND3DLISTENER iface)
{
- IDirectSoundBufferImpl *This = impl_from_IDirectSound3DListener(iface);
-
+ IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("\n");
DSOUND_ChangeListener(This);
return DS_OK;
}
-const IDirectSound3DListenerVtbl ds3dlvt =
+static const IDirectSound3DListenerVtbl ds3dlvt =
{
/* IUnknown methods */
IDirectSound3DListenerImpl_QueryInterface,
IDirectSound3DListenerImpl_SetVelocity,
IDirectSound3DListenerImpl_CommitDeferredSettings,
};
+
+HRESULT IDirectSound3DListenerImpl_Create(
+ DirectSoundDevice * device,
+ IDirectSound3DListenerImpl ** ppdsl)
+{
+ IDirectSound3DListenerImpl *pdsl;
+ TRACE("(%p,%p)\n",device,ppdsl);
+
+ pdsl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*pdsl));
+
+ if (pdsl == NULL) {
+ WARN("out of memory\n");
+ *ppdsl = 0;
+ return DSERR_OUTOFMEMORY;
+ }
+
+ pdsl->ref = 0;
+ pdsl->lpVtbl = &ds3dlvt;
+
+ pdsl->device = device;
+
+ pdsl->device->ds3dl.dwSize = sizeof(DS3DLISTENER);
+ pdsl->device->ds3dl.vPosition.x = 0.0;
+ pdsl->device->ds3dl.vPosition.y = 0.0;
+ pdsl->device->ds3dl.vPosition.z = 0.0;
+ pdsl->device->ds3dl.vVelocity.x = 0.0;
+ pdsl->device->ds3dl.vVelocity.y = 0.0;
+ pdsl->device->ds3dl.vVelocity.z = 0.0;
+ pdsl->device->ds3dl.vOrientFront.x = 0.0;
+ pdsl->device->ds3dl.vOrientFront.y = 0.0;
+ pdsl->device->ds3dl.vOrientFront.z = 1.0;
+ pdsl->device->ds3dl.vOrientTop.x = 0.0;
+ pdsl->device->ds3dl.vOrientTop.y = 1.0;
+ pdsl->device->ds3dl.vOrientTop.z = 0.0;
+ pdsl->device->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
+ pdsl->device->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
+ pdsl->device->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
+
+ pdsl->device->ds3dl_need_recalc = TRUE;
+
+ *ppdsl = pdsl;
+ return S_OK;
+}
--- /dev/null
+/*
+ * DirectSound driver
+ * (DirectX 5 version)
+ *
+ * Copyright (C) 2000 Ove Kaaven
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __WINE_DSDRIVER_H
+#define __WINE_DSDRIVER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*****************************************************************************
+ * Predeclare the interfaces
+ */
+DEFINE_GUID(IID_IDsDriver, 0x8C4233C0l, 0xB4CC, 0x11CE, 0x92, 0x94, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00);
+typedef struct IDsDriver *PIDSDRIVER;
+
+DEFINE_GUID(IID_IDsDriverBuffer, 0x8C4233C1l, 0xB4CC, 0x11CE, 0x92, 0x94, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00);
+typedef struct IDsDriverBuffer *PIDSDRIVERBUFFER;
+
+DEFINE_GUID(IID_IDsDriverPropertySet, 0x0F6F2E8E0, 0xD842, 0x11D0, 0x8F, 0x75, 0x00, 0xC0, 0x4F, 0xC2, 0x8A, 0xCA);
+typedef struct IDsDriverPropertySet *PIDSDRIVERPROPERTYSET;
+
+DEFINE_GUID(IID_IDsDriverNotify, 0x00363EF44, 0x3B57, 0x11D3, 0xAC, 0x79, 0x00, 0x10, 0x5A, 0x01, 0x7f, 0xe1);
+typedef struct IDsDriverNotify *PIDSDRIVERNOTIFY;
+
+DEFINE_GUID(IID_IDsCaptureDriver, 0x03DD10C47, 0x74FB, 0x11D3, 0x90, 0x49, 0xCB, 0xB4, 0xB3, 0x2E, 0xAA, 0x08);
+typedef struct IDsCaptureDriver *PIDSCDRIVER;
+
+DEFINE_GUID(IID_IDsCaptureDriverBuffer, 0x03DD10C48, 0x74FB, 0x11D3, 0x90, 0x49, 0xCB, 0xB4, 0xB3, 0x2E, 0xAA, 0x08);
+typedef struct IDsCaptureDriverBuffer *PIDSCDRIVERBUFFER;
+
+#define DSDDESC_DOMMSYSTEMOPEN 0x00000001
+#define DSDDESC_DOMMSYSTEMSETFORMAT 0x00000002
+#define DSDDESC_USESYSTEMMEMORY 0x00000004
+#define DSDDESC_DONTNEEDPRIMARYLOCK 0x00000008
+#define DSDDESC_DONTNEEDSECONDARYLOCK 0x00000010
+#define DSDDESC_DONTNEEDWRITELEAD 0x00000020
+
+#define DSDHEAP_NOHEAP 0
+#define DSDHEAP_CREATEHEAP 1
+#define DSDHEAP_USEDIRECTDRAWHEAP 2
+#define DSDHEAP_PRIVATEHEAP 3
+
+typedef struct _DSDRIVERDESC
+{
+ DWORD dwFlags;
+ CHAR szDesc[256];
+ CHAR szDrvname[256];
+ DWORD dnDevNode;
+ WORD wVxdId;
+ WORD wReserved;
+ ULONG ulDeviceNum;
+ DWORD dwHeapType;
+ LPVOID pvDirectDrawHeap;
+ DWORD dwMemStartAddress;
+ DWORD dwMemEndAddress;
+ DWORD dwMemAllocExtra;
+ LPVOID pvReserved1;
+ LPVOID pvReserved2;
+} DSDRIVERDESC,*PDSDRIVERDESC;
+
+typedef struct _DSDRIVERCAPS
+{
+ DWORD dwFlags;
+ DWORD dwMinSecondarySampleRate;
+ DWORD dwMaxSecondarySampleRate;
+ DWORD dwPrimaryBuffers;
+ DWORD dwMaxHwMixingAllBuffers;
+ DWORD dwMaxHwMixingStaticBuffers;
+ DWORD dwMaxHwMixingStreamingBuffers;
+ DWORD dwFreeHwMixingAllBuffers;
+ DWORD dwFreeHwMixingStaticBuffers;
+ DWORD dwFreeHwMixingStreamingBuffers;
+ DWORD dwMaxHw3DAllBuffers;
+ DWORD dwMaxHw3DStaticBuffers;
+ DWORD dwMaxHw3DStreamingBuffers;
+ DWORD dwFreeHw3DAllBuffers;
+ DWORD dwFreeHw3DStaticBuffers;
+ DWORD dwFreeHw3DStreamingBuffers;
+ DWORD dwTotalHwMemBytes;
+ DWORD dwFreeHwMemBytes;
+ DWORD dwMaxContigFreeHwMemBytes;
+} DSDRIVERCAPS,*PDSDRIVERCAPS;
+
+typedef struct _DSVOLUMEPAN
+{
+ DWORD dwTotalLeftAmpFactor;
+ DWORD dwTotalRightAmpFactor;
+ LONG lVolume;
+ DWORD dwVolAmpFactor;
+ LONG lPan;
+ DWORD dwPanLeftAmpFactor;
+ DWORD dwPanRightAmpFactor;
+} DSVOLUMEPAN,*PDSVOLUMEPAN;
+
+typedef union _DSPROPERTY
+{
+ struct {
+ GUID Set;
+ ULONG Id;
+ ULONG Flags;
+ ULONG InstanceId;
+ } DUMMYSTRUCTNAME;
+ ULONGLONG Alignment;
+} DSPROPERTY,*PDSPROPERTY;
+
+typedef struct _DSCDRIVERCAPS
+{
+ DWORD dwSize;
+ DWORD dwFlags;
+ DWORD dwFormats;
+ DWORD dwChannels;
+} DSCDRIVERCAPS,*PDSCDRIVERCAPS;
+
+/*****************************************************************************
+ * IDsDriver interface
+ */
+#define INTERFACE IDsDriver
+DECLARE_INTERFACE_(IDsDriver,IUnknown)
+{
+ /*** IUnknown methods ***/
+ STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+ STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+ STDMETHOD_(ULONG,Release)(THIS) PURE;
+ /*** IDsDriver methods ***/
+ STDMETHOD(GetDriverDesc)(THIS_ PDSDRIVERDESC pDsDriverDesc) PURE;
+ STDMETHOD(Open)(THIS) PURE;
+ STDMETHOD(Close)(THIS) PURE;
+ STDMETHOD(GetCaps)(THIS_ PDSDRIVERCAPS pDsDrvCaps) PURE;
+ STDMETHOD(CreateSoundBuffer)(THIS_ LPWAVEFORMATEX pwfx,DWORD dwFlags,DWORD dwCardAddress,LPDWORD pdwcbBufferSize,LPBYTE *ppbBuffer,LPVOID *ppvObj) PURE;
+ STDMETHOD(DuplicateSoundBuffer)(THIS_ PIDSDRIVERBUFFER pIDsDriverBuffer,LPVOID *ppvObj) PURE;
+};
+#undef INTERFACE
+
+#if !defined (__cplusplus) || defined(CINTERFACE)
+ /*** IUnknown methods ***/
+#define IDsDriver_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDsDriver_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDsDriver_Release(p) (p)->lpVtbl->Release(p)
+ /*** IDsDriver methods ***/
+#define IDsDriver_GetDriverDesc(p,a) (p)->lpVtbl->GetDriverDesc(p,a)
+#define IDsDriver_Open(p) (p)->lpVtbl->Open(p)
+#define IDsDriver_Close(p) (p)->lpVtbl->Close(p)
+#define IDsDriver_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a)
+#define IDsDriver_CreateSoundBuffer(p,a,b,c,d,e,f) (p)->lpVtbl->CreateSoundBuffer(p,a,b,c,d,e,f)
+#define IDsDriver_DuplicateSoundBuffer(p,a,b) (p)->lpVtbl->DuplicateSoundBuffer(p,a,b)
+#endif
+
+/*****************************************************************************
+ * IDsDriverBuffer interface
+ */
+#define INTERFACE IDsDriverBuffer
+DECLARE_INTERFACE_(IDsDriverBuffer,IUnknown)
+{
+ /*** IUnknown methods ***/
+ STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+ STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+ STDMETHOD_(ULONG,Release)(THIS) PURE;
+ /*** IDsDriverBuffer methods ***/
+ STDMETHOD(Lock)(THIS_ LPVOID *ppvAudio1,LPDWORD pdwLen1,LPVOID *pdwAudio2,LPDWORD pdwLen2,DWORD dwWritePosition,DWORD dwWriteLen,DWORD dwFlags) PURE;
+ STDMETHOD(Unlock)(THIS_ LPVOID pvAudio1,DWORD dwLen1,LPVOID pvAudio2,DWORD dwLen2) PURE;
+ STDMETHOD(SetFormat)(THIS_ LPWAVEFORMATEX pwfxToSet) PURE;
+ STDMETHOD(SetFrequency)(THIS_ DWORD dwFrequency) PURE;
+ STDMETHOD(SetVolumePan)(THIS_ PDSVOLUMEPAN pDsVolumePan) PURE;
+ STDMETHOD(SetPosition)(THIS_ DWORD dwNewPosition) PURE;
+ STDMETHOD(GetPosition)(THIS_ LPDWORD lpdwCurrentPlayCursor,LPDWORD lpdwCurrentWriteCursor) PURE;
+ STDMETHOD(Play)(THIS_ DWORD dwReserved1,DWORD dwReserved2,DWORD dwFlags) PURE;
+ STDMETHOD(Stop)(THIS) PURE;
+};
+#undef INTERFACE
+
+#if !defined (__cplusplus) || defined(CINTERFACE)
+ /*** IUnknown methods ***/
+#define IDsDriverBuffer_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDsDriverBuffer_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDsDriverBuffer_Release(p) (p)->lpVtbl->Release(p)
+ /*** IDsDriverBuffer methods ***/
+#define IDsDriverBuffer_Lock(p,a,b,c,d,e,f,g) (p)->lpVtbl->Lock(p,a,b,c,d,e,f,g)
+#define IDsDriverBuffer_Unlock(p,a,b,c,d) (p)->lpVtbl->Unlock(p,a,b,c,d)
+#define IDsDriverBuffer_SetFormat(p,a) (p)->lpVtbl->SetFormat(p,a)
+#define IDsDriverBuffer_SetFrequency(p,a) (p)->lpVtbl->SetFrequency(p,a)
+#define IDsDriverBuffer_SetVolumePan(p,a) (p)->lpVtbl->SetVolumePan(p,a)
+#define IDsDriverBuffer_SetPosition(p,a) (p)->lpVtbl->SetPosition(p,a)
+#define IDsDriverBuffer_GetPosition(p,a,b) (p)->lpVtbl->GetPosition(p,a,b)
+#define IDsDriverBuffer_Play(p,a,b,c) (p)->lpVtbl->Play(p,a,b,c)
+#define IDsDriverBuffer_Stop(p) (p)->lpVtbl->Stop(p)
+#endif
+
+/*****************************************************************************
+ * IDsDriverPropertySet interface
+ */
+#define INTERFACE IDsDriverPropertySet
+DECLARE_INTERFACE_(IDsDriverPropertySet,IUnknown)
+{
+ /*** IUnknown methods ***/
+ STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+ STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+ STDMETHOD_(ULONG,Release)(THIS) PURE;
+ /*** IDsDriverPropertySet methods ***/
+ STDMETHOD(Get)(THIS_ PDSPROPERTY pDsProperty,LPVOID pPropertyParams,ULONG cbPropertyParams,LPVOID pPropertyData,ULONG cbPropertyData,PULONG pcbReturnedData) PURE;
+ STDMETHOD(Set)(THIS_ PDSPROPERTY pDsProperty,LPVOID pPropertyParams,ULONG cbPropertyParams,LPVOID pPropertyData,ULONG cbPropertyData) PURE;
+ STDMETHOD(QuerySupport)(THIS_ REFGUID PropertySetId,ULONG PropertyId,PULONG pSupport) PURE;
+};
+#undef INTERFACE
+
+#if !defined (__cplusplus) || defined(CINTERFACE)
+ /*** IUnknown methods ***/
+#define IDsDriverPropertySet_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDsDriverPropertySet_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDsDriverPropertySet_Release(p) (p)->lpVtbl->Release(p)
+ /*** IDsDriverPropertySet methods ***/
+#define IDsDriverPropertySet_Get(p,a,b,c,d,e,f) (p)->lpVtbl->Get(p,a,b,c,d,e,f)
+#define IDsDriverPropertySet_Set(p,a,b,c,d,e) (p)->lpVtbl->Set(p,a,b,c,d,e)
+#define IDsDriverPropertySet_QuerySupport(p,a,b,c) (p)->lpVtbl->QuerySupport(p,a,b,c)
+#endif
+
+/* Defined property sets */
+DEFINE_GUID(DSPROPSETID_DirectSound3DListener, 0x6D047B40, 0x7AF9, 0x11D0, 0x92, 0x94, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0);
+typedef enum
+{
+ DSPROPERTY_DIRECTSOUND3DLISTENER_ALL,
+ DSPROPERTY_DIRECTSOUND3DLISTENER_POSITION,
+ DSPROPERTY_DIRECTSOUND3DLISTENER_VELOCITY,
+ DSPROPERTY_DIRECTSOUND3DLISTENER_ORIENTATION,
+ DSPROPERTY_DIRECTSOUND3DLISTENER_DISTANCEFACTOR,
+ DSPROPERTY_DIRECTSOUND3DLISTENER_ROLLOFFFACTOR,
+ DSPROPERTY_DIRECTSOUND3DLISTENER_DOPPLERFACTOR,
+ DSPROPERTY_DIRECTSOUND3DLISTENER_BATCH,
+ DSPROPERTY_DIRECTSOUND3DLISTENER_ALLOCATION
+} DSPROPERTY_DIRECTSOUND3DLISTENER;
+
+DEFINE_GUID(DSPROPSETID_DirectSound3DBuffer, 0x6D047B41, 0x7AF9, 0x11D0, 0x92, 0x94, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0);
+typedef enum
+{
+ DSPROPERTY_DIRECTSOUND3DBUFFER_ALL,
+ DSPROPERTY_DIRECTSOUND3DBUFFER_POSITION,
+ DSPROPERTY_DIRECTSOUND3DBUFFER_VELOCITY,
+ DSPROPERTY_DIRECTSOUND3DBUFFER_CONEANGLES,
+ DSPROPERTY_DIRECTSOUND3DBUFFER_CONEORIENTATION,
+ DSPROPERTY_DIRECTSOUND3DBUFFER_CONEOUTSIDEVOLUME,
+ DSPROPERTY_DIRECTSOUND3DBUFFER_MINDISTANCE,
+ DSPROPERTY_DIRECTSOUND3DBUFFER_MAXDISTANCE,
+ DSPROPERTY_DIRECTSOUND3DBUFFER_MODE
+} DSPROPERTY_DIRECTSOUND3DBUFFER;
+
+DEFINE_GUID(DSPROPSETID_DirectSoundSpeakerConfig, 0x6D047B42, 0x7AF9, 0x11D0, 0x92, 0x94, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0);
+typedef enum
+{
+ DSPROPERTY_DIRECTSOUNDSPEAKERCONFIG_SPEAKERCONFIG
+} DSPROPERTY_DIRECTSOUNDSPEAKERCONFIG;
+
+/*****************************************************************************
+ * IDsDriverNotify interface
+ */
+#define INTERFACE IDsDriverNotify
+DECLARE_INTERFACE_(IDsDriverNotify,IUnknown)
+{
+ /*** IUnknown methods ***/
+ STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+ STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+ STDMETHOD_(ULONG,Release)(THIS) PURE;
+ /*** IDsDriverNotify methods ***/
+ STDMETHOD(SetNotificationPositions)(THIS_ DWORD dwPositionNotifies,LPCDSBPOSITIONNOTIFY pcPositionNotifies) PURE;
+};
+#undef INTERFACE
+
+#if !defined (__cplusplus) || defined(CINTERFACE)
+ /*** IUnknown methods ***/
+#define IDsDriverNotify_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDsDriverNotify_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDsDriverNotify_Release(p) (p)->lpVtbl->Release(p)
+ /*** IDsDriverNotify methods ***/
+#define IDsDriverNotify_SetNotificationPositions(p,a,b) (p)->lpVtbl->SetNotificationPositions(p,a,b)
+#endif
+
+/*****************************************************************************
+ * IDsCaptureDriver interface
+ */
+#define INTERFACE IDsCaptureDriver
+DECLARE_INTERFACE_(IDsCaptureDriver,IUnknown)
+{
+ /*** IUnknown methods ***/
+ STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+ STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+ STDMETHOD_(ULONG,Release)(THIS) PURE;
+ /*** IDsCaptureDriver methods ***/
+ STDMETHOD(GetDriverDesc)(THIS_ PDSDRIVERDESC pDsDriverDesc) PURE;
+ STDMETHOD(Open)(THIS) PURE;
+ STDMETHOD(Close)(THIS) PURE;
+ STDMETHOD(GetCaps)(THIS_ PDSCDRIVERCAPS pDsDrvCaps) PURE;
+ STDMETHOD(CreateCaptureBuffer)(THIS_ LPWAVEFORMATEX pwfx,DWORD dwFlags,DWORD dwCardAddress,LPDWORD pdwcbBufferSize,LPBYTE *ppbBuffer,LPVOID *ppvObj) PURE;
+};
+#undef INTERFACE
+
+#if !defined (__cplusplus) || defined(CINTERFACE)
+ /*** IUnknown methods ***/
+#define IDsCaptureDriver_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDsCaptureDriver_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDsCaptureDriver_Release(p) (p)->lpVtbl->Release(p)
+ /*** IDsCaptureDriver methods ***/
+#define IDsCaptureDriver_GetDriverDesc(p,a) (p)->lpVtbl->GetDriverDesc(p,a)
+#define IDsCaptureDriver_Open(p) (p)->lpVtbl->Open(p)
+#define IDsCaptureDriver_Close(p) (p)->lpVtbl->Close(p)
+#define IDsCaptureDriver_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a)
+#define IDsCaptureDriver_CreateCaptureBuffer(p,a,b,c,d,e,f) (p)->lpVtbl->CreateCaptureBuffer(p,a,b,c,d,e,f)
+#endif
+
+/*****************************************************************************
+ * IDsCaptureDriverBuffer interface
+ */
+#define INTERFACE IDsCaptureDriverBuffer
+DECLARE_INTERFACE_(IDsCaptureDriverBuffer,IUnknown)
+{
+ /*** IUnknown methods ***/
+ STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
+ STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+ STDMETHOD_(ULONG,Release)(THIS) PURE;
+ /*** IDsCaptureDriverBuffer methods ***/
+ STDMETHOD(Lock)(THIS_ LPVOID *ppvAudio1,LPDWORD pdwLen1,LPVOID *ppvAudio2,LPDWORD pdwLen2,DWORD dwWritePosition,DWORD dwWriteLen,DWORD dwFlags) PURE;
+ STDMETHOD(Unlock)(THIS_ LPVOID pvAudio1,DWORD dwLen1,LPVOID pvAudio2,DWORD dwLen2) PURE;
+ STDMETHOD(SetFormat)(THIS_ LPWAVEFORMATEX pwfxToSet) PURE;
+ STDMETHOD(GetPosition)(THIS_ LPDWORD lpdwCurrentPlayCursor,LPDWORD lpdwCurrentWriteCursor) PURE;
+ STDMETHOD(GetStatus)(THIS_ LPDWORD lpdwStatus) PURE;
+ STDMETHOD(Start)(THIS_ DWORD dwFlags) PURE;
+ STDMETHOD(Stop)(THIS) PURE;
+};
+#undef INTERFACE
+
+#if !defined (__cplusplus) || defined(CINTERFACE)
+ /*** IUnknown methods ***/
+#define IDsCaptureDriverBuffer_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDsCaptureDriverBuffer_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDsCaptureDriverBuffer_Release(p) (p)->lpVtbl->Release(p)
+ /*** IDsCaptureDriverBuffer methods ***/
+#define IDsCaptureDriverBuffer_Lock(p,a,b,c,d,e,f,g) (p)->lpVtbl->Lock(p,a,b,c,d,e,f,g)
+#define IDsCaptureDriverBuffer_Unlock(p,a,b,c,d) (p)->lpVtbl->Unlock(p,a,b,c,d)
+#define IDsCaptureDriverBuffer_SetFormat(p,a) (p)->lpVtbl->SetFormat(p,a)
+#define IDsCaptureDriverBuffer_GetPosition(p,a,b) (p)->lpVtbl->GetPosition(p,a,b)
+#define IDsCaptureDriverBuffer_GetStatus(p,a) (p)->lpVtbl->GetStatus(p,a)
+#define IDsCaptureDriverBuffer_Start(p,a) (p)->lpVtbl->Start(p,a)
+#define IDsCaptureDriverBuffer_Stop(p) (p)->lpVtbl->Stop(p)
+#endif
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* __WINE_DSDRIVER_H */
reactos/dll/directx/wine/dmusic # Synced to Wine-1.7.27
reactos/dll/directx/wine/dplay # Synced to Wine-1.7.27
reactos/dll/directx/wine/dplayx # Synced to Wine-1.7.27
-reactos/dll/directx/wine/dsound # Synced to Wine-1.5.26
+reactos/dll/directx/wine/dsound # Synced to Wine-1.3.29
reactos/dll/directx/wine/dxdiagn # Synced to Wine-1.7.27
reactos/dll/directx/wine/dxgi # Synced to Wine-1.7.27
reactos/dll/directx/wine/msdmo # Synced to Wine-1.7.27