From 3bafbb22b80c09ff661b283d81615b5fbf2f9388 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Sat, 29 Sep 2007 01:54:03 +0200 Subject: [PATCH] dsound: Use smaller buffers for wavein capture. --- 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 684495d6249..a9496737a87 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 dc21a628069..33f9265482b 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 359a5ac5777..615b6f28367 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) -- 2.11.4.GIT