[DSOUND]
authorAmine Khaldi <amine.khaldi@reactos.org>
Sun, 28 Sep 2014 20:12:26 +0000 (20:12 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sun, 28 Sep 2014 20:12:26 +0000 (20:12 +0000)
* 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

16 files changed:
reactos/dll/directx/wine/dsound/CMakeLists.txt
reactos/dll/directx/wine/dsound/buffer.c
reactos/dll/directx/wine/dsound/capture.c
reactos/dll/directx/wine/dsound/dsound.c
reactos/dll/directx/wine/dsound/dsound_convert.c
reactos/dll/directx/wine/dsound/dsound_main.c
reactos/dll/directx/wine/dsound/dsound_private.h
reactos/dll/directx/wine/dsound/duplex.c
reactos/dll/directx/wine/dsound/fir.h [deleted file]
reactos/dll/directx/wine/dsound/guid.c
reactos/dll/directx/wine/dsound/mixer.c
reactos/dll/directx/wine/dsound/primary.c
reactos/dll/directx/wine/dsound/propset.c
reactos/dll/directx/wine/dsound/sound3d.c
reactos/include/dxsdk/dsdriver.h [new file with mode: 0644]
reactos/media/doc/README.WINE

index f536368..e660e4e 100644 (file)
@@ -30,5 +30,5 @@ if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
     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)
index a574449..89b516c 100644 (file)
  *             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) {
@@ -85,24 +92,30 @@ static HRESULT WINAPI IDirectSoundNotifyImpl_SetNotificationPositions(IDirectSou
                    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;
 }
@@ -115,6 +128,40 @@ static const IDirectSoundNotifyVtbl dsnvt =
     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
  */
@@ -126,7 +173,7 @@ static inline IDirectSoundBufferImpl *impl_from_IDirectSoundBuffer8(IDirectSound
 
 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,
@@ -179,6 +226,14 @@ static HRESULT WINAPI IDirectSoundBufferImpl_SetVolume(IDirectSoundBuffer8 *ifac
                        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);
        /* **** */
 
@@ -237,9 +292,10 @@ static HRESULT WINAPI IDirectSoundBufferImpl_SetFrequency(IDirectSoundBuffer8 *i
        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);
@@ -260,11 +316,18 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Play(IDirectSoundBuffer8 *iface, DW
        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);
        /* **** */
@@ -289,6 +352,13 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Stop(IDirectSoundBuffer8 *iface)
                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);
        /* **** */
@@ -312,22 +382,16 @@ static ULONG WINAPI IDirectSoundBufferImpl_AddRef(IDirectSoundBuffer8 *iface)
 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;
 }
 
@@ -335,31 +399,36 @@ static HRESULT WINAPI IDirectSoundBufferImpl_GetCurrentPosition(IDirectSoundBuff
         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",
@@ -469,31 +538,44 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Lock(IDirectSoundBuffer8 *iface, DW
        /* **** */
        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);
@@ -507,12 +589,15 @@ static HRESULT WINAPI IDirectSoundBufferImpl_SetCurrentPosition(IDirectSoundBuff
 {
         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;
@@ -521,6 +606,16 @@ static HRESULT WINAPI IDirectSoundBufferImpl_SetCurrentPosition(IDirectSoundBuff
        /* 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);
        /* **** */
 
@@ -552,6 +647,12 @@ static HRESULT WINAPI IDirectSoundBufferImpl_SetPan(IDirectSoundBuffer8 *iface,
        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);
@@ -589,14 +690,22 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Unlock(IDirectSoundBuffer8 *iface,
 
        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 )
@@ -606,7 +715,11 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Unlock(IDirectSoundBuffer8 *iface,
                         {
                            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);
@@ -707,7 +820,8 @@ static HRESULT WINAPI IDirectSoundBufferImpl_GetCaps(IDirectSoundBuffer8 *iface,
        }
 
        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;
 
@@ -741,19 +855,27 @@ static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface(IDirectSoundBuffer8
        }
 
        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 ) ) {
@@ -762,9 +884,15 @@ static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface(IDirectSoundBuffer8
        }
 
        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 ) );
@@ -809,6 +937,7 @@ HRESULT IDirectSoundBufferImpl_Create(
        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) {
@@ -827,16 +956,11 @@ HRESULT IDirectSoundBufferImpl_Create(
 
        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);
@@ -856,8 +980,10 @@ HRESULT IDirectSoundBufferImpl_Create(
                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;
@@ -865,7 +991,24 @@ HRESULT IDirectSoundBufferImpl_Create(
        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)));
@@ -877,15 +1020,35 @@ HRESULT IDirectSoundBufferImpl_Create(
                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;
@@ -895,10 +1058,10 @@ HRESULT IDirectSoundBufferImpl_Create(
 
        /* 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;
 
@@ -943,28 +1106,27 @@ HRESULT IDirectSoundBufferImpl_Create(
                }
        }
 
-        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);
@@ -972,6 +1134,38 @@ void secondarybuffer_destroy(IDirectSoundBufferImpl *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,
@@ -987,34 +1181,44 @@ HRESULT IDirectSoundBufferImpl_Duplicate(
         *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);
 
@@ -1022,6 +1226,7 @@ HRESULT IDirectSoundBufferImpl_Duplicate(
     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);
@@ -1029,104 +1234,191 @@ HRESULT IDirectSoundBufferImpl_Duplicate(
         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;
+}
index 756bbc0..b8df4f5 100644 (file)
 
 #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) {
@@ -152,26 +102,32 @@ static HRESULT WINAPI IDirectSoundNotifyImpl_SetNotificationPositions(IDirectSou
            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;
@@ -179,12 +135,36 @@ static HRESULT WINAPI IDirectSoundNotifyImpl_SetNotificationPositions(IDirectSou
 
 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",
@@ -195,18 +175,16 @@ static const char * const captureStateString[] = {
 
 
 /*******************************************************************************
- * 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) {
@@ -216,53 +194,100 @@ static HRESULT WINAPI IDirectSoundCaptureBufferImpl_QueryInterface(IDirectSoundC
 
     *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) {
@@ -289,11 +314,14 @@ static HRESULT WINAPI IDirectSoundCaptureBufferImpl_GetCaps(IDirectSoundCaptureB
     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) {
@@ -301,35 +329,42 @@ static HRESULT WINAPI IDirectSoundCaptureBufferImpl_GetCurrentPosition(IDirectSo
         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");
@@ -356,11 +391,12 @@ static HRESULT WINAPI IDirectSoundCaptureBufferImpl_GetFormat(IDirectSoundCaptur
     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) {
@@ -393,23 +429,32 @@ static HRESULT WINAPI IDirectSoundCaptureBufferImpl_GetStatus(IDirectSoundCaptur
     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() );
@@ -431,7 +476,14 @@ static HRESULT WINAPI IDirectSoundCaptureBufferImpl_Lock(IDirectSoundCaptureBuff
 
     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;
@@ -457,12 +509,13 @@ static HRESULT WINAPI IDirectSoundCaptureBufferImpl_Lock(IDirectSoundCaptureBuff
     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) {
@@ -470,45 +523,101 @@ static HRESULT WINAPI IDirectSoundCaptureBufferImpl_Start(IDirectSoundCaptureBuf
         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");
@@ -524,26 +633,35 @@ static HRESULT WINAPI IDirectSoundCaptureBufferImpl_Stop(IDirectSoundCaptureBuff
        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 );
 
@@ -552,7 +670,12 @@ static HRESULT WINAPI IDirectSoundCaptureBufferImpl_Unlock(IDirectSoundCaptureBu
         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;
     }
@@ -561,25 +684,29 @@ static HRESULT WINAPI IDirectSoundCaptureBufferImpl_Unlock(IDirectSoundCaptureBu
     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 );
 
@@ -634,13 +761,55 @@ static void capture_CheckNotify(IDirectSoundCaptureBufferImpl *This, DWORD from,
     }
 }
 
+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) {
@@ -648,15 +817,15 @@ static HRESULT IDirectSoundCaptureBufferImpl_Create(
        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;
     }
 
@@ -665,6 +834,7 @@ static HRESULT IDirectSoundCaptureBufferImpl_Create(
         (lpcDSCBufferDesc->dwBufferBytes == 0) ||
         (lpcDSCBufferDesc->lpwfxFormat == NULL) ) { /* FIXME: DSERR_BADFORMAT ? */
        WARN("invalid lpcDSCBufferDesc\n");
+       *ppobj = NULL;
        return DSERR_INVALIDPARAM;
     }
 
@@ -677,26 +847,30 @@ static HRESULT IDirectSoundCaptureBufferImpl_Create(
         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);
@@ -706,72 +880,80 @@ static HRESULT IDirectSoundCaptureBufferImpl_Create(
             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;
 }
@@ -780,6 +962,8 @@ static HRESULT IDirectSoundCaptureBufferImpl_Create(
 /*******************************************************************************
  * DirectSoundCaptureDevice
  */
+DirectSoundCaptureDevice * DSOUND_capture[MAXWAVEDRIVERS];
+
 static HRESULT DirectSoundCaptureDevice_Create(
     DirectSoundCaptureDevice ** ppDevice)
 {
@@ -813,351 +997,224 @@ static ULONG DirectSoundCaptureDevice_Release(
 
     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;
@@ -1188,11 +1245,11 @@ static HRESULT WINAPI IDirectSoundCaptureImpl_CreateCaptureBuffer(IDirectSoundCa
     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) {
@@ -1220,11 +1277,11 @@ static HRESULT WINAPI IDirectSoundCaptureImpl_GetCaps(IDirectSoundCapture *iface
     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) {
@@ -1247,50 +1304,85 @@ static const IDirectSoundCaptureVtbl dscvt =
     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;
 }
 
 /***************************************************************************
@@ -1315,12 +1407,13 @@ HRESULT DSOUND_CaptureCreate8(REFIID riid, void **ppv)
  *
  *    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) {
@@ -1330,10 +1423,11 @@ HRESULT WINAPI DirectSoundCaptureCreate(LPCGUID lpcGUID, IDirectSoundCapture **p
 
     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) {
@@ -1389,7 +1483,7 @@ HRESULT WINAPI DirectSoundCaptureCreate8(
         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) {
index 19577c9..9656b2c 100644 (file)
 
 #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) {
@@ -98,365 +156,842 @@ static void _dump_DSBCAPS(DWORD xmask) {
             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;
 }
 
 /*******************************************************************************
@@ -495,7 +1030,7 @@ HRESULT WINAPI DirectSoundCreate(
         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) {
@@ -512,6 +1047,41 @@ HRESULT WINAPI DirectSoundCreate(
     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)
  *
@@ -548,7 +1118,7 @@ HRESULT WINAPI DirectSoundCreate8(
         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) {
@@ -583,7 +1153,7 @@ static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice)
     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);
@@ -607,24 +1177,24 @@ static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice)
     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");
@@ -650,41 +1220,46 @@ ULONG DirectSoundDevice_Release(DirectSoundDevice * device)
     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);
@@ -694,58 +1269,67 @@ ULONG DirectSoundDevice_Release(DirectSoundDevice * device)
     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) {
@@ -757,108 +1341,140 @@ HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcG
     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;
 }
@@ -904,12 +1520,6 @@ HRESULT DirectSoundDevice_CreateSoundBuffer(
         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 "
@@ -926,7 +1536,10 @@ HRESULT DirectSoundDevice_CreateSoundBuffer(
             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");
         }
@@ -941,6 +1554,11 @@ HRESULT DirectSoundDevice_CreateSoundBuffer(
         }
         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 */
@@ -1041,6 +1659,101 @@ HRESULT DirectSoundDevice_DuplicateSoundBuffer(
     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.
@@ -1080,29 +1793,35 @@ HRESULT DirectSoundDevice_AddBuffer(
  * 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;
 }
index 76c99c1..1bb9b58 100644 (file)
 #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
 };
index c25418d..92103f0 100644 (file)
 #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;
 
 /*
@@ -114,18 +128,62 @@ void setup_dsound_options(void)
 
     /* 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)
@@ -141,64 +199,6 @@ 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]
  *
@@ -221,56 +221,34 @@ static HRESULT get_mmdevice_guid(IMMDevice *device, IPropertyStore *ps,
  */
 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;
 }
@@ -322,187 +300,6 @@ HRESULT WINAPI DirectSoundEnumerateA(
     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]
  *
@@ -520,20 +317,61 @@ HRESULT WINAPI DirectSoundEnumerateW(
        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;
 }
 
 /***************************************************************************
@@ -584,20 +422,64 @@ DirectSoundCaptureEnumerateW(
     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;
 }
 
 /*******************************************************************************
@@ -618,7 +500,7 @@ static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
 }
 
 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);
@@ -628,7 +510,7 @@ DSCF_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppobj)
         IsEqualIID(riid, &IID_IClassFactory))
     {
         *ppobj = iface;
-        IClassFactory_AddRef(iface);
+        IUnknown_AddRef(iface);
         return S_OK;
     }
     *ppobj = NULL;
@@ -682,12 +564,12 @@ static const IClassFactoryVtbl DSCF_Vtbl = {
 };
 
 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 }
 };
 
@@ -765,11 +647,18 @@ HRESULT WINAPI DllCanUnloadNow(void)
  */
 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 */
@@ -777,8 +666,6 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
         break;
     case DLL_PROCESS_DETACH:
         TRACE("DLL_PROCESS_DETACH\n");
-        DeleteCriticalSection(&DSOUND_renderers_lock);
-        DeleteCriticalSection(&DSOUND_capturers_lock);
         break;
     default:
         TRACE("UNKNOWN REASON\n");
index 0b5fde9..da80e58 100644 (file)
 #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>
@@ -59,34 +58,48 @@ WINE_DEFAULT_DEBUG_CHANNEL(dsound);
 #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
@@ -96,11 +109,16 @@ struct DirectSoundDevice
     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;
@@ -109,25 +127,18 @@ struct DirectSoundDevice
     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 */
@@ -145,7 +156,10 @@ HRESULT DirectSoundDevice_Initialize(
 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,
@@ -156,6 +170,19 @@ HRESULT DirectSoundDevice_DuplicateSoundBuffer(
     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
@@ -163,74 +190,175 @@ HRESULT DirectSoundDevice_DuplicateSoundBuffer(
 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;
@@ -238,25 +366,26 @@ HRESULT DSOUND_PrimaryStop(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 */
 
@@ -264,9 +393,8 @@ void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb) DECLSPEC_HIDDEN;
 
 /* 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
@@ -274,24 +402,16 @@ HRESULT IDirectSoundCaptureImpl_Create(IUnknown *outer_unk, REFIID riid, void **
 #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_ */
index 8e1b9fe..dbee1b1 100644 (file)
  */
 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,
@@ -261,32 +598,44 @@ static const IDirectSoundFullDuplexVtbl dsfd_vtbl =
     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;
 }
 
 /***************************************************************************
@@ -295,50 +644,93 @@ HRESULT DSOUND_FullDuplexCreate(REFIID riid, void **ppv)
  * 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;
 }
diff --git a/reactos/dll/directx/wine/dsound/fir.h b/reactos/dll/directx/wine/dsound/fir.h
deleted file mode 100644 (file)
index 399fbd4..0000000
+++ /dev/null
@@ -1,1591 +0,0 @@
-#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
-};
index ff912c5..bd861d3 100644 (file)
@@ -1,18 +1,13 @@
 /* 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 */
index bf81b1f..115d15c 100644 (file)
@@ -24,8 +24,6 @@
 
 #include "dsound_private.h"
 
-#include "fir.h"
-
 void DSOUND_RecalcVolPan(PDSVOLUMEPAN volpan)
 {
        double temp;
@@ -78,81 +76,138 @@ void DSOUND_AmpFactorToVolPan(PDSVOLUMEPAN volpan)
     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.
-   &nbs