[PATCH (try 2)] dsound: Copy SetFormat format more directly if we're not in PRIMARYWRITE mode

Andrew Eikum aeikum at codeweavers.com
Tue May 28 14:05:47 CDT 2013


User applications don't have any access to the primary buffer's data, so
it doesn't actually matter what the true format is. Some applications
like SNES9x depend on the result of GetFormat() matching the format
given to SetFormat(), so just copy the user's format.

---
Fixes bug 32312

try 2: Fix test failures on <=XP, and modify patch to match <=XP
  behavior

 dlls/dsound/primary.c      | 65 ++++++++++++-------------------------------
 dlls/dsound/tests/dsound.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 87 insertions(+), 47 deletions(-)

diff --git a/dlls/dsound/primary.c b/dlls/dsound/primary.c
index 0bfd5667..a824477 100644
--- a/dlls/dsound/primary.c
+++ b/dlls/dsound/primary.c
@@ -440,35 +440,24 @@ HRESULT DSOUND_PrimaryGetPosition(DirectSoundDevice *device, LPDWORD playpos, LP
 	return DS_OK;
 }
 
-static DWORD DSOUND_GetFormatSize(LPCWAVEFORMATEX wfex)
+WAVEFORMATEX *DSOUND_CopyFormat(const WAVEFORMATEX *wfex)
 {
-	if (wfex->wFormatTag == WAVE_FORMAT_PCM)
-		return sizeof(WAVEFORMATEX);
-	else
-		return sizeof(WAVEFORMATEX) + wfex->cbSize;
-}
+    WAVEFORMATEX *pwfx;
+    if(wfex->wFormatTag == WAVE_FORMAT_PCM){
+        pwfx = HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEFORMATEX));
+        CopyMemory(pwfx, wfex, sizeof(PCMWAVEFORMAT));
+        pwfx->cbSize = 0;
+    }else{
+        pwfx = HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEFORMATEX) + wfex->cbSize);
+        CopyMemory(pwfx, wfex, sizeof(WAVEFORMATEX) + wfex->cbSize);
+    }
 
-LPWAVEFORMATEX DSOUND_CopyFormat(LPCWAVEFORMATEX wfex)
-{
-	DWORD size = DSOUND_GetFormatSize(wfex);
-	LPWAVEFORMATEX pwfx = HeapAlloc(GetProcessHeap(),0,size);
-	if (pwfx == NULL) {
-		WARN("out of memory\n");
-	} else if (wfex->wFormatTag != WAVE_FORMAT_PCM) {
-		CopyMemory(pwfx, wfex, size);
-	} else {
-		CopyMemory(pwfx, wfex, sizeof(PCMWAVEFORMAT));
-		pwfx->cbSize=0;
-		if (pwfx->nBlockAlign != pwfx->nChannels * pwfx->wBitsPerSample/8) {
-			WARN("Fixing bad nBlockAlign (%u)\n", pwfx->nBlockAlign);
-			pwfx->nBlockAlign  = pwfx->nChannels * pwfx->wBitsPerSample/8;
-		}
-		if (pwfx->nAvgBytesPerSec != pwfx->nSamplesPerSec * pwfx->nBlockAlign) {
-			WARN("Fixing bad nAvgBytesPerSec (%u)\n", pwfx->nAvgBytesPerSec);
-			pwfx->nAvgBytesPerSec  = pwfx->nSamplesPerSec * pwfx->nBlockAlign;
-		}
-	}
-	return pwfx;
+    if(pwfx->wFormatTag == WAVE_FORMAT_PCM ||
+            (pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
+             IsEqualGUID(&((const WAVEFORMATEXTENSIBLE*)pwfx)->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)))
+        pwfx->nBlockAlign = (pwfx->nChannels * pwfx->wBitsPerSample) / 8;
+
+    return pwfx;
 }
 
 HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX passed_fmt)
@@ -545,27 +534,9 @@ done:
 			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));
+		HeapFree(GetProcessHeap(), 0, device->primary_pwfx);
+		device->primary_pwfx = DSOUND_CopyFormat(passed_fmt);
 	}
 
 out:
diff --git a/dlls/dsound/tests/dsound.c b/dlls/dsound/tests/dsound.c
index 4291e7a..bca0d76 100644
--- a/dlls/dsound/tests/dsound.c
+++ b/dlls/dsound/tests/dsound.c
@@ -1348,6 +1348,15 @@ static HRESULT test_invalid_fmts(LPGUID lpGuid)
         rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
         ok(rc == S_OK, "SetFormat: %08x\n", rc);
 
+        rc = IDirectSoundBuffer_GetFormat(primary, &wfx, sizeof(wfx), NULL);
+        ok(rc == S_OK, "GetFormat: %08x\n", rc);
+        ok(wfx.wFormatTag == WAVE_FORMAT_PCM, "format: 0x%x\n", wfx.wFormatTag);
+        ok(wfx.nChannels == 2, "channels: %u\n", wfx.nChannels);
+        ok(wfx.nSamplesPerSec == 44100, "rate: %u\n", wfx.nSamplesPerSec);
+        ok(wfx.wBitsPerSample == 16, "bps: %u\n", wfx.wBitsPerSample);
+        ok(wfx.nBlockAlign == 4, "blockalign: %u\n", wfx.nBlockAlign);
+        ok(wfx.nAvgBytesPerSec == 44100 * 4 + 1, "avgbytes: %u\n", wfx.nAvgBytesPerSec);
+
         wfx.nChannels = 2;
         wfx.nSamplesPerSec = 44100;
         wfx.wBitsPerSample = 16;
@@ -1356,6 +1365,15 @@ static HRESULT test_invalid_fmts(LPGUID lpGuid)
         rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
         ok(rc == S_OK, "SetFormat: %08x\n", rc);
 
+        rc = IDirectSoundBuffer_GetFormat(primary, &wfx, sizeof(wfx), NULL);
+        ok(rc == S_OK, "GetFormat: %08x\n", rc);
+        ok(wfx.wFormatTag == WAVE_FORMAT_PCM, "format: 0x%x\n", wfx.wFormatTag);
+        ok(wfx.nChannels == 2, "channels: %u\n", wfx.nChannels);
+        ok(wfx.nSamplesPerSec == 44100, "rate: %u\n", wfx.nSamplesPerSec);
+        ok(wfx.wBitsPerSample == 16, "bps: %u\n", wfx.wBitsPerSample);
+        ok(wfx.nBlockAlign == 4, "blockalign: %u\n", wfx.nBlockAlign);
+        ok(wfx.nAvgBytesPerSec == 44100 * 4 - 1, "avgbytes: %u\n", wfx.nAvgBytesPerSec);
+
         wfx.nChannels = 2;
         wfx.nSamplesPerSec = 44100;
         wfx.wBitsPerSample = 16;
@@ -1364,6 +1382,33 @@ static HRESULT test_invalid_fmts(LPGUID lpGuid)
         rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
         ok(rc == S_OK, "SetFormat: %08x\n", rc);
 
+        rc = IDirectSoundBuffer_GetFormat(primary, &wfx, sizeof(wfx), NULL);
+        ok(rc == S_OK, "GetFormat: %08x\n", rc);
+        ok(wfx.wFormatTag == WAVE_FORMAT_PCM, "format: 0x%x\n", wfx.wFormatTag);
+        ok(wfx.nChannels == 2, "channels: %u\n", wfx.nChannels);
+        ok(wfx.nSamplesPerSec == 44100, "rate: %u\n", wfx.nSamplesPerSec);
+        ok(wfx.wBitsPerSample == 16, "bps: %u\n", wfx.wBitsPerSample);
+        ok(wfx.nBlockAlign == 4, "blockalign: %u\n", wfx.nBlockAlign);
+        ok(wfx.nAvgBytesPerSec == 44100 * 4 + 1, "avgbytes: %u\n", wfx.nAvgBytesPerSec);
+
+        wfx.wFormatTag = WAVE_FORMAT_ALAW;
+        wfx.nChannels = 2;
+        wfx.nSamplesPerSec = 44100;
+        wfx.wBitsPerSample = 16;
+        wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
+        wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
+        rc = IDirectSoundBuffer_SetFormat(primary, &wfx);
+        ok(rc == S_OK, "SetFormat: %08x\n", rc);
+
+        rc = IDirectSoundBuffer_GetFormat(primary, &wfx, sizeof(wfx), NULL);
+        ok(rc == S_OK, "GetFormat: %08x\n", rc);
+        ok(wfx.wFormatTag == WAVE_FORMAT_ALAW, "format: 0x%x\n", wfx.wFormatTag);
+        ok(wfx.nChannels == 2, "channels: %u\n", wfx.nChannels);
+        ok(wfx.nSamplesPerSec == 44100, "rate: %u\n", wfx.nSamplesPerSec);
+        ok(wfx.wBitsPerSample == 16, "bps: %u\n", wfx.wBitsPerSample);
+        ok(wfx.nBlockAlign == 4, "blockalign: %u\n", wfx.nBlockAlign);
+        ok(wfx.nAvgBytesPerSec == 44100 * 4, "avgbytes: %u\n", wfx.nAvgBytesPerSec);
+
         fmtex.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
         fmtex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
         fmtex.Format.nChannels = 2;
@@ -1377,6 +1422,19 @@ static HRESULT test_invalid_fmts(LPGUID lpGuid)
         rc = IDirectSoundBuffer_SetFormat(primary, (WAVEFORMATEX*)&fmtex);
         ok(rc == S_OK, "SetFormat: %08x\n", rc);
 
+        rc = IDirectSoundBuffer_GetFormat(primary, (WAVEFORMATEX*)&fmtex, sizeof(fmtex), NULL);
+        ok(rc == S_OK, "GetFormat: %08x\n", rc);
+        ok(fmtex.Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE, "format: 0x%x\n", fmtex.Format.wFormatTag);
+        ok(fmtex.Format.nChannels == 2, "channels: %u\n", fmtex.Format.nChannels);
+        ok(fmtex.Format.nSamplesPerSec == 44100, "rate: %u\n", fmtex.Format.nSamplesPerSec);
+        ok(fmtex.Format.wBitsPerSample == 16, "bps: %u\n", fmtex.Format.wBitsPerSample);
+        ok(fmtex.Format.nBlockAlign == 4, "blockalign: %u\n", fmtex.Format.nBlockAlign);
+        ok(fmtex.Format.nAvgBytesPerSec == 44100 * 4, "avgbytes: %u\n", fmtex.Format.nAvgBytesPerSec);
+        ok(fmtex.Samples.wValidBitsPerSample == 0 || /* <= XP */
+                fmtex.Samples.wValidBitsPerSample == 16, /* >= Vista */
+                "validbits: %u\n", fmtex.Samples.wValidBitsPerSample);
+        ok(IsEqualGUID(&fmtex.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM), "subtype incorrect\n");
+
         fmtex.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
         fmtex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
         fmtex.Format.nChannels = 2;
@@ -1390,6 +1448,17 @@ static HRESULT test_invalid_fmts(LPGUID lpGuid)
         rc = IDirectSoundBuffer_SetFormat(primary, (WAVEFORMATEX*)&fmtex);
         ok(rc == S_OK, "SetFormat: %08x\n", rc);
 
+        rc = IDirectSoundBuffer_GetFormat(primary, (WAVEFORMATEX*)&fmtex, sizeof(fmtex), NULL);
+        ok(rc == S_OK, "GetFormat: %08x\n", rc);
+        ok(fmtex.Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE, "format: 0x%x\n", fmtex.Format.wFormatTag);
+        ok(fmtex.Format.nChannels == 2, "channels: %u\n", fmtex.Format.nChannels);
+        ok(fmtex.Format.nSamplesPerSec == 44100, "rate: %u\n", fmtex.Format.nSamplesPerSec);
+        ok(fmtex.Format.wBitsPerSample == 24, "bps: %u\n", fmtex.Format.wBitsPerSample);
+        ok(fmtex.Format.nBlockAlign == 6, "blockalign: %u\n", fmtex.Format.nBlockAlign);
+        ok(fmtex.Format.nAvgBytesPerSec == 44100 * 6, "avgbytes: %u\n", fmtex.Format.nAvgBytesPerSec);
+        ok(fmtex.Samples.wValidBitsPerSample == 20, "validbits: %u\n", fmtex.Samples.wValidBitsPerSample);
+        ok(IsEqualGUID(&fmtex.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM), "subtype incorrect\n");
+
         fmtex.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
         fmtex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
         fmtex.Format.nChannels = 2;
-- 
1.8.3




More information about the wine-patches mailing list