[REACTOS] Fix 64 bit build (#465)
[reactos.git] / dll / directx / wine / dsound / primary.c
index fd1dbb7..b04a526 100644 (file)
 
 #include "dsound_private.h"
 
-static DWORD DSOUND_fraglen(DirectSoundDevice *device)
+/** Calculate how long a fragment length of about 10 ms should be in frames
+ *
+ * nSamplesPerSec: Frequency rate in samples per second
+ * nBlockAlign: Size of a single blockalign
+ *
+ * Returns:
+ * Size in bytes of a single fragment
+ */
+DWORD DSOUND_fraglen(DWORD nSamplesPerSec, DWORD nBlockAlign)
 {
-    REFERENCE_TIME period;
-    HRESULT hr;
-    DWORD ret;
-
-    hr = IAudioClient_GetDevicePeriod(device->client, &period, NULL);
-    if(FAILED(hr)){
-        /* just guess at 10ms */
-        WARN("GetDevicePeriod failed: %08x\n", hr);
-        ret = MulDiv(device->pwfx->nBlockAlign, device->pwfx->nSamplesPerSec, 100);
-    }else
-        ret = MulDiv(device->pwfx->nSamplesPerSec * device->pwfx->nBlockAlign, period, 10000000);
-
-    ret -= ret % device->pwfx->nBlockAlign;
-    return ret;
+    /* Given a timer delay of 10ms, the fragment size is approximately:
+     *     fraglen = (nSamplesPerSec * 10 / 1000) * nBlockAlign
+     * ==> fraglen = (nSamplesPerSec / 100) * nBlockSize
+     *
+     * ALSA uses buffers that are powers of 2. Because of this, fraglen
+     * is rounded up to the nearest power of 2:
+     */
+
+    if (nSamplesPerSec <= 12800)
+        return 128 * nBlockAlign;
+
+    if (nSamplesPerSec <= 25600)
+        return 256 * nBlockAlign;
+
+    if (nSamplesPerSec <= 51200)
+        return 512 * nBlockAlign;
+
+    return 1024 * nBlockAlign;
 }
 
-static HRESULT DSOUND_WaveFormat(DirectSoundDevice *device, IAudioClient *client,
-                                BOOL forcewave, WAVEFORMATEX **wfx)
+static void DSOUND_RecalcPrimary(DirectSoundDevice *device)
 {
-    WAVEFORMATEXTENSIBLE *retwfe = NULL;
-    WAVEFORMATEX *w;
-    HRESULT hr;
-
-    if (!forcewave) {
-        WAVEFORMATEXTENSIBLE *mixwfe;
-        hr = IAudioClient_GetMixFormat(client, (WAVEFORMATEX**)&mixwfe);
-
-        if (FAILED(hr))
-            return hr;
-
-        if (mixwfe->Format.nChannels > 2) {
-            static int once;
-            if (!once++)
-                FIXME("Limiting channels to 2 due to lack of multichannel support\n");
-
-            mixwfe->Format.nChannels = 2;
-            mixwfe->Format.nBlockAlign = mixwfe->Format.nChannels * mixwfe->Format.wBitsPerSample / 8;
-            mixwfe->Format.nAvgBytesPerSec = mixwfe->Format.nSamplesPerSec * mixwfe->Format.nBlockAlign;
-            mixwfe->dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
-        }
+    TRACE("(%p)\n", device);
 
-        if (!IsEqualGUID(&mixwfe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) {
-            WAVEFORMATEXTENSIBLE testwfe = *mixwfe;
-
-            testwfe.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
-            testwfe.Samples.wValidBitsPerSample = testwfe.Format.wBitsPerSample = 32;
-            testwfe.Format.nBlockAlign = testwfe.Format.nChannels * testwfe.Format.wBitsPerSample / 8;
-            testwfe.Format.nAvgBytesPerSec = testwfe.Format.nSamplesPerSec * testwfe.Format.nBlockAlign;
-
-            if (FAILED(IAudioClient_IsFormatSupported(client, AUDCLNT_SHAREMODE_SHARED, &testwfe.Format, (WAVEFORMATEX**)&retwfe)))
-                w = DSOUND_CopyFormat(&mixwfe->Format);
-            else if (retwfe)
-                w = DSOUND_CopyFormat(&retwfe->Format);
-            else
-                w = DSOUND_CopyFormat(&testwfe.Format);
-            CoTaskMemFree(retwfe);
-            retwfe = NULL;
-        } else
-            w = DSOUND_CopyFormat(&mixwfe->Format);
-        CoTaskMemFree(mixwfe);
-    } else if (device->primary_pwfx->wFormatTag == WAVE_FORMAT_PCM ||
-               device->primary_pwfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) {
-        WAVEFORMATEX *wi = device->primary_pwfx;
-        WAVEFORMATEXTENSIBLE *wfe;
-
-        /* Convert to WAVEFORMATEXTENSIBLE */
-        w = HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEFORMATEXTENSIBLE));
-        wfe = (WAVEFORMATEXTENSIBLE*)w;
-        if (!wfe)
-            return DSERR_OUTOFMEMORY;
-
-        wfe->Format = *wi;
-        w->wFormatTag = WAVE_FORMAT_EXTENSIBLE;
-        w->cbSize = sizeof(*wfe) - sizeof(*w);
-        w->nBlockAlign = w->nChannels * w->wBitsPerSample / 8;
-        w->nAvgBytesPerSec = w->nSamplesPerSec * w->nBlockAlign;
-
-        wfe->dwChannelMask = 0;
-        if (wi->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) {
-            w->wBitsPerSample = 32;
-            wfe->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
-        } else
-            wfe->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
-        wfe->Samples.wValidBitsPerSample = w->wBitsPerSample;
-    } else
-        w = DSOUND_CopyFormat(device->primary_pwfx);
-
-    if (!w)
-        return DSERR_OUTOFMEMORY;
-
-    hr = IAudioClient_IsFormatSupported(client, AUDCLNT_SHAREMODE_SHARED, w, (WAVEFORMATEX**)&retwfe);
-    if (retwfe) {
-        memcpy(w, retwfe, sizeof(WAVEFORMATEX) + retwfe->Format.cbSize);
-        CoTaskMemFree(retwfe);
-    }
-    if (FAILED(hr)) {
-        WARN("IsFormatSupported failed: %08x\n", hr);
-        HeapFree(GetProcessHeap(), 0, w);
-        return hr;
-    }
-    *wfx = w;
-    return S_OK;
+    device->fraglen = DSOUND_fraglen(device->pwfx->nSamplesPerSec, device->pwfx->nBlockAlign);
+    device->helfrags = device->buflen / device->fraglen;
+    TRACE("fraglen=%d helfrags=%d\n", device->fraglen, device->helfrags);
+
+    if (device->hwbuf && device->drvdesc.dwFlags & DSDDESC_DONTNEEDWRITELEAD)
+        device->writelead = 0;
+    else
+        /* calculate the 10ms write lead */
+        device->writelead = (device->pwfx->nSamplesPerSec / 100) * device->pwfx->nBlockAlign;
 }
 
 HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave)
 {
-    UINT prebuf_frames;
-    REFERENCE_TIME prebuf_rt;
-    WAVEFORMATEX *wfx = NULL;
-    HRESULT hres;
-    REFERENCE_TIME period;
-    DWORD period_ms;
-
-    TRACE("(%p, %d)\n", device, forcewave);
-
-    if(device->client){
-        IAudioClient_Release(device->client);
-        device->client = NULL;
-    }
-    if(device->render){
-        IAudioRenderClient_Release(device->render);
-        device->render = NULL;
-    }
-    if(device->clock){
-        IAudioClock_Release(device->clock);
-        device->clock = NULL;
-    }
-    if(device->volume){
-        IAudioStreamVolume_Release(device->volume);
-        device->volume = NULL;
-    }
+       HRESULT hres = DS_OK;
+       TRACE("(%p, %d)\n", device, forcewave);
+
+       if (device->driver)
+       {
+               IDsDriver_Close(device->driver);
+               if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
+                       waveOutClose(device->hwo);
+               IDsDriver_Release(device->driver);
+               device->driver = NULL;
+               device->buffer = NULL;
+               device->hwo = 0;
+       }
+       else if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
+               waveOutClose(device->hwo);
+
+       /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
+       if (ds_hw_accel != DS_HW_ACCEL_EMULATION && !forcewave)
+               waveOutMessage((HWAVEOUT)(DWORD_PTR)device->drvdesc.dnDevNode, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&device->driver, 0);
+
+       /* Get driver description */
+       if (device->driver) {
+               DWORD wod = device->drvdesc.dnDevNode;
+               hres = IDsDriver_GetDriverDesc(device->driver,&(device->drvdesc));
+               device->drvdesc.dnDevNode = wod;
+               if (FAILED(hres)) {
+                       WARN("IDsDriver_GetDriverDesc failed: %08x\n", hres);
+                       IDsDriver_Release(device->driver);
+                       device->driver = NULL;
+               }
+        }
 
-    hres = IMMDevice_Activate(device->mmdevice, &IID_IAudioClient,
-            CLSCTX_INPROC_SERVER, NULL, (void **)&device->client);
-    if(FAILED(hres)) {
-        WARN("Activate failed: %08x\n", hres);
-        return hres;
-    }
+        /* if no DirectSound interface available, use WINMM API instead */
+       if (!device->driver)
+               device->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
 
-    hres = DSOUND_WaveFormat(device, device->client, forcewave, &wfx);
-    if (FAILED(hres)) {
-        IAudioClient_Release(device->client);
-        device->client = NULL;
-        return hres;
-    }
-    HeapFree(GetProcessHeap(), 0, device->pwfx);
-    device->pwfx = wfx;
-
-    prebuf_frames = device->prebuf * DSOUND_fraglen(device) / device->pwfx->nBlockAlign;
-    prebuf_rt = (10000000 * (UINT64)prebuf_frames) / device->pwfx->nSamplesPerSec;
-
-    hres = IAudioClient_Initialize(device->client,
-            AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_NOPERSIST |
-            AUDCLNT_STREAMFLAGS_EVENTCALLBACK, prebuf_rt, 0, device->pwfx, NULL);
-    if(FAILED(hres)){
-        IAudioClient_Release(device->client);
-        device->client = NULL;
-        WARN("Initialize failed: %08x\n", hres);
-        return hres;
-    }
-    IAudioClient_SetEventHandle(device->client, device->sleepev);
-
-    hres = IAudioClient_GetService(device->client, &IID_IAudioRenderClient,
-            (void**)&device->render);
-    if(FAILED(hres)){
-        IAudioClient_Release(device->client);
-        device->client = NULL;
-        WARN("GetService failed: %08x\n", hres);
-        return hres;
-    }
+       if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
+       {
+               DWORD flags = CALLBACK_FUNCTION | WAVE_MAPPED;
 
-    hres = IAudioClient_GetService(device->client, &IID_IAudioClock,
-            (void**)&device->clock);
-    if(FAILED(hres)){
-        IAudioClient_Release(device->client);
-        IAudioRenderClient_Release(device->render);
-        device->client = NULL;
-        device->render = NULL;
-        WARN("GetService failed: %08x\n", hres);
-        return hres;
-    }
+               if (device->driver)
+                       flags |= WAVE_DIRECTSOUND;
 
-    hres = IAudioClient_GetService(device->client, &IID_IAudioStreamVolume,
-            (void**)&device->volume);
-    if(FAILED(hres)){
-        IAudioClient_Release(device->client);
-        IAudioRenderClient_Release(device->render);
-        IAudioClock_Release(device->clock);
-        device->client = NULL;
-        device->render = NULL;
-        device->clock = NULL;
-        WARN("GetService failed: %08x\n", hres);
-        return hres;
-    }
+               hres = mmErr(waveOutOpen(&(device->hwo), device->drvdesc.dnDevNode, device->pwfx, (DWORD_PTR)DSOUND_callback, (DWORD_PTR)device, flags));
+               if (FAILED(hres)) {
+                       WARN("waveOutOpen failed\n");
+                       if (device->driver)
+                       {
+                               IDsDriver_Release(device->driver);
+                               device->driver = NULL;
+                       }
+                       return hres;
+               }
+       }
 
-    /* Now kick off the timer so the event fires periodically */
-    hres = IAudioClient_Start(device->client);
-    if (FAILED(hres))
-        WARN("starting failed with %08x\n", hres);
-
-    hres = IAudioClient_GetStreamLatency(device->client, &period);
-    if (FAILED(hres)) {
-        WARN("GetStreamLatency failed with %08x\n", hres);
-        period_ms = 10;
-    } else
-        period_ms = (period + 9999) / 10000;
-    TRACE("period %u ms fraglen %u prebuf %u\n", period_ms, device->fraglen, device->prebuf);
-
-    if (period_ms < 3)
-        device->sleeptime = 5;
-    else
-        device->sleeptime = period_ms * 5 / 2;
+       if (device->driver)
+               hres = IDsDriver_Open(device->driver);
 
-    return S_OK;
+       return hres;
 }
 
-HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
+static HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
 {
-       IDirectSoundBufferImpl** dsb = device->buffers;
-       LPBYTE newbuf;
-        int i;
-
+       DWORD buflen;
+       HRESULT err = DS_OK;
        TRACE("(%p)\n", device);
 
-       device->fraglen = DSOUND_fraglen(device);
-
        /* on original windows, the buffer it set to a fixed size, no matter what the settings are.
           on windows this size is always fixed (tested on win-xp) */
        if (!device->buflen)
                device->buflen = ds_hel_buflen;
-       device->buflen -= device->buflen % device->pwfx->nBlockAlign;
-       while(device->buflen < device->fraglen * device->prebuf){
-               device->buflen += ds_hel_buflen;
-               device->buflen -= device->buflen % device->pwfx->nBlockAlign;
+       buflen = device->buflen;
+       buflen -= buflen % device->pwfx->nBlockAlign;
+       device->buflen = buflen;
+
+       if (device->driver)
+       {
+               err = IDsDriver_CreateSoundBuffer(device->driver,device->pwfx,
+                                                 DSBCAPS_PRIMARYBUFFER,0,
+                                                 &(device->buflen),&(device->buffer),
+                                                 (LPVOID*)&(device->hwbuf));
+
+               if (err != DS_OK) {
+                       WARN("IDsDriver_CreateSoundBuffer failed (%08x), falling back to waveout\n", err);
+                       err = DSOUND_ReopenDevice(device, TRUE);
+                       if (FAILED(err))
+                       {
+                               WARN("Falling back to waveout failed too! Giving up\n");
+                               return err;
+                       }
+               }
+                if (device->hwbuf)
+                    IDsDriverBuffer_SetVolumePan(device->hwbuf, &device->volpan);
+
+                DSOUND_RecalcPrimary(device);
+               device->prebuf = ds_snd_queue_max;
+               if (device->helfrags < ds_snd_queue_min)
+               {
+                       WARN("Too little sound buffer to be effective (%d/%d) falling back to waveout\n", device->buflen, ds_snd_queue_min * device->fraglen);
+                       device->buflen = buflen;
+                       IDsDriverBuffer_Release(device->hwbuf);
+                       device->hwbuf = NULL;
+                       err = DSOUND_ReopenDevice(device, TRUE);
+                       if (FAILED(err))
+                       {
+                               WARN("Falling back to waveout failed too! Giving up\n");
+                               return err;
+                       }
+               }
+               else if (device->helfrags < ds_snd_queue_max)
+                       device->prebuf = device->helfrags;
        }
 
-       HeapFree(GetProcessHeap(), 0, device->mix_buffer);
-       device->mix_buffer_len = (device->buflen / (device->pwfx->wBitsPerSample / 8)) * sizeof(float);
-       device->mix_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, device->mix_buffer_len);
+       device->mix_buffer_len = DSOUND_bufpos_to_mixpos(device, device->buflen);
+       device->mix_buffer = HeapAlloc(GetProcessHeap(), 0, device->mix_buffer_len);
        if (!device->mix_buffer)
+       {
+               if (device->hwbuf)
+                       IDsDriverBuffer_Release(device->hwbuf);
+               device->hwbuf = NULL;
                return DSERR_OUTOFMEMORY;
+       }
 
        if (device->state == STATE_PLAYING) device->state = STATE_STARTING;
        else if (device->state == STATE_STOPPING) device->state = STATE_STOPPED;
 
-    /* reallocate emulated primary buffer */
-    if (device->buffer)
-        newbuf = HeapReAlloc(GetProcessHeap(),0,device->buffer, device->buflen);
-    else
-        newbuf = HeapAlloc(GetProcessHeap(),0, device->buflen);
+       /* are we using waveOut stuff? */
+       if (!device->driver) {
+               LPBYTE newbuf;
+               LPWAVEHDR headers = NULL;
+               DWORD overshot;
+               unsigned int c;
 
-    if (!newbuf) {
-        ERR("failed to allocate primary buffer\n");
-        return DSERR_OUTOFMEMORY;
-        /* but the old buffer might still exist and must be re-prepared */
-    }
+               /* Start in pause mode, to allow buffers to get filled */
+               waveOutPause(device->hwo);
 
-    device->writelead = (device->pwfx->nSamplesPerSec / 100) * device->pwfx->nBlockAlign;
+               TRACE("desired buflen=%d, old buffer=%p\n", buflen, device->buffer);
 
-    device->buffer = newbuf;
+               /* reallocate emulated primary buffer */
+               if (device->buffer)
+                       newbuf = HeapReAlloc(GetProcessHeap(),0,device->buffer, buflen);
+               else
+                       newbuf = HeapAlloc(GetProcessHeap(),0, buflen);
 
-    TRACE("buflen: %u, fraglen: %u, mix_buffer_len: %u\n",
-            device->buflen, device->fraglen, device->mix_buffer_len);
+               if (!newbuf) {
+                       ERR("failed to allocate primary buffer\n");
+                       return DSERR_OUTOFMEMORY;
+                       /* but the old buffer might still exist and must be re-prepared */
+               }
 
-    if(device->pwfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
-            (device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
-             IsEqualGUID(&((WAVEFORMATEXTENSIBLE*)device->pwfx)->SubFormat,
-                 &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)))
-        device->normfunction = normfunctions[4];
-    else
-        device->normfunction = normfunctions[device->pwfx->wBitsPerSample/8 - 1];
+               DSOUND_RecalcPrimary(device);
+               if (device->pwave)
+                       headers = HeapReAlloc(GetProcessHeap(),0,device->pwave, device->helfrags * sizeof(WAVEHDR));
+               else
+                       headers = HeapAlloc(GetProcessHeap(),0,device->helfrags * sizeof(WAVEHDR));
 
-    FillMemory(device->buffer, device->buflen, (device->pwfx->wBitsPerSample == 8) ? 128 : 0);
-    FillMemory(device->mix_buffer, device->mix_buffer_len, 0);
-    device->playpos = 0;
+               if (!headers) {
+                       ERR("failed to allocate wave headers\n");
+                       HeapFree(GetProcessHeap(), 0, newbuf);
+                       DSOUND_RecalcPrimary(device);
+                       return DSERR_OUTOFMEMORY;
+               }
 
-    if (device->pwfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
-        (device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
-         IsEqualGUID(&((WAVEFORMATEXTENSIBLE*)device->pwfx)->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)))
-        device->normfunction = normfunctions[4];
-    else
-        device->normfunction = normfunctions[device->pwfx->wBitsPerSample/8 - 1];
+               device->buffer = newbuf;
+               device->pwave = headers;
+
+               /* prepare fragment headers */
+               for (c=0; c<device->helfrags; c++) {
+                       device->pwave[c].lpData = (char*)device->buffer + c*device->fraglen;
+                       device->pwave[c].dwBufferLength = device->fraglen;
+                       device->pwave[c].dwUser = (DWORD_PTR)device;
+                       device->pwave[c].dwFlags = 0;
+                       device->pwave[c].dwLoops = 0;
+                       err = mmErr(waveOutPrepareHeader(device->hwo,&device->pwave[c],sizeof(WAVEHDR)));
+                       if (err != DS_OK) {
+                               while (c--)
+                                       waveOutUnprepareHeader(device->hwo,&device->pwave[c],sizeof(WAVEHDR));
+                               break;
+                       }
+               }
 
-    for (i = 0; i < device->nrofbuffers; i++) {
-        RtlAcquireResourceExclusive(&dsb[i]->lock, TRUE);
-        DSOUND_RecalcFormat(dsb[i]);
-        RtlReleaseResource(&dsb[i]->lock);
-    }
+               overshot = device->buflen % device->fraglen;
+               /* sanity */
+               if(overshot)
+               {
+                       overshot -= overshot % device->pwfx->nBlockAlign;
+                       device->pwave[device->helfrags - 1].dwBufferLength += overshot;
+               }
 
-    return DS_OK;
+               TRACE("fraglen=%d, overshot=%d\n", device->fraglen, overshot);
+       }
+       device->mixfunction = mixfunctions[device->pwfx->wBitsPerSample/8 - 1];
+       device->normfunction = normfunctions[device->pwfx->wBitsPerSample/8 - 1];
+       FillMemory(device->buffer, device->buflen, (device->pwfx->wBitsPerSample == 8) ? 128 : 0);
+       FillMemory(device->mix_buffer, device->mix_buffer_len, 0);
+       device->pwplay = device->pwqueue = device->playpos = device->mixpos = 0;
+       return err;
 }
 
 
 static void DSOUND_PrimaryClose(DirectSoundDevice *device)
 {
-    HRESULT hr;
-
-    TRACE("(%p)\n", device);
+       TRACE("(%p)\n", device);
 
-    if(device->client){
-        hr = IAudioClient_Stop(device->client);
-        if(FAILED(hr))
-            WARN("Stop failed: %08x\n", hr);
-    }
+       /* are we using waveOut stuff? */
+       if (!device->hwbuf) {
+               unsigned c;
 
-    /* clear the queue */
-    device->in_mmdev_bytes = 0;
+               /* get out of CS when calling the wave system */
+               LeaveCriticalSection(&(device->mixlock));
+               /* **** */
+               device->pwqueue = (DWORD)-1; /* resetting queues */
+               waveOutReset(device->hwo);
+               for (c=0; c<device->helfrags; c++)
+                       waveOutUnprepareHeader(device->hwo, &device->pwave[c], sizeof(WAVEHDR));
+               /* **** */
+               EnterCriticalSection(&(device->mixlock));
+
+               /* clear the queue */
+               device->pwqueue = 0;
+       } else {
+               ULONG ref = IDsDriverBuffer_Release(device->hwbuf);
+               if (!ref)
+                       device->hwbuf = 0;
+               else
+                       ERR("Still %d references on primary buffer, refcount leak?\n", ref);
+       }
 }
 
 HRESULT DSOUND_PrimaryCreate(DirectSoundDevice *device)
@@ -361,16 +326,15 @@ HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *device)
        EnterCriticalSection(&(device->mixlock));
 
        DSOUND_PrimaryClose(device);
-
-       if(device->primary && (device->primary->ref || device->primary->numIfaces))
-               WARN("Destroying primary buffer while references held (%u %u)\n", device->primary->ref, device->primary->numIfaces);
-
-       HeapFree(GetProcessHeap(), 0, device->primary);
-       device->primary = NULL;
-
-       HeapFree(GetProcessHeap(),0,device->primary_pwfx);
-       HeapFree(GetProcessHeap(),0,device->pwfx);
-       device->pwfx=NULL;
+       if (device->driver) {
+               if (device->hwbuf) {
+                       if (IDsDriverBuffer_Release(device->hwbuf) == 0)
+                               device->hwbuf = 0;
+               }
+       } else
+                HeapFree(GetProcessHeap(),0,device->pwave);
+        HeapFree(GetProcessHeap(),0,device->pwfx);
+        device->pwfx=NULL;
 
        LeaveCriticalSection(&(device->mixlock));
        /* **** */
@@ -380,47 +344,84 @@ HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *device)
 
 HRESULT DSOUND_PrimaryPlay(DirectSoundDevice *device)
 {
-    HRESULT hr;
-
-    TRACE("(%p)\n", device);
+       HRESULT err = DS_OK;
+       TRACE("(%p)\n", device);
 
-    hr = IAudioClient_Start(device->client);
-    if(FAILED(hr) && hr != AUDCLNT_E_NOT_STOPPED){
-        WARN("Start failed: %08x\n", hr);
-        return hr;
-    }
+       if (device->hwbuf) {
+               err = IDsDriverBuffer_Play(device->hwbuf, 0, 0, DSBPLAY_LOOPING);
+               if (err != DS_OK)
+                       WARN("IDsDriverBuffer_Play failed\n");
+       } else {
+               err = mmErr(waveOutRestart(device->hwo));
+               if (err != DS_OK)
+                       WARN("waveOutRestart failed\n");
+       }
 
-    return DS_OK;
+       return err;
 }
 
 HRESULT DSOUND_PrimaryStop(DirectSoundDevice *device)
 {
-    HRESULT hr;
+       HRESULT err = DS_OK;
+       TRACE("(%p)\n", device);
 
-    TRACE("(%p)\n", device);
+       if (device->hwbuf) {
+               err = IDsDriverBuffer_Stop(device->hwbuf);
+               if (err == DSERR_BUFFERLOST) {
+                       DSOUND_PrimaryClose(device);
+                       err = DSOUND_ReopenDevice(device, FALSE);
+                       if (FAILED(err))
+                               ERR("DSOUND_ReopenDevice failed\n");
+                       else
+                       {
+                               err = DSOUND_PrimaryOpen(device);
+                               if (FAILED(err))
+                                       WARN("DSOUND_PrimaryOpen failed\n");
+                       }
+               } else if (err != DS_OK) {
+                       WARN("IDsDriverBuffer_Stop failed\n");
+               }
+       } else {
 
-    hr = IAudioClient_Stop(device->client);
-    if(FAILED(hr)){
-        WARN("Stop failed: %08x\n", hr);
-        return hr;
-    }
+               /* don't call the wave system with the lock set */
+               LeaveCriticalSection(&(device->mixlock));
+               /* **** */
 
-    return DS_OK;
+               err = mmErr(waveOutPause(device->hwo));
+
+               /* **** */
+               EnterCriticalSection(&(device->mixlock));
+
+               if (err != DS_OK)
+                       WARN("waveOutPause failed\n");
+       }
+
+       return err;
 }
 
 HRESULT DSOUND_PrimaryGetPosition(DirectSoundDevice *device, LPDWORD playpos, LPDWORD writepos)
 {
        TRACE("(%p,%p,%p)\n", device, playpos, writepos);
 
-       /* check if playpos was requested */
-       if (playpos)
-               *playpos = device->playing_offs_bytes;
+       if (device->hwbuf) {
+               HRESULT err=IDsDriverBuffer_GetPosition(device->hwbuf,playpos,writepos);
+               if (err != S_OK) {
+                       WARN("IDsDriverBuffer_GetPosition failed\n");
+                       return err;
+               }
+       } else {
+               TRACE("pwplay=%i, pwqueue=%i\n", device->pwplay, device->pwqueue);
 
-       /* check if writepos was requested */
-       if (writepos)
-               /* the writepos is the first non-queued position */
-               *writepos = (device->playing_offs_bytes + device->in_mmdev_bytes) % device->buflen;
+               /* check if playpos was requested */
+               if (playpos)
+                       /* use the cached play position */
+                       *playpos = device->pwplay * device->fraglen;
 
+               /* check if writepos was requested */
+               if (writepos)
+                       /* the writepos is the first non-queued position */
+                       *writepos = ((device->pwplay + device->pwqueue) % device->helfrags) * device->fraglen;
+       }
        TRACE("playpos = %d, writepos = %d (%p, time=%d)\n", playpos?*playpos:-1, writepos?*writepos:-1, device, GetTickCount());
        return DS_OK;
 }
@@ -456,14 +457,15 @@ LPWAVEFORMATEX DSOUND_CopyFormat(LPCWAVEFORMATEX wfex)
        return pwfx;
 }
 
-HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX passed_fmt)
+HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex)
 {
-       HRESULT err = S_OK;
-       WAVEFORMATEX *old_fmt;
-       WAVEFORMATEXTENSIBLE *fmtex, *passed_fmtex = (WAVEFORMATEXTENSIBLE*)passed_fmt;
-       BOOL forced = (device->priolevel == DSSCL_WRITEPRIMARY);
+       HRESULT err = DSERR_BUFFERLOST;
+       int i;
+       DWORD nSamplesPerSec, bpp, chans;
+       LPWAVEFORMATEX oldpwfx;
+        BOOL forced = device->priolevel == DSSCL_WRITEPRIMARY;
 
-       TRACE("(%p,%p)\n", device, passed_fmt);
+       TRACE("(%p,%p)\n", device, wfex);
 
        if (device->priolevel == DSSCL_NORMAL) {
                WARN("failed priority check!\n");
@@ -471,93 +473,129 @@ HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX passe
        }
 
        /* Let's be pedantic! */
-       if (passed_fmt == NULL) {
-               WARN("invalid parameter: passed_fmt==NULL!\n");
+       if (wfex == NULL) {
+               WARN("invalid parameter: wfex==NULL!\n");
                return DSERR_INVALIDPARAM;
        }
        TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
-                         "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
-                 passed_fmt->wFormatTag, passed_fmt->nChannels, passed_fmt->nSamplesPerSec,
-                 passed_fmt->nAvgBytesPerSec, passed_fmt->nBlockAlign,
-                 passed_fmt->wBitsPerSample, passed_fmt->cbSize);
-
-       if(passed_fmt->wBitsPerSample < 8 || passed_fmt->wBitsPerSample % 8 != 0 ||
-                       passed_fmt->nChannels == 0 || passed_fmt->nSamplesPerSec == 0 ||
-                       passed_fmt->nAvgBytesPerSec == 0 ||
-                       passed_fmt->nBlockAlign != passed_fmt->nChannels * passed_fmt->wBitsPerSample / 8)
-               return DSERR_INVALIDPARAM;
-
-       if(passed_fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE){
-               if(passed_fmtex->Samples.wValidBitsPerSample > passed_fmtex->Format.wBitsPerSample)
-                       return DSERR_INVALIDPARAM;
-       }
+              "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
+             wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec,
+             wfex->nAvgBytesPerSec, wfex->nBlockAlign,
+             wfex->wBitsPerSample, wfex->cbSize);
 
        /* **** */
        RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE);
        EnterCriticalSection(&(device->mixlock));
 
-       if (device->priolevel == DSSCL_WRITEPRIMARY) {
-               old_fmt = device->primary_pwfx;
-               device->primary_pwfx = DSOUND_CopyFormat(passed_fmt);
-               fmtex = (WAVEFORMATEXTENSIBLE *)device->primary_pwfx;
-               if (device->primary_pwfx == NULL) {
-                       err = DSERR_OUTOFMEMORY;
-                       goto out;
+       nSamplesPerSec = device->pwfx->nSamplesPerSec;
+       bpp = device->pwfx->wBitsPerSample;
+       chans = device->pwfx->nChannels;
+
+       oldpwfx = device->pwfx;
+       device->pwfx = DSOUND_CopyFormat(wfex);
+       if (device->pwfx == NULL) {
+               device->pwfx = oldpwfx;
+               oldpwfx = NULL;
+               err = DSERR_OUTOFMEMORY;
+               goto done;
+       }
+
+       if (!(device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMSETFORMAT) && device->hwbuf) {
+               err = IDsDriverBuffer_SetFormat(device->hwbuf, device->pwfx);
+
+               /* On bad format, try to re-create, big chance it will work then, only do this if we <HAVE> to */
+               if (forced && (device->pwfx->nSamplesPerSec/100 != wfex->nSamplesPerSec/100 || err == DSERR_BADFORMAT))
+               {
+                       DWORD cp_size = wfex->wFormatTag == WAVE_FORMAT_PCM ?
+                               sizeof(PCMWAVEFORMAT) : sizeof(WAVEFORMATEX) + wfex->cbSize;
+                       err = DSERR_BUFFERLOST;
+                       CopyMemory(device->pwfx, wfex, cp_size);
                }
 
-               if (fmtex->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
-                   fmtex->Samples.wValidBitsPerSample == 0) {
-                       TRACE("Correcting 0 valid bits per sample\n");
-                       fmtex->Samples.wValidBitsPerSample = fmtex->Format.wBitsPerSample;
+               if (err != DSERR_BUFFERLOST && FAILED(err)) {
+                       DWORD size = DSOUND_GetFormatSize(oldpwfx);
+                       WARN("IDsDriverBuffer_SetFormat failed\n");
+                       if (!forced) {
+                               CopyMemory(device->pwfx, oldpwfx, size);
+                               err = DS_OK;
+                       }
+                       goto done;
                }
 
+               if (err == S_FALSE)
+               {
+                       /* ALSA specific: S_FALSE tells that recreation was successful,
+                        * but size and location may be changed, and buffer has to be restarted
+                        * I put it here, so if frequency doesn't match the error will be changed to DSERR_BUFFERLOST
+                        * and the entire re-initialization will occur anyway
+                        */
+                       IDsDriverBuffer_Lock(device->hwbuf, (LPVOID *)&device->buffer, &device->buflen, NULL, NULL, 0, 0, DSBLOCK_ENTIREBUFFER);
+                       IDsDriverBuffer_Unlock(device->hwbuf, device->buffer, 0, NULL, 0);
+
+                       if (device->state == STATE_PLAYING) device->state = STATE_STARTING;
+                       else if (device->state == STATE_STOPPING) device->state = STATE_STOPPED;
+                       device->pwplay = device->pwqueue = device->playpos = device->mixpos = 0;
+                       err = DS_OK;
+               }
+               DSOUND_RecalcPrimary(device);
+       }
+
+       if (err == DSERR_BUFFERLOST)
+       {
                DSOUND_PrimaryClose(device);
 
-               err = DSOUND_ReopenDevice(device, forced);
-               if (FAILED(err)) {
-                       ERR("No formats could be opened\n");
+               err = DSOUND_ReopenDevice(device, FALSE);
+               if (FAILED(err))
+               {
+                       WARN("DSOUND_ReopenDevice failed: %08x\n", err);
                        goto done;
                }
-
                err = DSOUND_PrimaryOpen(device);
                if (err != DS_OK) {
-                       ERR("DSOUND_PrimaryOpen failed\n");
+                       WARN("DSOUND_PrimaryOpen failed\n");
                        goto done;
                }
 
-done:
-               if (err != DS_OK)
-                       device->primary_pwfx = old_fmt;
-               else
-                       HeapFree(GetProcessHeap(), 0, old_fmt);
-       } else if (passed_fmt->wFormatTag == WAVE_FORMAT_PCM ||
-                  passed_fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) {
-               /* Fill in "real" values to primary_pwfx */
-               WAVEFORMATEX *fmt = device->primary_pwfx;
-
-               *fmt = *device->pwfx;
-               fmtex = (void*)device->pwfx;
-
-               if (IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) &&
-                   passed_fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) {
-                       fmt->wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
-               } else {
-                       fmt->wFormatTag = WAVE_FORMAT_PCM;
-                       fmt->wBitsPerSample = 16;
+               if (wfex->nSamplesPerSec/100 != device->pwfx->nSamplesPerSec/100 && forced && device->buffer)
+               {
+                       DSOUND_PrimaryClose(device);
+                       device->pwfx->nSamplesPerSec = wfex->nSamplesPerSec;
+                       err = DSOUND_ReopenDevice(device, TRUE);
+                       if (FAILED(err))
+                               WARN("DSOUND_ReopenDevice(2) failed: %08x\n", err);
+                       else if (FAILED((err = DSOUND_PrimaryOpen(device))))
+                               WARN("DSOUND_PrimaryOpen(2) failed: %08x\n", err);
+               }
+       }
+
+       device->mix_buffer_len = DSOUND_bufpos_to_mixpos(device, device->buflen);
+       device->mix_buffer = HeapReAlloc(GetProcessHeap(), 0, device->mix_buffer, device->mix_buffer_len);
+       FillMemory(device->mix_buffer, device->mix_buffer_len, 0);
+       device->mixfunction = mixfunctions[device->pwfx->wBitsPerSample/8 - 1];
+       device->normfunction = normfunctions[device->pwfx->wBitsPerSample/8 - 1];
+
+       if (nSamplesPerSec != device->pwfx->nSamplesPerSec || bpp != device->pwfx->wBitsPerSample || chans != device->pwfx->nChannels) {
+               IDirectSoundBufferImpl** dsb = device->buffers;
+               for (i = 0; i < device->nrofbuffers; i++, dsb++) {
+                       /* **** */
+                       RtlAcquireResourceExclusive(&(*dsb)->lock, TRUE);
+
+                       (*dsb)->freqAdjust = ((DWORD64)(*dsb)->freq << DSOUND_FREQSHIFT) / device->pwfx->nSamplesPerSec;
+                       DSOUND_RecalcFormat((*dsb));
+                       DSOUND_MixToTemporary((*dsb), 0, (*dsb)->buflen, FALSE);
+                       (*dsb)->primary_mixpos = 0;
+
+                       RtlReleaseResource(&(*dsb)->lock);
+                       /* **** */
                }
-               fmt->nBlockAlign = fmt->nChannels * fmt->wBitsPerSample / 8;
-               fmt->nAvgBytesPerSec = fmt->nBlockAlign * fmt->nSamplesPerSec;
-               fmt->cbSize = 0;
-       } else {
-               device->primary_pwfx = HeapReAlloc(GetProcessHeap(), 0, device->primary_pwfx, sizeof(*fmtex));
-               memcpy(device->primary_pwfx, device->pwfx, sizeof(*fmtex));
        }
 
-out:
+done:
        LeaveCriticalSection(&(device->mixlock));
        RtlReleaseResource(&(device->buffer_list_lock));
        /* **** */
 
+       HeapFree(GetProcessHeap(), 0, oldpwfx);
        return err;
 }
 
@@ -570,22 +608,24 @@ static inline IDirectSoundBufferImpl *impl_from_IDirectSoundBuffer(IDirectSoundB
     return CONTAINING_RECORD(iface, IDirectSoundBufferImpl, IDirectSoundBuffer8_iface);
 }
 
-/* This sets this format for the primary buffer only */
-static HRESULT WINAPI PrimaryBufferImpl_SetFormat(IDirectSoundBuffer *iface,
-        const WAVEFORMATEX *wfex)
+/* This sets this format for the <em>Primary Buffer Only</em> */
+/* See file:///cdrom/sdk52/docs/worddoc/dsound.doc page 120 */
+static HRESULT WINAPI PrimaryBufferImpl_SetFormat(
+    LPDIRECTSOUNDBUFFER iface,
+    LPCWAVEFORMATEX wfex)
 {
     IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
     TRACE("(%p,%p)\n", iface, wfex);
     return primarybuffer_SetFormat(This->device, wfex);
 }
 
-static HRESULT WINAPI PrimaryBufferImpl_SetVolume(IDirectSoundBuffer *iface, LONG vol)
-{
-       IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
-       DirectSoundDevice *device = This->device;
-       HRESULT hr;
-       float lvol, rvol;
-
+static HRESULT WINAPI PrimaryBufferImpl_SetVolume(
+       LPDIRECTSOUNDBUFFER iface,LONG vol
+) {
+        IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
+        DirectSoundDevice *device = This->device;
+       DWORD ampfactors;
+        HRESULT hres = DS_OK;
        TRACE("(%p,%d)\n", iface, vol);
 
        if (!(This->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
@@ -599,63 +639,37 @@ static HRESULT WINAPI PrimaryBufferImpl_SetVolume(IDirectSoundBuffer *iface, LON
        }
 
        /* **** */
-       EnterCriticalSection(&device->mixlock);
-
-       hr = IAudioStreamVolume_GetChannelVolume(device->volume, 0, &lvol);
-       if(FAILED(hr)){
-               LeaveCriticalSection(&device->mixlock);
-               WARN("GetChannelVolume failed: %08x\n", hr);
-               return hr;
-       }
-
-       if(device->pwfx->nChannels > 1){
-               hr = IAudioStreamVolume_GetChannelVolume(device->volume, 1, &rvol);
-               if(FAILED(hr)){
-                       LeaveCriticalSection(&device->mixlock);
-                       WARN("GetChannelVolume failed: %08x\n", hr);
-                       return hr;
-               }
-       }else
-               rvol = 1;
-
-       device->volpan.dwTotalLeftAmpFactor = ((UINT16)(lvol * (DWORD)0xFFFF));
-       device->volpan.dwTotalRightAmpFactor = ((UINT16)(rvol * (DWORD)0xFFFF));
-
-       DSOUND_AmpFactorToVolPan(&device->volpan);
-       if (vol != device->volpan.lVolume) {
-               device->volpan.lVolume=vol;
-               DSOUND_RecalcVolPan(&device->volpan);
-               lvol = (float)((DWORD)(device->volpan.dwTotalLeftAmpFactor & 0xFFFF) / (float)0xFFFF);
-               hr = IAudioStreamVolume_SetChannelVolume(device->volume, 0, lvol);
-               if(FAILED(hr)){
-                       LeaveCriticalSection(&device->mixlock);
-                       WARN("SetChannelVolume failed: %08x\n", hr);
-                       return hr;
-               }
+       EnterCriticalSection(&(device->mixlock));
 
-               if(device->pwfx->nChannels > 1){
-                       rvol = (float)((DWORD)(device->volpan.dwTotalRightAmpFactor & 0xFFFF) / (float)0xFFFF);
-                       hr = IAudioStreamVolume_SetChannelVolume(device->volume, 1, rvol);
-                       if(FAILED(hr)){
-                               LeaveCriticalSection(&device->mixlock);
-                               WARN("SetChannelVolume failed: %08x\n", hr);
-                               return hr;
-                       }
-               }
-       }
+        waveOutGetVolume(device->hwo, &ampfactors);
+        device->volpan.dwTotalLeftAmpFactor=ampfactors & 0xffff;
+        device->volpan.dwTotalRightAmpFactor=ampfactors >> 16;
+        DSOUND_AmpFactorToVolPan(&device->volpan);
+        if (vol != device->volpan.lVolume) {
+            device->volpan.lVolume=vol;
+            DSOUND_RecalcVolPan(&device->volpan);
+            if (device->hwbuf) {
+                hres = IDsDriverBuffer_SetVolumePan(device->hwbuf, &device->volpan);
+                if (hres != DS_OK)
+                    WARN("IDsDriverBuffer_SetVolumePan failed\n");
+            } else {
+                ampfactors = (device->volpan.dwTotalLeftAmpFactor & 0xffff) | (device->volpan.dwTotalRightAmpFactor << 16);
+                waveOutSetVolume(device->hwo, ampfactors);
+            }
+        }
 
        LeaveCriticalSection(&(device->mixlock));
        /* **** */
 
-       return DS_OK;
+       return hres;
 }
 
-static HRESULT WINAPI PrimaryBufferImpl_GetVolume(IDirectSoundBuffer *iface, LONG *vol)
-{
-       IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
-       DirectSoundDevice *device = This->device;
-       float lvol, rvol;
-       HRESULT hr;
+static HRESULT WINAPI PrimaryBufferImpl_GetVolume(
+       LPDIRECTSOUNDBUFFER iface,LPLONG vol
+) {
+        IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
+        DirectSoundDevice *device = This->device;
+       DWORD ampfactors;
        TRACE("(%p,%p)\n", iface, vol);
 
        if (!(This->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
@@ -668,38 +682,20 @@ static HRESULT WINAPI PrimaryBufferImpl_GetVolume(IDirectSoundBuffer *iface, LON
                return DSERR_INVALIDPARAM;
        }
 
-       EnterCriticalSection(&device->mixlock);
-
-       hr = IAudioStreamVolume_GetChannelVolume(device->volume, 0, &lvol);
-       if(FAILED(hr)){
-               LeaveCriticalSection(&device->mixlock);
-               WARN("GetChannelVolume failed: %08x\n", hr);
-               return hr;
-       }
-
-       if(device->pwfx->nChannels > 1){
-               hr = IAudioStreamVolume_GetChannelVolume(device->volume, 1, &rvol);
-               if(FAILED(hr)){
-                       LeaveCriticalSection(&device->mixlock);
-                       WARN("GetChannelVolume failed: %08x\n", hr);
-                       return hr;
-               }
-       }else
-               rvol = 1;
-
-       device->volpan.dwTotalLeftAmpFactor = ((UINT16)(lvol * (DWORD)0xFFFF));
-       device->volpan.dwTotalRightAmpFactor = ((UINT16)(rvol * (DWORD)0xFFFF));
-
-       DSOUND_AmpFactorToVolPan(&device->volpan);
-       *vol = device->volpan.lVolume;
-
-       LeaveCriticalSection(&device->mixlock);
-
+        if (!device->hwbuf)
+        {
+           waveOutGetVolume(device->hwo, &ampfactors);
+           device->volpan.dwTotalLeftAmpFactor=ampfactors & 0xffff;
+           device->volpan.dwTotalRightAmpFactor=ampfactors >> 16;
+           DSOUND_AmpFactorToVolPan(&device->volpan);
+        }
+        *vol = device->volpan.lVolume;
        return DS_OK;
 }
 
-static HRESULT WINAPI PrimaryBufferImpl_SetFrequency(IDirectSoundBuffer *iface, DWORD freq)
-{
+static HRESULT WINAPI PrimaryBufferImpl_SetFrequency(
+       LPDIRECTSOUNDBUFFER iface,DWORD freq
+) {
         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
        TRACE("(%p,%d)\n",This,freq);
 
@@ -708,9 +704,9 @@ static HRESULT WINAPI PrimaryBufferImpl_SetFrequency(IDirectSoundBuffer *iface,
        return DSERR_CONTROLUNAVAIL;
 }
 
-static HRESULT WINAPI PrimaryBufferImpl_Play(IDirectSoundBuffer *iface, DWORD reserved1,
-        DWORD reserved2, DWORD flags)
-{
+static HRESULT WINAPI PrimaryBufferImpl_Play(
+       LPDIRECTSOUNDBUFFER iface,DWORD reserved1,DWORD reserved2,DWORD flags
+{
         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
         DirectSoundDevice *device = This->device;
        TRACE("(%p,%08x,%08x,%08x)\n", iface, reserved1, reserved2, flags);
@@ -734,7 +730,7 @@ static HRESULT WINAPI PrimaryBufferImpl_Play(IDirectSoundBuffer *iface, DWORD re
        return DS_OK;
 }
 
-static HRESULT WINAPI PrimaryBufferImpl_Stop(IDirectSoundBuffer *iface)
+static HRESULT WINAPI PrimaryBufferImpl_Stop(LPDIRECTSOUNDBUFFER iface)
 {
         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
         DirectSoundDevice *device = This->device;
@@ -754,7 +750,7 @@ static HRESULT WINAPI PrimaryBufferImpl_Stop(IDirectSoundBuffer *iface)
        return DS_OK;
 }
 
-static ULONG WINAPI PrimaryBufferImpl_AddRef(IDirectSoundBuffer *iface)
+static ULONG WINAPI PrimaryBufferImpl_AddRef(LPDIRECTSOUNDBUFFER iface)
 {
     IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
     ULONG ref = InterlockedIncrement(&(This->ref));
@@ -764,37 +760,27 @@ static ULONG WINAPI PrimaryBufferImpl_AddRef(IDirectSoundBuffer *iface)
     return ref;
 }
 
-/* Decreases *out by 1 to no less than 0.
- * Returns the new value of *out. */
-LONG capped_refcount_dec(LONG *out)
+void primarybuffer_destroy(IDirectSoundBufferImpl *This)
 {
-    LONG ref, oldref;
-    do {
-        ref = *out;
-        if(!ref)
-            return 0;
-        oldref = InterlockedCompareExchange(out, ref - 1, ref);
-    } while(oldref != ref);
-    return ref - 1;
+    This->device->primary = NULL;
+    HeapFree(GetProcessHeap(), 0, This);
+    TRACE("(%p) released\n", This);
 }
 
-static ULONG WINAPI PrimaryBufferImpl_Release(IDirectSoundBuffer *iface)
+static ULONG WINAPI PrimaryBufferImpl_Release(LPDIRECTSOUNDBUFFER iface)
 {
     IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
-    ULONG ref;
-
-    ref = capped_refcount_dec(&This->ref);
-    if(!ref)
-        capped_refcount_dec(&This->numIfaces);
-
-    TRACE("(%p) primary ref is now %d\n", This, ref);
+    DWORD ref = InterlockedDecrement(&(This->ref));
+    TRACE("(%p) ref was %d\n", This, ref + 1);
 
+    if (!ref && !InterlockedDecrement(&This->numIfaces))
+        primarybuffer_destroy(This);
     return ref;
 }
 
-static HRESULT WINAPI PrimaryBufferImpl_GetCurrentPosition(IDirectSoundBuffer *iface,
-        DWORD *playpos, DWORD *writepos)
-{
+static HRESULT WINAPI PrimaryBufferImpl_GetCurrentPosition(
+       LPDIRECTSOUNDBUFFER iface,LPDWORD playpos,LPDWORD writepos
+{
        HRESULT hres;
         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
         DirectSoundDevice *device = This->device;
@@ -823,8 +809,9 @@ static HRESULT WINAPI PrimaryBufferImpl_GetCurrentPosition(IDirectSoundBuffer *i
        return DS_OK;
 }
 
-static HRESULT WINAPI PrimaryBufferImpl_GetStatus(IDirectSoundBuffer *iface, DWORD *status)
-{
+static HRESULT WINAPI PrimaryBufferImpl_GetStatus(
+       LPDIRECTSOUNDBUFFER iface,LPDWORD status
+) {
         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
         DirectSoundDevice *device = This->device;
        TRACE("(%p,%p)\n", iface, status);
@@ -844,19 +831,22 @@ static HRESULT WINAPI PrimaryBufferImpl_GetStatus(IDirectSoundBuffer *iface, DWO
 }
 
 
-static HRESULT WINAPI PrimaryBufferImpl_GetFormat(IDirectSoundBuffer *iface, WAVEFORMATEX *lpwf,
-        DWORD wfsize, DWORD *wfwritten)
+static HRESULT WINAPI PrimaryBufferImpl_GetFormat(
+    LPDIRECTSOUNDBUFFER iface,
+    LPWAVEFORMATEX lpwf,
+    DWORD wfsize,
+    LPDWORD wfwritten)
 {
     DWORD size;
     IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
     DirectSoundDevice *device = This->device;
     TRACE("(%p,%p,%d,%p)\n", iface, lpwf, wfsize, wfwritten);
 
-    size = sizeof(WAVEFORMATEX) + device->primary_pwfx->cbSize;
+    size = sizeof(WAVEFORMATEX) + device->pwfx->cbSize;
 
     if (lpwf) {        /* NULL is valid */
         if (wfsize >= size) {
-            CopyMemory(lpwf,device->primary_pwfx,size);
+            CopyMemory(lpwf,device->pwfx,size);
             if (wfwritten)
                 *wfwritten = size;
         } else {
@@ -867,7 +857,7 @@ static HRESULT WINAPI PrimaryBufferImpl_GetFormat(IDirectSoundBuffer *iface, WAV
         }
     } else {
         if (wfwritten)
-            *wfwritten = sizeof(WAVEFORMATEX) + device->primary_pwfx->cbSize;
+            *wfwritten = sizeof(WAVEFORMATEX) + device->pwfx->cbSize;
         else {
             WARN("invalid parameter: wfwritten == NULL\n");
             return DSERR_INVALIDPARAM;
@@ -877,10 +867,9 @@ static HRESULT WINAPI PrimaryBufferImpl_GetFormat(IDirectSoundBuffer *iface, WAV
     return DS_OK;
 }
 
-static HRESULT WINAPI PrimaryBufferImpl_Lock(IDirectSoundBuffer *iface, DWORD writecursor,
-        DWORD writebytes, void **lplpaudioptr1, DWORD *audiobytes1, void **lplpaudioptr2,
-        DWORD *audiobytes2, DWORD flags)
-{
+static HRESULT WINAPI PrimaryBufferImpl_Lock(
+       LPDIRECTSOUNDBUFFER iface,DWORD writecursor,DWORD writebytes,LPVOID *lplpaudioptr1,LPDWORD audiobytes1,LPVOID *lplpaudioptr2,LPDWORD audiobytes2,DWORD flags
+) {
        HRESULT hres;
         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
         DirectSoundDevice *device = This->device;
@@ -930,28 +919,41 @@ static HRESULT WINAPI PrimaryBufferImpl_Lock(IDirectSoundBuffer *iface, DWORD wr
                 return DSERR_INVALIDPARAM;
         }
 
-       if (writecursor+writebytes <= device->buflen) {
-               *(LPBYTE*)lplpaudioptr1 = device->buffer+writecursor;
-               *audiobytes1 = writebytes;
-               if (lplpaudioptr2)
-                       *(LPBYTE*)lplpaudioptr2 = NULL;
-               if (audiobytes2)
-                       *audiobytes2 = 0;
-               TRACE("->%d.0\n",writebytes);
+       if (!(device->drvdesc.dwFlags & DSDDESC_DONTNEEDPRIMARYLOCK) && device->hwbuf) {
+               hres = IDsDriverBuffer_Lock(device->hwbuf,
+                                           lplpaudioptr1, audiobytes1,
+                                           lplpaudioptr2, audiobytes2,
+                                           writecursor, writebytes,
+                                           0);
+               if (hres != DS_OK) {
+                       WARN("IDsDriverBuffer_Lock failed\n");
+                       return hres;
+               }
        } else {
-               *(LPBYTE*)lplpaudioptr1 = device->buffer+writecursor;
-               *audiobytes1 = device->buflen-writecursor;
-               if (lplpaudioptr2)
-                       *(LPBYTE*)lplpaudioptr2 = device->buffer;
-               if (audiobytes2)
-                       *audiobytes2 = writebytes-(device->buflen-writecursor);
-               TRACE("->%d.%d\n",*audiobytes1,audiobytes2?*audiobytes2:0);
+               if (writecursor+writebytes <= device->buflen) {
+                       *(LPBYTE*)lplpaudioptr1 = device->buffer+writecursor;
+                       *audiobytes1 = writebytes;
+                       if (lplpaudioptr2)
+                               *(LPBYTE*)lplpaudioptr2 = NULL;
+                       if (audiobytes2)
+                               *audiobytes2 = 0;
+                       TRACE("->%d.0\n",writebytes);
+               } else {
+                       *(LPBYTE*)lplpaudioptr1 = device->buffer+writecursor;
+                       *audiobytes1 = device->buflen-writecursor;
+                       if (lplpaudioptr2)
+                               *(LPBYTE*)lplpaudioptr2 = device->buffer;
+                       if (audiobytes2)
+                               *audiobytes2 = writebytes-(device->buflen-writecursor);
+                       TRACE("->%d.%d\n",*audiobytes1,audiobytes2?*audiobytes2:0);
+               }
        }
        return DS_OK;
 }
 
-static HRESULT WINAPI PrimaryBufferImpl_SetCurrentPosition(IDirectSoundBuffer *iface, DWORD newpos)
-{
+static HRESULT WINAPI PrimaryBufferImpl_SetCurrentPosition(
+       LPDIRECTSOUNDBUFFER iface,DWORD newpos
+) {
         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
        TRACE("(%p,%d)\n",This,newpos);
 
@@ -960,12 +962,13 @@ static HRESULT WINAPI PrimaryBufferImpl_SetCurrentPosition(IDirectSoundBuffer *i
        return DSERR_INVALIDCALL;
 }
 
-static HRESULT WINAPI PrimaryBufferImpl_SetPan(IDirectSoundBuffer *iface, LONG pan)
-{
-       IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
-       DirectSoundDevice *device = This->device;
-       float lvol, rvol;
-       HRESULT hr;
+static HRESULT WINAPI PrimaryBufferImpl_SetPan(
+       LPDIRECTSOUNDBUFFER iface,LONG pan
+) {
+        IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
+        DirectSoundDevice *device = This->device;
+       DWORD ampfactors;
+        HRESULT hres = DS_OK;
        TRACE("(%p,%d)\n", iface, pan);
 
        if (!(This->dsbd.dwFlags & DSBCAPS_CTRLPAN)) {
@@ -979,64 +982,40 @@ static HRESULT WINAPI PrimaryBufferImpl_SetPan(IDirectSoundBuffer *iface, LONG p
        }
 
        /* **** */
-       EnterCriticalSection(&device->mixlock);
-
-       hr = IAudioStreamVolume_GetChannelVolume(device->volume, 0, &lvol);
-       if(FAILED(hr)){
-               LeaveCriticalSection(&device->mixlock);
-               WARN("GetChannelVolume failed: %08x\n", hr);
-               return hr;
-       }
-
-       if(device->pwfx->nChannels > 1){
-               hr = IAudioStreamVolume_GetChannelVolume(device->volume, 1, &rvol);
-               if(FAILED(hr)){
-                       LeaveCriticalSection(&device->mixlock);
-                       WARN("GetChannelVolume failed: %08x\n", hr);
-                       return hr;
-               }
-       }else
-               rvol = 1;
-
-       device->volpan.dwTotalLeftAmpFactor = ((UINT16)(lvol * (DWORD)0xFFFF));
-       device->volpan.dwTotalRightAmpFactor = ((UINT16)(rvol * (DWORD)0xFFFF));
-
-       DSOUND_AmpFactorToVolPan(&device->volpan);
-       if (pan != device->volpan.lPan) {
-               device->volpan.lPan=pan;
-               DSOUND_RecalcVolPan(&device->volpan);
-
-               lvol = (float)((DWORD)(device->volpan.dwTotalLeftAmpFactor & 0xFFFF) / (float)0xFFFF);
-               hr = IAudioStreamVolume_SetChannelVolume(device->volume, 0, lvol);
-               if(FAILED(hr)){
-                       LeaveCriticalSection(&device->mixlock);
-                       WARN("SetChannelVolume failed: %08x\n", hr);
-                       return hr;
-               }
+       EnterCriticalSection(&(device->mixlock));
 
-               if(device->pwfx->nChannels > 1){
-                       rvol = (float)((DWORD)(device->volpan.dwTotalRightAmpFactor & 0xFFFF) / (float)0xFFFF);
-                       hr = IAudioStreamVolume_SetChannelVolume(device->volume, 1, rvol);
-                       if(FAILED(hr)){
-                               LeaveCriticalSection(&device->mixlock);
-                               WARN("SetChannelVolume failed: %08x\n", hr);
-                               return hr;
-                       }
-               }
-       }
+        if (!device->hwbuf)
+        {
+            waveOutGetVolume(device->hwo, &ampfactors);
+            device->volpan.dwTotalLeftAmpFactor=ampfactors & 0xffff;
+            device->volpan.dwTotalRightAmpFactor=ampfactors >> 16;
+            DSOUND_AmpFactorToVolPan(&device->volpan);
+        }
+        if (pan != device->volpan.lPan) {
+            device->volpan.lPan=pan;
+            DSOUND_RecalcVolPan(&device->volpan);
+            if (device->hwbuf) {
+                hres = IDsDriverBuffer_SetVolumePan(device->hwbuf, &device->volpan);
+                if (hres != DS_OK)
+                    WARN("IDsDriverBuffer_SetVolumePan failed\n");
+            } else {
+                ampfactors = (device->volpan.dwTotalLeftAmpFactor & 0xffff) | (device->volpan.dwTotalRightAmpFactor << 16);
+                waveOutSetVolume(device->hwo, ampfactors);
+            }
+        }
 
-       LeaveCriticalSection(&device->mixlock);
+       LeaveCriticalSection(&(device->mixlock));
        /* **** */
 
-       return DS_OK;
+       return hres;
 }
 
-static HRESULT WINAPI PrimaryBufferImpl_GetPan(IDirectSoundBuffer *iface, LONG *pan)
-{
-       IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
-       DirectSoundDevice *device = This->device;
-       float lvol, rvol;
-       HRESULT hr;
+static HRESULT WINAPI PrimaryBufferImpl_GetPan(
+       LPDIRECTSOUNDBUFFER iface,LPLONG pan
+) {
+        IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
+        DirectSoundDevice *device = This->device;
+       DWORD ampfactors;
        TRACE("(%p,%p)\n", iface, pan);
 
        if (!(This->dsbd.dwFlags & DSBCAPS_CTRLPAN)) {
@@ -1049,39 +1028,20 @@ static HRESULT WINAPI PrimaryBufferImpl_GetPan(IDirectSoundBuffer *iface, LONG *
                return DSERR_INVALIDPARAM;
        }
 
-       EnterCriticalSection(&device->mixlock);
-
-       hr = IAudioStreamVolume_GetChannelVolume(device->volume, 0, &lvol);
-       if(FAILED(hr)){
-               LeaveCriticalSection(&device->mixlock);
-               WARN("GetChannelVolume failed: %08x\n", hr);
-               return hr;
-       }
-
-       if(device->pwfx->nChannels > 1){
-               hr = IAudioStreamVolume_GetChannelVolume(device->volume, 1, &rvol);
-               if(FAILED(hr)){
-                       LeaveCriticalSection(&device->mixlock);
-                       WARN("GetChannelVolume failed: %08x\n", hr);
-                       return hr;
-               }
-       }else
-               rvol = 1;
-
-       device->volpan.dwTotalLeftAmpFactor = ((UINT16)(lvol * (DWORD)0xFFFF));
-       device->volpan.dwTotalRightAmpFactor = ((UINT16)(rvol * (DWORD)0xFFFF));
-
-       DSOUND_AmpFactorToVolPan(&device->volpan);
+        if (!device->hwbuf)
+        {
+           waveOutGetVolume(device->hwo, &ampfactors);
+           device->volpan.dwTotalLeftAmpFactor=ampfactors & 0xffff;
+           device->volpan.dwTotalRightAmpFactor=ampfactors >> 16;
+           DSOUND_AmpFactorToVolPan(&device->volpan);
+        }
        *pan = device->volpan.lPan;
-
-       LeaveCriticalSection(&device->mixlock);
-
        return DS_OK;
 }
 
-static HRESULT WINAPI PrimaryBufferImpl_Unlock(IDirectSoundBuffer *iface, void *p1, DWORD x1,
-        void *p2, DWORD x2)
-{
+static HRESULT WINAPI PrimaryBufferImpl_Unlock(
+       LPDIRECTSOUNDBUFFER iface,LPVOID p1,DWORD x1,LPVOID p2,DWORD x2
+{
         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
         DirectSoundDevice *device = This->device;
        TRACE("(%p,%p,%d,%p,%d)\n", iface, p1, x1, p2, x2);
@@ -1091,22 +1051,34 @@ static HRESULT WINAPI PrimaryBufferImpl_Unlock(IDirectSoundBuffer *iface, void *
                return DSERR_PRIOLEVELNEEDED;
        }
 
-       if ((p1 && ((BYTE*)p1 < device->buffer || (BYTE*)p1 >= device->buffer + device->buflen)) ||
-           (p2 && ((BYTE*)p2 < device->buffer || (BYTE*)p2 >= device->buffer + device->buflen)))
-               return DSERR_INVALIDPARAM;
+       if (!(device->drvdesc.dwFlags & DSDDESC_DONTNEEDPRIMARYLOCK) && device->hwbuf) {
+               HRESULT hres;
+
+               if ((char *)p1 - (char *)device->buffer + x1 > device->buflen)
+                   hres = DSERR_INVALIDPARAM;
+               else
+                   hres = IDsDriverBuffer_Unlock(device->hwbuf, p1, x1, p2, x2);
+
+               if (hres != DS_OK) {
+                       WARN("IDsDriverBuffer_Unlock failed\n");
+                       return hres;
+               }
+       }
 
        return DS_OK;
 }
 
-static HRESULT WINAPI PrimaryBufferImpl_Restore(IDirectSoundBuffer *iface)
-{
+static HRESULT WINAPI PrimaryBufferImpl_Restore(
+       LPDIRECTSOUNDBUFFER iface
+) {
         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
        FIXME("(%p):stub\n",This);
        return DS_OK;
 }
 
-static HRESULT WINAPI PrimaryBufferImpl_GetFrequency(IDirectSoundBuffer *iface, DWORD *freq)
-{
+static HRESULT WINAPI PrimaryBufferImpl_GetFrequency(
+       LPDIRECTSOUNDBUFFER iface,LPDWORD freq
+) {
         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
         DirectSoundDevice *device = This->device;
        TRACE("(%p,%p)\n", iface, freq);
@@ -1127,16 +1099,17 @@ static HRESULT WINAPI PrimaryBufferImpl_GetFrequency(IDirectSoundBuffer *iface,
        return DS_OK;
 }
 
-static HRESULT WINAPI PrimaryBufferImpl_Initialize(IDirectSoundBuffer *iface, IDirectSound *dsound,
-        const DSBUFFERDESC *dbsd)
-{
+static HRESULT WINAPI PrimaryBufferImpl_Initialize(
+       LPDIRECTSOUNDBUFFER iface,LPDIRECTSOUND dsound,LPCDSBUFFERDESC dbsd
+{
         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
        WARN("(%p) already initialized\n", This);
        return DSERR_ALREADYINITIALIZED;
 }
 
-static HRESULT WINAPI PrimaryBufferImpl_GetCaps(IDirectSoundBuffer *iface, DSBCAPS *caps)
-{
+static HRESULT WINAPI PrimaryBufferImpl_GetCaps(
+       LPDIRECTSOUNDBUFFER iface,LPDSBCAPS caps
+) {
         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
         DirectSoundDevice *device = This->device;
        TRACE("(%p,%p)\n", iface, caps);
@@ -1161,11 +1134,11 @@ static HRESULT WINAPI PrimaryBufferImpl_GetCaps(IDirectSoundBuffer *iface, DSBCA
        return DS_OK;
 }
 
-static HRESULT WINAPI PrimaryBufferImpl_QueryInterface(IDirectSoundBuffer *iface, REFIID riid,
-        void **ppobj)
-{
+static HRESULT WINAPI PrimaryBufferImpl_QueryInterface(
+       LPDIRECTSOUNDBUFFER iface,REFIID riid,LPVOID *ppobj
+{
         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface);
-
+        DirectSoundDevice *device = This->device;
        TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppobj);
 
        if (ppobj == NULL) {
@@ -1177,8 +1150,8 @@ static HRESULT WINAPI PrimaryBufferImpl_QueryInterface(IDirectSoundBuffer *iface
 
        if ( IsEqualGUID(riid, &IID_IUnknown) ||
             IsEqualGUID(riid, &IID_IDirectSoundBuffer) ) {
-               IDirectSoundBuffer_AddRef(iface);
-               *ppobj = iface;
+               IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)This);
+               *ppobj = This;
                return S_OK;
        }
 
@@ -1201,15 +1174,21 @@ static HRESULT WINAPI PrimaryBufferImpl_QueryInterface(IDirectSoundBuffer *iface
        }
 
         if ( IsEqualGUID( &IID_IDirectSound3DListener, riid ) ) {
-                *ppobj = &This->IDirectSound3DListener_iface;
-                IDirectSound3DListener_AddRef(&This->IDirectSound3DListener_iface);
-                return S_OK;
+               if (!device->listener)
+                       IDirectSound3DListenerImpl_Create(device, &device->listener);
+               if (device->listener) {
+                       *ppobj = device->listener;
+                       IDirectSound3DListener_AddRef((LPDIRECTSOUND3DLISTENER)*ppobj);
+                       return S_OK;
+               }
+
+               WARN("IID_IDirectSound3DListener failed\n");
+               return E_NOINTERFACE;
        }
 
        if ( IsEqualGUID( &IID_IKsPropertySet, riid ) ) {
-                *ppobj = &This->IKsPropertySet_iface;
-                IKsPropertySet_AddRef(&This->IKsPropertySet_iface);
-                return S_OK;
+               FIXME("app requested IKsPropertySet on primary buffer\n");
+               return E_NOINTERFACE;
        }
 
        FIXME( "Unknown IID %s\n", debugstr_guid( riid ) );
@@ -1261,35 +1240,12 @@ HRESULT primarybuffer_create(DirectSoundDevice *device, IDirectSoundBufferImpl *
                return DSERR_OUTOFMEMORY;
        }
 
-        dsb->ref = 0;
-        dsb->ref3D = 0;
-        dsb->refiks = 0;
-        dsb->numIfaces = 0;
+        dsb->ref = 1;
+        dsb->numIfaces = 1;
        dsb->device = device;
        dsb->IDirectSoundBuffer8_iface.lpVtbl = (IDirectSoundBuffer8Vtbl *)&dspbvt;
-        dsb->IDirectSound3DListener_iface.lpVtbl = &ds3dlvt;
-        dsb->IKsPropertySet_iface.lpVtbl = &iksbvt;
        dsb->dsbd = *dsbd;
 
-        /* IDirectSound3DListener */
-        device->ds3dl.dwSize = sizeof(DS3DLISTENER);
-        device->ds3dl.vPosition.x = 0.0;
-        device->ds3dl.vPosition.y = 0.0;
-        device->ds3dl.vPosition.z = 0.0;
-        device->ds3dl.vVelocity.x = 0.0;
-        device->ds3dl.vVelocity.y = 0.0;
-        device->ds3dl.vVelocity.z = 0.0;
-        device->ds3dl.vOrientFront.x = 0.0;
-        device->ds3dl.vOrientFront.y = 0.0;
-        device->ds3dl.vOrientFront.z = 1.0;
-        device->ds3dl.vOrientTop.x = 0.0;
-        device->ds3dl.vOrientTop.y = 1.0;
-        device->ds3dl.vOrientTop.z = 0.0;
-        device->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
-        device->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
-        device->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
-        device->ds3dl_need_recalc = TRUE;
-
        TRACE("Created primary buffer at %p\n", dsb);
        TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
                "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
@@ -1298,7 +1254,6 @@ HRESULT primarybuffer_create(DirectSoundDevice *device, IDirectSoundBufferImpl *
                 device->pwfx->nBlockAlign, device->pwfx->wBitsPerSample,
                 device->pwfx->cbSize);
 
-        IDirectSoundBuffer_AddRef(&dsb->IDirectSoundBuffer8_iface);
        *ppdsb = dsb;
        return S_OK;
 }