[PATCH] dsound: Use smaller buffers for wavein capture

Maarten Lankhorst maarten at codeweavers.com
Fri Sep 28 18:54:03 CDT 2007


---
 dlls/dsound/capture.c        |  195 ++++++++++++++++-------------------------
 dlls/dsound/dsound_private.h |    2 +-
 dlls/dsound/primary.c        |   54 +++++++-----
 3 files changed, 108 insertions(+), 143 deletions(-)

diff --git a/dlls/dsound/capture.c b/dlls/dsound/capture.c
index 684495d..a949673 100644
--- a/dlls/dsound/capture.c
+++ b/dlls/dsound/capture.c
@@ -384,6 +384,31 @@ DirectSoundCaptureEnumerateW(
     return DS_OK;
 }
 
+static void capture_CheckNotify(IDirectSoundCaptureBufferImpl *This, DWORD from, DWORD len)
+{
+    unsigned i;
+    for (i = 0; i < This->nrofnotifies; ++i) {
+        LPDSBPOSITIONNOTIFY event = This->notifies + i;
+        DWORD offset = event->dwOffset;
+        TRACE("checking %d, position %d, event = %p\n", i, offset, event->hEventNotify);
+
+        if (offset == DSBPN_OFFSETSTOP) {
+            if (!from && !len) {
+                SetEvent(event->hEventNotify);
+                TRACE("signalled event %p (%d)\n", event->hEventNotify, i);
+                return;
+            }
+            else return;
+        }
+
+        if (offset >= from && offset < (from + len))
+        {
+            TRACE("signalled event %p (%d)\n", event->hEventNotify, i);
+            SetEvent(event->hEventNotify);
+        }
+    }
+}
+
 static void CALLBACK
 DSOUND_capture_callback(
     HWAVEIN hwi,
@@ -393,27 +418,25 @@ DSOUND_capture_callback(
     DWORD dw2 )
 {
     DirectSoundCaptureDevice * This = (DirectSoundCaptureDevice*)dwUser;
+    IDirectSoundCaptureBufferImpl * Moi = (IDirectSoundCaptureBufferImpl*) This->capture_buffer;
     TRACE("(%p,%08x(%s),%08x,%08x,%08x) entering at %d\n",hwi,msg,
 	msg == MM_WIM_OPEN ? "MM_WIM_OPEN" : msg == MM_WIM_CLOSE ? "MM_WIM_CLOSE" :
 	msg == MM_WIM_DATA ? "MM_WIM_DATA" : "UNKNOWN",dwUser,dw1,dw2,GetTickCount());
 
     if (msg == MM_WIM_DATA) {
-        LPWAVEHDR pHdr = (LPWAVEHDR)dw1;
     	EnterCriticalSection( &(This->lock) );
 	TRACE("DirectSoundCapture msg=MM_WIM_DATA, old This->state=%s, old This->index=%d\n",
 	    captureStateString[This->state],This->index);
 	if (This->state != STATE_STOPPED) {
 	    int index = This->index;
-	    if (This->state == STATE_STARTING) {
-                This->read_position = pHdr->dwBytesRecorded;
+	    if (This->state == STATE_STARTING)
 		This->state = STATE_CAPTURING;
-	    }
-	    if (This->capture_buffer->nrofnotifies)
-		SetEvent(This->capture_buffer->notifies[This->index].hEventNotify);
-	    This->index = (This->index + 1) % This->nrofpwaves;
+	    capture_CheckNotify(Moi, (DWORD_PTR)This->pwave[index].lpData - (DWORD_PTR)This->buffer, This->pwave[index].dwBufferLength);
+	    This->index = (++This->index) % This->nrofpwaves;
 	    if ( (This->index == 0) && !(This->capture_buffer->flags & DSCBSTART_LOOPING) ) {
 		TRACE("end of buffer\n");
 		This->state = STATE_STOPPED;
+		capture_CheckNotify(Moi, 0, 0);
 	    } else {
 		if (This->state == STATE_CAPTURING) {
 		    waveInAddBuffer(hwi, &(This->pwave[index]), sizeof(WAVEHDR));
@@ -574,7 +597,6 @@ HRESULT WINAPI IDirectSoundCaptureImpl_Initialize(
 	WARN("already initialized\n");
 	return DSERR_ALREADYINITIALIZED;
     }
-
     return DirectSoundCaptureDevice_Initialize(&This->device, lpcGUID);
 }
 
@@ -895,28 +917,18 @@ IDirectSoundCaptureBufferImpl_GetCurrentPosition(
 	if (hres != DS_OK)
 	    WARN("IDsCaptureDriverBuffer_GetPosition failed\n");
     } else if (This->device->hwi) {
+	DWORD pos;
+
+	EnterCriticalSection(&This->device->lock);
+	pos = (DWORD_PTR)This->device->pwave[This->device->index].lpData - (DWORD_PTR)This->device->buffer;
 	TRACE("old This->device->state=%s\n",captureStateString[This->device->state]);
-        if (lpdwCapturePosition) {
-            MMTIME mtime;
-            mtime.wType = TIME_BYTES;
-            waveInGetPosition(This->device->hwi, &mtime, sizeof(mtime));
-            TRACE("mtime.u.cb=%d,This->device->buflen=%d\n", mtime.u.cb,
-		This->device->buflen);
-	    mtime.u.cb = mtime.u.cb % This->device->buflen;
-            *lpdwCapturePosition = mtime.u.cb;
-        }
+        if (lpdwCapturePosition)
+            *lpdwCapturePosition = pos;
+
+	if (lpdwReadPosition)
+            *lpdwReadPosition = (This->device->pwave[This->device->index].dwBufferLength + pos) % This->device->buflen;
+	LeaveCriticalSection(&This->device->lock);
 
-	EnterCriticalSection(&(This->device->lock));
-	if (lpdwReadPosition) {
-            if (This->device->state == STATE_STARTING) {
-		if (lpdwCapturePosition)
-		    This->device->read_position = *lpdwCapturePosition;
-                This->device->state = STATE_CAPTURING;
-            }
-            *lpdwReadPosition = This->device->read_position;
-        }
-	TRACE("new This->device->state=%s\n",captureStateString[This->device->state]);
-	LeaveCriticalSection(&(This->device->lock));
 	if (lpdwCapturePosition) TRACE("*lpdwCapturePosition=%d\n",*lpdwCapturePosition);
 	if (lpdwReadPosition) TRACE("*lpdwReadPosition=%d\n",*lpdwReadPosition);
     } else {
@@ -1122,99 +1134,47 @@ IDirectSoundCaptureBufferImpl_Start(
         DirectSoundCaptureDevice *device = This->device;
 
         if (device->buffer) {
-            if (This->nrofnotifies) {
-            	int c;
-
-		device->nrofpwaves = This->nrofnotifies;
-		TRACE("nrofnotifies=%d\n", This->nrofnotifies);
-
-                /* prepare headers */
-		if (device->pwave)
-                    device->pwave = HeapReAlloc(GetProcessHeap(),0,device->pwave,
-	                device->nrofpwaves*sizeof(WAVEHDR));
-		else
-                    device->pwave = HeapAlloc(GetProcessHeap(),0,
-	                device->nrofpwaves*sizeof(WAVEHDR));
-
-                for (c = 0; c < device->nrofpwaves; c++) {
-                    if (This->notifies[c].dwOffset == DSBPN_OFFSETSTOP) {
-                        TRACE("got DSBPN_OFFSETSTOP\n");
-                        device->nrofpwaves = c;
-                        break;
-                    }
-                    if (c == 0) {
-                        device->pwave[0].lpData = (LPSTR)device->buffer;
-                        device->pwave[0].dwBufferLength =
-                            This->notifies[0].dwOffset + 1;
-                    } else {
-                        device->pwave[c].lpData = (LPSTR)device->buffer +
-                            This->notifies[c-1].dwOffset + 1;
-                        device->pwave[c].dwBufferLength =
-                            This->notifies[c].dwOffset -
-                            This->notifies[c-1].dwOffset;
-                    }
-                    device->pwave[c].dwBytesRecorded = 0;
-                    device->pwave[c].dwUser = (DWORD)device;
-                    device->pwave[c].dwFlags = 0;
-                    device->pwave[c].dwLoops = 0;
-                    hres = mmErr(waveInPrepareHeader(device->hwi,
-                        &(device->pwave[c]),sizeof(WAVEHDR)));
-		    if (hres != DS_OK) {
-                        WARN("waveInPrepareHeader failed\n");
-			while (c--)
-			    waveInUnprepareHeader(device->hwi,
-				&(device->pwave[c]),sizeof(WAVEHDR));
-			break;
-		    }
-
-	            hres = mmErr(waveInAddBuffer(device->hwi,
-			&(device->pwave[c]), sizeof(WAVEHDR)));
-		    if (hres != DS_OK) {
-                        WARN("waveInAddBuffer failed\n");
-                        while (c--)
-			    waveInUnprepareHeader(device->hwi,
-				&(device->pwave[c]),sizeof(WAVEHDR));
-			break;
-		    }
+            int c;
+            DWORD blocksize = DSOUND_fraglen(device->pwfx->nSamplesPerSec, device->pwfx->nBlockAlign);
+            device->nrofpwaves = device->buflen / blocksize + !!(device->buflen % blocksize);
+            TRACE("nrofpwaves=%d\n", device->nrofpwaves);
+
+            /* prepare headers */
+            if (device->pwave)
+                device->pwave = HeapReAlloc(GetProcessHeap(), 0,device->pwave, device->nrofpwaves*sizeof(WAVEHDR));
+            else
+                device->pwave = HeapAlloc(GetProcessHeap(), 0, device->nrofpwaves*sizeof(WAVEHDR));
+
+            for (c = 0; c < device->nrofpwaves; ++c) {
+                device->pwave[c].lpData = (char *)device->buffer + c * blocksize;
+                device->pwave[c].dwBufferLength = blocksize;
+                device->pwave[c].dwBytesRecorded = 0;
+                device->pwave[c].dwUser = (DWORD)device;
+                device->pwave[c].dwFlags = 0;
+                device->pwave[c].dwLoops = 0;
+                hres = mmErr(waveInPrepareHeader(device->hwi, &(device->pwave[c]),sizeof(WAVEHDR)));
+                if (hres != DS_OK) {
+                    WARN("waveInPrepareHeader failed\n");
+                    while (c--)
+                        waveInUnprepareHeader(device->hwi, &(device->pwave[c]),sizeof(WAVEHDR));
+                    break;
                 }
 
-                FillMemory(device->buffer, device->buflen,
-                    (device->pwfx->wBitsPerSample == 8) ? 128 : 0);
-            } else {
-		TRACE("no notifiers specified\n");
-		/* no notifiers specified so just create a single default header */
-		device->nrofpwaves = 1;
-		if (device->pwave)
-                    device->pwave = HeapReAlloc(GetProcessHeap(),0,device->pwave,sizeof(WAVEHDR));
-		else
-                    device->pwave = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEHDR));
-
-                device->pwave[0].lpData = (LPSTR)device->buffer;
-                device->pwave[0].dwBufferLength = device->buflen;
-                device->pwave[0].dwBytesRecorded = 0;
-                device->pwave[0].dwUser = (DWORD)device;
-                device->pwave[0].dwFlags = 0;
-                device->pwave[0].dwLoops = 0;
-
-                hres = mmErr(waveInPrepareHeader(device->hwi,
-                    &(device->pwave[0]),sizeof(WAVEHDR)));
+                hres = mmErr(waveInAddBuffer(device->hwi, &(device->pwave[c]), sizeof(WAVEHDR)));
                 if (hres != DS_OK) {
-		    WARN("waveInPrepareHeader failed\n");
-                    waveInUnprepareHeader(device->hwi,
-                        &(device->pwave[0]),sizeof(WAVEHDR));
-		}
-	        hres = mmErr(waveInAddBuffer(device->hwi,
-		    &(device->pwave[0]), sizeof(WAVEHDR)));
-		if (hres != DS_OK) {
-		    WARN("waveInAddBuffer failed\n");
-	    	    waveInUnprepareHeader(device->hwi,
-			&(device->pwave[0]),sizeof(WAVEHDR));
-		}
-	    }
+                    WARN("waveInAddBuffer failed\n");
+                    while (c--)
+                        waveInUnprepareHeader(device->hwi, &(device->pwave[c]),sizeof(WAVEHDR));
+                    break;
+                }
+            }
+            if (device->buflen % blocksize)
+                device->pwave[device->nrofpwaves - 1].dwBufferLength = device->buflen % blocksize;
+
+            FillMemory(device->buffer, device->buflen, (device->pwfx->wBitsPerSample == 8) ? 128 : 0);
         }
 
         device->index = 0;
-        device->read_position = 0;
 
 	if (hres == DS_OK) {
 	    /* start filling the first buffer */
@@ -1300,10 +1260,7 @@ IDirectSoundCaptureBufferImpl_Unlock(
                                              dwAudioBytes1, lpvAudioPtr2, dwAudioBytes2);
 	if (hres != DS_OK)
 	    WARN("IDsCaptureDriverBuffer_Unlock failed\n");
-    } else if (This->device->hwi) {
-        This->device->read_position = (This->device->read_position +
-            (dwAudioBytes1 + dwAudioBytes2)) % This->device->buflen;
-    } else {
+    } else if (!This->device->hwi) {
         WARN("invalid call\n");
         hres = DSERR_INVALIDCALL;
     }
diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h
index dc21a62..33f9265 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -253,7 +253,6 @@ struct DirectSoundCaptureDevice
     /* more stuff */
     LPBYTE                             buffer;
     DWORD                              buflen;
-    DWORD                              read_position;
 
     PWAVEFORMATEX                      pwfx;
 
@@ -420,6 +419,7 @@ HRESULT DSOUND_Create8(REFIID riid, LPDIRECTSOUND8 *ppDS);
 
 /* primary.c */
 
+DWORD DSOUND_fraglen(DWORD nSamplesPerSec, DWORD nBlockAlign);
 HRESULT DSOUND_PrimaryCreate(DirectSoundDevice *device);
 HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *device);
 HRESULT DSOUND_PrimaryPlay(DirectSoundDevice *device);
diff --git a/dlls/dsound/primary.c b/dlls/dsound/primary.c
index 359a5ac..615b6f2 100644
--- a/dlls/dsound/primary.c
+++ b/dlls/dsound/primary.c
@@ -36,36 +36,44 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
 
-static void DSOUND_RecalcPrimary(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)
 {
-	DWORD nBlockAlign;
-	DWORD fraglen;
-	TRACE("(%p)\n", device);
+    DWORD fraglen = 512 * nBlockAlign;
 
-	nBlockAlign = device->pwfx->nBlockAlign;
-	/* Alsa doesn't have continuous buffers, instead it has buffers with power of 2,
-	 * If DS_TIME_DEL is about 10 ms, 512 * nBlockAlign is roughly correct */
-	fraglen = 512 * nBlockAlign;
+    /* Compensate for only being roughly accurate */
+    if (nSamplesPerSec <= 26000)
+        fraglen /= 2;
 
-	/* Compensate for only being roughly accurate */
-	if (device->pwfx->nSamplesPerSec <= 26000)
-		fraglen /= 2;
+    if (nSamplesPerSec <= 12000)
+        fraglen /= 2;
 
-	if (device->pwfx->nSamplesPerSec <= 12000)
-		fraglen /= 2;
+    if (nSamplesPerSec >= 80000)
+        fraglen *= 2;
 
-	if (device->pwfx->nSamplesPerSec >= 80000)
-		fraglen *= 2;
+    return fraglen;
+}
+
+static void DSOUND_RecalcPrimary(DirectSoundDevice *device)
+{
+    TRACE("(%p)\n", device);
 
-	device->fraglen = fraglen;
-	device->helfrags = device->buflen / fraglen;
-	TRACE("fraglen=%d helfrags=%d\n", device->fraglen, device->helfrags);
+    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) * nBlockAlign;
+    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)
-- 
1.5.2.5


--------------020109060905020301060405--



More information about the wine-patches mailing list