Author: silverblade
Date: Mon Jul 7 17:59:45 2008
New Revision: 34360
URL: http://svn.reactos.org/svn/reactos?rev=34360&view=rev
Log:
Wave buffers are now split up into chunks before being fed to the sound driver.
Testing by writing 65,536 bytes using an un-even block size of 16,383. Results
in 4 x 16,383 byte blocks and 1 x 4 byte block, as expected. Completion of
one buffer results in submission of the next. Doesn't handle multiple WAVEHDRs
yet.
Modified:
branches/silverblade-audio/include/reactos/libs/sound/mmebuddy.h
branches/silverblade-audio/lib/drivers/sound/mmebuddy/thread.c
branches/silverblade-audio/lib/drivers/sound/mmebuddy/wave/wavethread.c
Modified: branches/silverblade-audio/include/reactos/libs/sound/mmebuddy.h
URL: http://svn.reactos.org/svn/reactos/branches/silverblade-audio/include/react…
==============================================================================
--- branches/silverblade-audio/include/reactos/libs/sound/mmebuddy.h [iso-8859-1] (original)
+++ branches/silverblade-audio/include/reactos/libs/sound/mmebuddy.h [iso-8859-1] Mon Jul 7 17:59:45 2008
@@ -169,7 +169,8 @@
PWAVEHDR FirstBuffer;
PWAVEHDR LastBuffer;
- /*DWORD RemainingBytes;*/
+ /* How much data is waiting with the driver */
+ DWORD RemainingBytes;
} WAVE_THREAD_DATA, *PWAVE_THREAD_DATA;
/*
Modified: branches/silverblade-audio/lib/drivers/sound/mmebuddy/thread.c
URL: http://svn.reactos.org/svn/reactos/branches/silverblade-audio/lib/drivers/s…
==============================================================================
--- branches/silverblade-audio/lib/drivers/sound/mmebuddy/thread.c [iso-8859-1] (original)
+++ branches/silverblade-audio/lib/drivers/sound/mmebuddy/thread.c [iso-8859-1] Mon Jul 7 17:59:45 2008
@@ -12,6 +12,11 @@
4 July 2008 - Created
5 July 2008 - Implemented basic request processing
6 July 2008 - Added I/O completion handling
+
+ Possible improvements:
+ Spawn *one* thread to deal with requests and I/O completion, rather
+ than have a thread per sound device instance. This wouldn't be too
+ hard to do but not worth doing right now.
*/
/*
Modified: branches/silverblade-audio/lib/drivers/sound/mmebuddy/wave/wavethread.c
URL: http://svn.reactos.org/svn/reactos/branches/silverblade-audio/lib/drivers/s…
==============================================================================
--- branches/silverblade-audio/lib/drivers/sound/mmebuddy/wave/wavethread.c [iso-8859-1] (original)
+++ branches/silverblade-audio/lib/drivers/sound/mmebuddy/wave/wavethread.c [iso-8859-1] Mon Jul 7 17:59:45 2008
@@ -23,23 +23,97 @@
/*
- Just a neat wrapper around the writing routine.
-*/
-
-MMRESULT
-WriteWaveBufferToSoundDevice(
+ How much we can feed to the driver at a time.
+ This is deliberately set low at the moment for testing purposes, and
+ intentionally set to be "one out" from 16384 so that writing 65536 bytes
+ results in 4x16383 byte buffers followed by 1x4 byte buffer.
+
+ Should it be configurable? Some sound drivers let you set buffer size...
+*/
+#define MAX_SOUND_BUFFER_SIZE 16383
+
+
+/*
+ Audio buffer I/O streaming handler. Slices 'n dices your buffers and
+ serves them up on a platter with a side dressing of your choice.
+
+ It's safe to update the buffer information post-submission within this
+ routine since any completion will be done in an APC for the same thread,
+ so we're not likely to be rudely interrupted by a completion routine
+ bursting through the door.
+*/
+MMRESULT
+StreamWaveData(
IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
- IN PWAVE_THREAD_DATA ThreadData,
- IN PWAVEHDR WaveHeader)
-{
- SOUND_ASSERT(SoundDeviceInstance);
- SOUND_ASSERT(ThreadData);
- SOUND_ASSERT(WaveHeader);
-
- return OverlappedWriteToSoundDevice(SoundDeviceInstance,
- (PVOID) WaveHeader,
- WaveHeader->lpData,
- WaveHeader->dwBufferLength);
+ IN PWAVE_THREAD_DATA ThreadData)
+{
+ PWAVEHDR Buffer = ThreadData->CurrentBuffer;
+ DWORD BufferOffset, BytesToStream, BytesAvailable;
+ MMRESULT Result;
+
+ SOUND_ASSERT(ThreadData->RemainingBytes <= MAX_SOUND_BUFFER_SIZE);
+ SOUND_ASSERT(Buffer);
+
+ /* The 'reserved' member of Buffer contains the offset */
+ BufferOffset = Buffer->reserved;
+
+ /* Work out how much data can be streamed with the driver */
+ BytesAvailable = MAX_SOUND_BUFFER_SIZE - ThreadData->RemainingBytes;
+
+ /*
+ If no space available, don't do anything. The routine will be revisited
+ as buffers complete, at which point the backlog will start being
+ dealt with.
+ */
+ if ( BytesAvailable == 0 )
+ return MMSYSERR_NOERROR;
+
+ /*
+ Adjust the amount of data to be streamed based on how much of the
+ current buffer has actually been dealt with already.
+ */
+ BytesToStream = Buffer->dwBufferLength - BufferOffset;
+
+ /*
+ No point in doing work unless we have to... This is, however, a
+ completed buffer, so it should be dealt with!!
+ */
+ if ( BytesToStream == 0 )
+ {
+ /* TODO */
+ return MMSYSERR_NOERROR;
+ }
+
+ /*
+ Now we know how much buffer is waiting to be provided to the driver,
+ we need to consider how much the driver can accept.
+ */
+ if ( BytesToStream > BytesAvailable )
+ {
+ /* Buffer can't fit entirely - fill the available space */
+ BytesToStream = BytesAvailable;
+ }
+
+ /*
+ Now the audio buffer sets sail on its merry way to the sound driver...
+ NOTE: Will need to implement a 'read' function, too.
+ */
+ Result = OverlappedWriteToSoundDevice(SoundDeviceInstance,
+ (PVOID) ThreadData,
+ Buffer->lpData + BufferOffset,
+ BytesToStream);
+
+ if ( Result != MMSYSERR_NOERROR )
+ return Result;
+
+ /* Update the offset ready for the next streaming operation */
+ BufferOffset += BytesToStream;
+ Buffer->reserved = BufferOffset;
+
+ /* More data has been sent to the driver, so this is updated, too */
+ ThreadData->RemainingBytes += BytesToStream;
+
+ return MMSYSERR_NOERROR;
}
@@ -53,12 +127,15 @@
IN PWAVE_THREAD_DATA ThreadData,
IN PWAVEHDR Buffer)
{
+/* DWORD BytesSubmitted = 0;*/
+
SOUND_ASSERT(Instance != NULL);
SOUND_ASSERT(Buffer != NULL);
SOUND_ASSERT(Instance->Thread != NULL);
- /* Store the device instance */
- Buffer->reserved = (DWORD) Instance;
+ /* This is used to mark the offset within the buffer */
+ Buffer->reserved = 0;
+ /* TODO: Clear completion flag */
/* Set the head of the buffer list if this is the first buffer */
if ( ! ThreadData->FirstBuffer )
@@ -78,18 +155,13 @@
/* Increment the number of buffers queued */
++ ThreadData->BufferCount;
- /* HACK */
- ThreadData->CurrentBuffer = ThreadData->FirstBuffer;
-
- WriteWaveBufferToSoundDevice(Instance, ThreadData, Buffer);
-
-/*
- Result = WriteSoundDeviceBuffer(Instance,
- ThreadData->CurrentBuffer->lpData,
- ThreadData->CurrentBuffer->dwBufferLength,
- WaveBufferCompleted,
- (LPOVERLAPPED) &Thread->Wave.Overlapped);
-*/
+ /* If nothing is playing, we'll need to start things off */
+ if ( ThreadData->RemainingBytes == 0 )
+ {
+ ThreadData->CurrentBuffer = ThreadData->FirstBuffer;
+ StreamWaveData(Instance, ThreadData);
+ }
+
return MMSYSERR_NOERROR;
}
@@ -141,10 +213,12 @@
IN PVOID ContextData,
IN DWORD BytesTransferred)
{
- LPWAVEHDR WaveHeader = (LPWAVEHDR) ContextData;
-
- SOUND_DEBUG(L"ProcessWaveIoCompletion called :)");
- SOUND_DEBUG_HEX(WaveHeader);
+ PWAVE_THREAD_DATA ThreadData = (PWAVE_THREAD_DATA) ContextData;
+ SOUND_ASSERT(ThreadData);
+ WCHAR msg[1024];
+
+ /*SOUND_DEBUG(L"ProcessWaveIoCompletion called :)");*/
+ /*SOUND_DEBUG_HEX(WaveHeader);*/
/*
At this point we know:
@@ -164,6 +238,21 @@
thread will wait for more requests from the client before
it does anything else.
*/
+
+ /* Discount the amount of buffer which has been processed */
+ SOUND_ASSERT(BytesTransferred <= ThreadData->RemainingBytes);
+ ThreadData->RemainingBytes -= BytesTransferred;
+
+ wsprintf(msg, L"Wave header: %x\nOffset: %d\nTransferred: %d bytes\nRemaining: %d bytes",
+ ThreadData->CurrentBuffer,
+ ThreadData->CurrentBuffer->reserved,
+ BytesTransferred,
+ ThreadData->RemainingBytes);
+
+ MessageBox(0, msg, L"I/O COMPLETE", MB_OK | MB_TASKMODAL);
+
+ /* TODO: Check return value */
+ StreamWaveData(Instance, ThreadData);
}