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

Andrew Eikum aeikum at codeweavers.com
Tue May 28 13:39:51 CDT 2013


Fixes bug 32312.

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.
---
 dlls/dsound/primary.c      | 69 +++++++++++++++-------------------------------
 dlls/dsound/tests/dsound.c | 67 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 89 insertions(+), 47 deletions(-)

diff --git a/dlls/dsound/primary.c b/dlls/dsound/primary.c
index 0bfd5667..d940c16 100644
--- a/dlls/dsound/primary.c
+++ b/dlls/dsound/primary.c
@@ -440,35 +440,28 @@ 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->nBlockAlign = (pwfx->nChannels * pwfx->wBitsPerSample) / 8;
+    else if(pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
+             IsEqualGUID(&((const WAVEFORMATEXTENSIBLE*)pwfx)->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)){
+        pwfx->nBlockAlign = (pwfx->nChannels * pwfx->wBitsPerSample) / 8;
+        if(((WAVEFORMATEXTENSIBLE*)pwfx)->Samples.wValidBitsPerSample == 0)
+            ((WAVEFORMATEXTENSIBLE*)pwfx)->Samples.wValidBitsPerSample = pwfx->wBitsPerSample;
+    }
+
+    return pwfx;
 }
 
 HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX passed_fmt)
@@ -545,27 +538,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..fd88100 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,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, &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 == 16, "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 +1446,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, &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