[PATCH v4] dsound: create a primary_pwfx separately from pwfx

Maarten Lankhorst maarten.lankhorst at canonical.com
Fri Nov 16 13:35:51 CST 2012


I promised I would never touch it, but then I wanted to play skyrim

V2: Limit channels to 2 in primary if not in writeprimary mode
V3: Split off DSOUND_WaveFormat to its own function sooner.
V4: Fix accidental revert of device->buflen increase. It was supposed to wait until rework in patch 3.
---
diff --git a/dlls/dsound/dsound.c b/dlls/dsound/dsound.c
index e5b0e3c..ac85ba2 100644
--- a/dlls/dsound/dsound.c
+++ b/dlls/dsound/dsound.c
@@ -305,21 +305,36 @@ static HRESULT WINAPI IDirectSound8Impl_SetCooperativeLevel(IDirectSound8 *iface
         DWORD level)
 {
     IDirectSoundImpl *This = impl_from_IDirectSound8(iface);
+    DirectSoundDevice *device = This->device;
+    DWORD oldlevel;
+    HRESULT hr = S_OK;
 
     TRACE("(%p,%p,%s)\n", This, hwnd, dumpCooperativeLevel(level));
 
-    if (!This->device) {
+    if (!device) {
         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");
+             level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
     }
 
-    This->device->priolevel = level;
-    return DS_OK;
+    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);
+    }
+    LeaveCriticalSection(&device->mixlock);
+    RtlReleaseResource(&device->buffer_list_lock);
+    return hr;
 }
 
 static HRESULT WINAPI IDirectSound8Impl_Compact(IDirectSound8 *iface)
@@ -612,20 +627,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(WAVEFORMATEX));
-    if (device->pwfx == NULL) {
+    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) {
         WARN("out of memory\n");
+        HeapFree(GetProcessHeap(),0,device->primary_pwfx);
+        HeapFree(GetProcessHeap(),0,device->pwfx);
         HeapFree(GetProcessHeap(),0,device);
         return DSERR_OUTOFMEMORY;
     }
 
     device->pwfx->wFormatTag = WAVE_FORMAT_PCM;
-    device->pwfx->nSamplesPerSec = ds_default_sample_rate;
-    device->pwfx->wBitsPerSample = ds_default_bits_per_sample;
+    device->pwfx->nSamplesPerSec = 22050;
+    device->pwfx->wBitsPerSample = 8;
     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");
diff --git a/dlls/dsound/dsound_main.c b/dlls/dsound/dsound_main.c
index 3fded64..3c47423 100644
--- a/dlls/dsound/dsound_main.c
+++ b/dlls/dsound/dsound_main.c
@@ -93,8 +93,6 @@ WCHAR wine_vxd_drv[] = { 'w','i','n','e','m','m','.','v','x','d', 0 };
 /* All default settings, you most likely don't want to touch these, see wiki on UsefulRegistryKeys */
 int ds_hel_buflen = 32768 * 2;
 int ds_snd_queue_max = 10;
-int ds_default_sample_rate = 44100;
-int ds_default_bits_per_sample = 16;
 static HINSTANCE instance;
 
 /*
@@ -151,19 +149,11 @@ void setup_dsound_options(void)
         ds_snd_queue_max = 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_hel_buflen = %d\n", ds_hel_buflen);
     TRACE("ds_snd_queue_max = %d\n", ds_snd_queue_max);
-    TRACE("ds_default_sample_rate = %d\n", ds_default_sample_rate);
-    TRACE("ds_default_bits_per_sample = %d\n", ds_default_bits_per_sample);
 }
 
 static const char * get_device_id(LPCGUID pGuid)
diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h
index 247f229..62656a5 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -32,9 +32,6 @@
 
 extern int ds_hel_buflen DECLSPEC_HIDDEN;
 extern int ds_snd_queue_max DECLSPEC_HIDDEN;
-extern int ds_snd_shadow_maxsize DECLSPEC_HIDDEN;
-extern int ds_default_sample_rate DECLSPEC_HIDDEN;
-extern int ds_default_bits_per_sample DECLSPEC_HIDDEN;
 
 /*****************************************************************************
  * Predeclare the interface implementation structures
@@ -72,8 +69,8 @@ struct DirectSoundDevice
     GUID                        guid;
     DSCAPS                      drvcaps;
     DWORD                       priolevel;
-    PWAVEFORMATEX               pwfx;
-    UINT                        timerID, playing_offs_bytes, in_mmdev_bytes, prebuf, helfrags;
+    PWAVEFORMATEX               pwfx, primary_pwfx;
+    UINT                        timerID, playing_offs_bytes, in_mmdev_bytes, prebuf;
     DWORD                       fraglen;
     LPBYTE                      buffer;
     DWORD                       writelead, buflen, state, playpos, mixpos;
@@ -211,6 +208,7 @@ 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;
diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c
index 264d64d..84e029b 100644
--- a/dlls/dsound/mixer.c
+++ b/dlls/dsound/mixer.c
@@ -112,6 +112,7 @@ void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb)
 	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))))
diff --git a/dlls/dsound/primary.c b/dlls/dsound/primary.c
index 8da12e2..bf76dec 100644
--- a/dlls/dsound/primary.c
+++ b/dlls/dsound/primary.c
@@ -58,10 +58,99 @@ static DWORD DSOUND_fraglen(DirectSoundDevice *device)
     return ret;
 }
 
+static HRESULT DSOUND_WaveFormat(DirectSoundDevice *device, IAudioClient *client,
+				 BOOL forcewave, WAVEFORMATEX **wfx)
+{
+    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;
+        }
+
+        if (!IsEqualGUID(&mixwfe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) {
+            WAVEFORMATEXTENSIBLE testwfe = *mixwfe;
+
+            testwfe.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
+            testwfe.Format.wBitsPerSample = 32;
+            testwfe.Format.nBlockAlign = testwfe.Format.nChannels * testwfe.Format.wBitsPerSample / 8;
+            testwfe.Format.nAvgBytesPerSec = testwfe.Format.nSamplesPerSec * testwfe.Format.nBlockAlign;
+            testwfe.Samples.wValidBitsPerSample = 0;
+
+            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;
+        wfe->Samples.wValidBitsPerSample = 0;
+        if (wi->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) {
+            w->wBitsPerSample = 32;
+            wfe->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
+        } else
+            wfe->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
+    } 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;
+}
+
 HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave)
 {
     UINT prebuf_frames;
     REFERENCE_TIME prebuf_rt;
+    WAVEFORMATEX *wfx = NULL;
     HRESULT hres;
 
     TRACE("(%p, %d)\n", device, forcewave);
@@ -85,11 +174,20 @@ HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave)
 
     hres = IMMDevice_Activate(device->mmdevice, &IID_IAudioClient,
             CLSCTX_INPROC_SERVER, NULL, (void **)&device->client);
-    if(FAILED(hres)){
+    if(FAILED(hres)) {
         WARN("Activate failed: %08x\n", hres);
         return hres;
     }
 
+    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;
 
@@ -139,9 +237,11 @@ HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave)
     return S_OK;
 }
 
-static HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
+HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
 {
+	IDirectSoundBufferImpl** dsb = device->buffers;
 	LPBYTE newbuf;
+	DWORD i;
 
 	TRACE("(%p)\n", device);
 
@@ -157,9 +257,8 @@ static HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
 		device->buflen -= device->buflen % device->pwfx->nBlockAlign;
 	}
 
-	device->helfrags = device->buflen / device->fraglen;
-
-	device->mix_buffer_len = ((device->prebuf * device->fraglen) / (device->pwfx->wBitsPerSample / 8)) * sizeof(float);
+	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);
 	if (!device->mix_buffer)
 		return DSERR_OUTOFMEMORY;
@@ -183,8 +282,8 @@ static HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
 
     device->buffer = newbuf;
 
-    TRACE("buflen: %u, fraglen: %u, helfrags: %u, mix_buffer_len: %u\n",
-            device->buflen, device->fraglen, device->helfrags, device->mix_buffer_len);
+    TRACE("buflen: %u, fraglen: %u, mix_buffer_len: %u\n",
+            device->buflen, device->fraglen, device->mix_buffer_len);
 
     if(device->pwfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
             (device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
@@ -196,8 +295,22 @@ static HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
 
 	FillMemory(device->buffer, device->buflen, (device->pwfx->wBitsPerSample == 8) ? 128 : 0);
 	FillMemory(device->mix_buffer, device->mix_buffer_len, 0);
-	device->playing_offs_bytes = device->in_mmdev_bytes = device->playpos = device->mixpos = 0;
-	return DS_OK;
+	device->playpos = 0;
+
+    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];
+
+    for (i = 0; i < device->nrofbuffers; i++) {
+        RtlAcquireResourceExclusive(&dsb[i]->lock, TRUE);
+        DSOUND_RecalcFormat(dsb[i]);
+        RtlReleaseResource(&dsb[i]->lock);
+    }
+
+    return DS_OK;
 }
 
 
@@ -249,6 +362,7 @@ HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *device)
 	HeapFree(GetProcessHeap(), 0, device->primary);
 	device->primary = NULL;
 
+	HeapFree(GetProcessHeap(),0,device->primary_pwfx);
 	HeapFree(GetProcessHeap(),0,device->pwfx);
 	device->pwfx=NULL;
 
@@ -338,8 +452,7 @@ LPWAVEFORMATEX DSOUND_CopyFormat(LPCWAVEFORMATEX wfex)
 
 HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX passed_fmt)
 {
-	HRESULT err = DSERR_BUFFERLOST;
-	int i;
+	HRESULT err = S_OK;
 	WAVEFORMATEX *old_fmt;
 	WAVEFORMATEXTENSIBLE *fmtex, *passed_fmtex = (WAVEFORMATEXTENSIBLE*)passed_fmt;
 	BOOL forced = (device->priolevel == DSSCL_WRITEPRIMARY);
@@ -377,169 +490,68 @@ HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX passe
 	RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE);
 	EnterCriticalSection(&(device->mixlock));
 
-	old_fmt = device->pwfx;
-	device->pwfx = DSOUND_CopyFormat(passed_fmt);
-	fmtex = (WAVEFORMATEXTENSIBLE *)device->pwfx;
-	if (device->pwfx == NULL) {
-		device->pwfx = old_fmt;
-		old_fmt = NULL;
-		err = DSERR_OUTOFMEMORY;
-		goto done;
-	}
+	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;
+		}
 
-	if(device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE){
-		if(fmtex->Samples.wValidBitsPerSample == 0){
+		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;
 		}
-	}
-
-	DSOUND_PrimaryClose(device);
-
-	err = DSOUND_ReopenDevice(device, FALSE);
-	if(SUCCEEDED(err))
-		goto opened;
-
-	/* requested format failed, so try others */
-	if(device->pwfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT){
-		device->pwfx->wFormatTag = WAVE_FORMAT_PCM;
-		device->pwfx->wBitsPerSample = 32;
-		device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign;
-		device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8);
-
-		err = DSOUND_ReopenDevice(device, FALSE);
-		if(SUCCEEDED(err))
-			goto opened;
-	}
-
-	if(device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
-			 IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)){
-		fmtex->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
-		device->pwfx->wBitsPerSample = 32;
-		device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign;
-		device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8);
-
-		err = DSOUND_ReopenDevice(device, FALSE);
-		if(SUCCEEDED(err))
-			goto opened;
-	}
 
-	device->pwfx->wBitsPerSample = 32;
-	device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign;
-	device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8);
-	if(device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
-		fmtex->Samples.wValidBitsPerSample = device->pwfx->wBitsPerSample;
-	err = DSOUND_ReopenDevice(device, FALSE);
-	if(SUCCEEDED(err))
-		goto opened;
-
-	device->pwfx->wBitsPerSample = 16;
-	device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign;
-	device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8);
-	if(device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
-		fmtex->Samples.wValidBitsPerSample = device->pwfx->wBitsPerSample;
-	err = DSOUND_ReopenDevice(device, FALSE);
-	if(SUCCEEDED(err))
-		goto opened;
-
-	device->pwfx->wBitsPerSample = 8;
-	device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign;
-	device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8);
-	if(device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
-		fmtex->Samples.wValidBitsPerSample = device->pwfx->wBitsPerSample;
-	err = DSOUND_ReopenDevice(device, FALSE);
-	if(SUCCEEDED(err))
-		goto opened;
-
-	device->pwfx->nChannels = (passed_fmt->nChannels == 2) ? 1 : 2;
-	device->pwfx->wBitsPerSample = passed_fmt->wBitsPerSample;
-	device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign;
-	device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8);
-	if(device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
-		fmtex->Samples.wValidBitsPerSample = device->pwfx->wBitsPerSample;
-	err = DSOUND_ReopenDevice(device, FALSE);
-	if(SUCCEEDED(err))
-		goto opened;
-
-	device->pwfx->wBitsPerSample = 32;
-	device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign;
-	device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8);
-	if(device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
-		fmtex->Samples.wValidBitsPerSample = device->pwfx->wBitsPerSample;
-	err = DSOUND_ReopenDevice(device, FALSE);
-	if(SUCCEEDED(err))
-		goto opened;
-
-	device->pwfx->wBitsPerSample = 16;
-	device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign;
-	device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8);
-	if(device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
-		fmtex->Samples.wValidBitsPerSample = device->pwfx->wBitsPerSample;
-	err = DSOUND_ReopenDevice(device, FALSE);
-	if(SUCCEEDED(err))
-		goto opened;
-
-	device->pwfx->wBitsPerSample = 8;
-	device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign;
-	device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8);
-	if(device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
-		fmtex->Samples.wValidBitsPerSample = device->pwfx->wBitsPerSample;
-	err = DSOUND_ReopenDevice(device, FALSE);
-	if(SUCCEEDED(err))
-		goto opened;
-
-	WARN("No formats could be opened\n");
-	goto done;
-
-opened:
-	err = DSOUND_PrimaryOpen(device);
-	if (err != DS_OK) {
-		WARN("DSOUND_PrimaryOpen failed\n");
-		goto done;
-	}
-
-	if (passed_fmt->nSamplesPerSec/100 != device->pwfx->nSamplesPerSec/100 && forced && device->buffer)
-	{
 		DSOUND_PrimaryClose(device);
-		device->pwfx->nSamplesPerSec = passed_fmt->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);
-	}
-
 
-	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];
-
-	if (old_fmt->nSamplesPerSec != device->pwfx->nSamplesPerSec ||
-			old_fmt->wBitsPerSample != device->pwfx->wBitsPerSample ||
-			old_fmt->nChannels != device->pwfx->nChannels) {
-		IDirectSoundBufferImpl** dsb = device->buffers;
-		for (i = 0; i < device->nrofbuffers; i++, dsb++) {
-			/* **** */
-			RtlAcquireResourceExclusive(&(*dsb)->lock, TRUE);
+		err = DSOUND_ReopenDevice(device, forced);
+		if (FAILED(err)) {
+			ERR("No formats could be opened\n");
+			goto done;
+		}
 
-			(*dsb)->freqAdjust = (*dsb)->freq / (float)device->pwfx->nSamplesPerSec;
-			DSOUND_RecalcFormat((*dsb));
+		err = DSOUND_PrimaryOpen(device);
+		if (err != DS_OK) {
+			ERR("DSOUND_PrimaryOpen failed\n");
+			goto done;
+		}
 
-			RtlReleaseResource(&(*dsb)->lock);
-			/* **** */
+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;
 		}
+		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));
 	}
 
-done:
+out:
 	LeaveCriticalSection(&(device->mixlock));
 	RtlReleaseResource(&(device->buffer_list_lock));
 	/* **** */
 
-	HeapFree(GetProcessHeap(), 0, old_fmt);
 	return err;
 }
 
@@ -834,11 +846,11 @@ static HRESULT WINAPI PrimaryBufferImpl_GetFormat(IDirectSoundBuffer *iface, WAV
     DirectSoundDevice *device = This->device;
     TRACE("(%p,%p,%d,%p)\n", iface, lpwf, wfsize, wfwritten);
 
-    size = sizeof(WAVEFORMATEX) + device->pwfx->cbSize;
+    size = sizeof(WAVEFORMATEX) + device->primary_pwfx->cbSize;
 
     if (lpwf) {	/* NULL is valid */
         if (wfsize >= size) {
-            CopyMemory(lpwf,device->pwfx,size);
+            CopyMemory(lpwf,device->primary_pwfx,size);
             if (wfwritten)
                 *wfwritten = size;
         } else {
@@ -849,7 +861,7 @@ static HRESULT WINAPI PrimaryBufferImpl_GetFormat(IDirectSoundBuffer *iface, WAV
         }
     } else {
         if (wfwritten)
-            *wfwritten = sizeof(WAVEFORMATEX) + device->pwfx->cbSize;
+            *wfwritten = sizeof(WAVEFORMATEX) + device->primary_pwfx->cbSize;
         else {
             WARN("invalid parameter: wfwritten == NULL\n");
             return DSERR_INVALIDPARAM;




More information about the wine-patches mailing list