Author: silverblade
Date: Thu Jul 10 18:32:48 2008
New Revision: 34416
URL:
http://svn.reactos.org/svn/reactos?rev=34416&view=rev
Log:
Replaced threaded wave stream playback code again, to overcome stuttering
playback issue caused by limiting playback to a single buffer at a time. This
was causing playback to only go smoothly when the buffer got split up (ie,
it became double-buffered). Need to fix a bug occuring when buffers are
exhausted still.
Modified:
branches/silverblade-audio/dll/win32/sndblst/sndblst.c
branches/silverblade-audio/include/reactos/libs/sound/mmebuddy.h
branches/silverblade-audio/lib/drivers/sound/mmebuddy/wave/wavethread.c
Modified: branches/silverblade-audio/dll/win32/sndblst/sndblst.c
URL:
http://svn.reactos.org/svn/reactos/branches/silverblade-audio/dll/win32/snd…
==============================================================================
--- branches/silverblade-audio/dll/win32/sndblst/sndblst.c [iso-8859-1] (original)
+++ branches/silverblade-audio/dll/win32/sndblst/sndblst.c [iso-8859-1] Thu Jul 10
18:32:48 2008
@@ -165,7 +165,7 @@
/* WODM_OPEN */
Format.wFormatTag = WAVE_FORMAT_PCM;
Format.nChannels = 2;
- Format.nSamplesPerSec = 22050;
+ Format.nSamplesPerSec = 44100;
Format.wBitsPerSample = 16;
Format.nBlockAlign = Format.nChannels * (Format.wBitsPerSample / 8);
Format.nAvgBytesPerSec = Format.nSamplesPerSec * Format.nBlockAlign;
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] Thu Jul
10 18:32:48 2008
@@ -75,6 +75,13 @@
CopyMemory(dest, source, StringLengthToBytes(WCHAR, wcslen(source)))
+#define MinimumOf(value_a, value_b) \
+ ( value_a < value_b ? value_a : value_b )
+
+#define MaximumOf(value_a, value_b) \
+ ( value_a > value_b ? value_a : value_b )
+
+
struct _SOUND_DEVICE;
struct _SOUND_DEVICE_INSTANCE;
@@ -136,79 +143,6 @@
PSOUND_THREAD_COMPLETED_IO CompletionData;
} SOUND_THREAD_OVERLAPPED, *PSOUND_THREAD_OVERLAPPED;
-#if 0
-/*
- Used internally to shuttle data to/from the sound processing thread.
-*/
-typedef struct _THREAD_REQUEST
-{
- struct _SOUND_DEVICE_INSTANCE* DeviceInstance;
- DWORD RequestId;
- PVOID Data;
- MMRESULT Result;
-} THREAD_REQUEST, *PTHREAD_REQUEST;
-
-typedef struct _SOUND_THREAD_COMPLETED_IO
-{
- struct _SOUND_THREAD_COMPLETED_IO* Next;
- PVOID ContextData; /* eg: PWAVEHDR */
- DWORD BytesTransferred;
-} SOUND_THREAD_COMPLETED_IO, *PSOUND_THREAD_COMPLETED_IO;
-
-typedef struct _SOUND_THREAD_OVERLAPPED
-{
- OVERLAPPED General;
- struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance;
- PVOID PrivateThreadData;
- PVOID ContextData; /* eg: PWAVEHDR */
- PSOUND_THREAD_COMPLETED_IO CompletionData;
-} SOUND_THREAD_OVERLAPPED, *PSOUND_THREAD_OVERLAPPED;
-
-
-typedef VOID (*SOUND_THREAD_IO_COMPLETION_HANDLER)(
- IN struct _SOUND_DEVICE_INSTANCE* Instance,
- IN PVOID PrivateThreadData,
- IN PVOID ContextData,
- IN DWORD BytesTransferred);
-
-typedef struct _SOUND_THREAD
-{
- /* Thread management */
- HANDLE Handle;
- PVOID PrivateData;
- BOOLEAN Running;
-
- HANDLE ReadyEvent; /* Thread waiting for a request */
- HANDLE RequestEvent; /* Caller sending a request */
- HANDLE DoneEvent; /* Thread completed a request */
-
- SOUND_THREAD_REQUEST_HANDLER RequestHandler;
- THREAD_REQUEST Request;
-
- SOUND_THREAD_OVERLAPPED Overlapped;
- PSOUND_THREAD_COMPLETED_IO FirstCompletedIo;
- SOUND_THREAD_IO_COMPLETION_HANDLER IoCompletionHandler;
-} SOUND_THREAD, *PSOUND_THREAD;
-#endif
-
-
-/*
- Wave thread
-*/
-#if 0
-typedef struct _WAVE_THREAD_DATA
-{
- /* Wave thread specific */
- DWORD BufferCount;
- PWAVEHDR CurrentBuffer;
- PWAVEHDR FirstBuffer;
- PWAVEHDR LastBuffer;
-
- /* How much data is waiting with the driver */
- DWORD RemainingBytes;
-} WAVE_THREAD_DATA, *PWAVE_THREAD_DATA;
-#endif
-
/*
Audio device function table
*/
@@ -276,9 +210,9 @@
/* The buffer currently being processed */
PWAVEHDR CurrentBuffer;
/* How far into the current buffer we've gone */
- DWORD BufferOffset;
- /* How much data we're expecting back */
- DWORD BytesOutstanding;
+ //DWORD BufferOffset;
+ /* How many I/O operations have been submitted */
+ DWORD BuffersOutstanding;
} WAVE_STREAM_INFO, *PWAVE_STREAM_INFO;
typedef struct _SOUND_DEVICE_INSTANCE
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]
Thu Jul 10 18:32:48 2008
@@ -23,16 +23,15 @@
/*
- 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...
+ How much we can feed to the driver at a time. For example, 2 buffers
+ of 65536 would mean we can send 65536 bytes in a single I/O operation,
+ and a total of 2 buffers (not necessarily full).
+
+ If a single WAVEHDR is larger than MAX_SOUND_BUFFER_SIZE then a second
+ buffer will be used.
*/
#define MAX_SOUND_BUFFER_SIZE 65536
-
-
+#define MAX_SOUND_BUFFERS 2
VOID
CompleteWaveBuffer(
@@ -40,122 +39,95 @@
IN PVOID Parameter,
IN DWORD BytesWritten);
+BOOLEAN
+StreamReadyForData(
+ IN PWAVE_STREAM_INFO StreamInfo)
+{
+ SOUND_ASSERT(StreamInfo);
+
+ return (StreamInfo->BuffersOutstanding < MAX_SOUND_BUFFERS);
+}
+
+BOOLEAN
+StreamHasBuffersQueued(
+ IN PWAVE_STREAM_INFO StreamInfo)
+{
+ SOUND_ASSERT(StreamInfo);
+
+ return (StreamInfo->CurrentBuffer != NULL);
+}
+
+DWORD
+PerformWaveIo(
+ IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
+{
+ PWAVE_STREAM_INFO StreamInfo;
+ DWORD BytesToStream, BytesStreamed = 0;
+
+ SOUND_ASSERT(SoundDeviceInstance);
+
+ StreamInfo = &SoundDeviceInstance->Streaming.Wave;
+ SOUND_ASSERT(StreamInfo->CurrentBuffer);
+
+ /* Work out how much buffer can be submitted */
+ BytesToStream = MinimumOf(StreamInfo->CurrentBuffer->dwBufferLength -
+ StreamInfo->CurrentBuffer->reserved,
+ MAX_SOUND_BUFFER_SIZE);
+
+ SOUND_TRACE("Writing %p + %d (%d bytes) - buffer length is %d bytes\n",
+ StreamInfo->CurrentBuffer->lpData,
+ (int) StreamInfo->CurrentBuffer->reserved,
+ (int) BytesToStream,
+ (int) StreamInfo->CurrentBuffer->dwBufferLength);
+
+ /* TODO: Error checking */
+ OverlappedSoundDeviceIo(SoundDeviceInstance,
+ (PCHAR) StreamInfo->CurrentBuffer->lpData +
+ StreamInfo->CurrentBuffer->reserved,
+ BytesToStream,
+ CompleteWaveBuffer,
+ (PVOID) StreamInfo->CurrentBuffer);
+
+ /* FIXME? - find out how much was actually sent? */
+ BytesStreamed = BytesToStream;
+
+ /* Advance the offset */
+ StreamInfo->CurrentBuffer->reserved += BytesStreamed;
+
+ /* If we've hit the end of the buffer, move to the next one */
+ if ( StreamInfo->CurrentBuffer->reserved ==
+ StreamInfo->CurrentBuffer->dwBufferLength )
+ {
+ SOUND_TRACE("Advancing to next buffer\n");
+ StreamInfo->CurrentBuffer = StreamInfo->CurrentBuffer->lpNext;
+ }
+
+ /* Increase the number of outstanding buffers */
+ ++ StreamInfo->BuffersOutstanding;
+
+ return BytesStreamed;
+}
MMRESULT
-StreamWaveIo(
+StreamWaveBuffers(
IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
{
PWAVE_STREAM_INFO StreamInfo;
- DWORD BytesAvailable, BytesToStream;
+ SOUND_ASSERT(SoundDeviceInstance);
+
+ StreamInfo = &SoundDeviceInstance->Streaming.Wave;
SOUND_TRACE("<== Streaming wave I/O ==>\n");
-
- SOUND_ASSERT(SoundDeviceInstance);
-
- /* Get the streaming info */
- StreamInfo = &SoundDeviceInstance->Streaming.Wave;
-
- BytesAvailable = MAX_SOUND_BUFFER_SIZE - StreamInfo->BytesOutstanding;
-
- if ( ! BytesAvailable )
- {
- SOUND_TRACE("NO BUFFER SPACE AVAILABLE\n");
- }
-
- if ( ! StreamInfo->CurrentBuffer )
- {
- SOUND_TRACE("NO CURRENT BUFFER\n");
- }
-
- while ( StreamInfo->CurrentBuffer && BytesAvailable )
- {
- /*
- Determine how much of the current buffer remains to be
- streamed.
- */
- BytesToStream = StreamInfo->CurrentBuffer->dwBufferLength -
- StreamInfo->BufferOffset;
-
- SOUND_TRACE("Buffer %p, offset %d, length %d\nAvailable %d | BytesToStream
%d | BytesOutstanding %d\n",
- StreamInfo->CurrentBuffer,
- (int) StreamInfo->BufferOffset,
- (int) StreamInfo->CurrentBuffer->dwBufferLength,
- (int) BytesAvailable,
- (int) BytesToStream,
- (int) StreamInfo->BytesOutstanding);
-
-
- /*
- We may receive a buffer with no bytes left to stream, for
- example as a result of an I/O completion triggering this
- routine, or if on a previous iteration of this loop we managed
- to finish sending a buffer.
- */
- if ( BytesToStream == 0 )
- {
- SOUND_TRACE("No bytes to stream\n");
- StreamInfo->CurrentBuffer = StreamInfo->CurrentBuffer->lpNext;
- StreamInfo->BufferOffset = 0;
- continue;
- }
-
- /*
- If the buffer can't be sent in its entirety to the sound driver,
- send a portion of it to fill the available space.
- */
- if ( BytesToStream > BytesAvailable )
- {
- BytesToStream = BytesAvailable;
- }
-
- SOUND_TRACE("Writing %d bytes from buffer %p, offset %d\n",
- (int) BytesToStream,
- StreamInfo->CurrentBuffer->lpData,
- (int)StreamInfo->BufferOffset);
-
- /* TODO: Do the streaming */
- OverlappedSoundDeviceIo(SoundDeviceInstance,
- (PCHAR) StreamInfo->CurrentBuffer->lpData +
- StreamInfo->BufferOffset,
- BytesToStream,
- CompleteWaveBuffer,
- (PVOID) StreamInfo->CurrentBuffer);
-
- /*
- Keep track of the amount of data currently in the hands of the
- sound driver, so we know how much space is being used up so
- far, and how many bytes will be announced to the completion
- routines.
- */
- StreamInfo->BytesOutstanding += BytesToStream;
-
- /*
- Update the offset within the buffer to reflect the amount of
- data being transferred in this transaction.
- */
- StreamInfo->BufferOffset += BytesToStream;
-
- /*
- Update the number of bytes available for the next iteration.
- */
- BytesAvailable = MAX_SOUND_BUFFER_SIZE - StreamInfo->BytesOutstanding;
-
- }
-
- SOUND_TRACE("<== Done filling stream ==>\n");
-
-#if 0
- /* TODO: Check result */
- OverlappedSoundDeviceIo(SoundDeviceInstance,
- WaveHeader->lpData,
- WaveHeader->dwBufferLength,
- CompleteWaveBuffer,
- (PVOID) WaveHeader);
-#endif
+ while ( StreamReadyForData(StreamInfo) &&
+ StreamHasBuffersQueued(StreamInfo) )
+ {
+ SOUND_TRACE("Performing wave I/O ...\n");
+ PerformWaveIo(SoundDeviceInstance);
+ }
+ SOUND_TRACE("<== Done streaming ==>\n");
return MMSYSERR_NOERROR;
}
-
VOID
CompleteWaveBuffer(
@@ -163,13 +135,22 @@
IN PVOID Parameter,
IN DWORD BytesWritten)
{
- SOUND_TRACE("CompleteWaveBuffer called - wrote %d bytes\n",
(int)BytesWritten);
-
- SoundDeviceInstance->Streaming.Wave.BytesOutstanding -= BytesWritten;
-
- StreamWaveIo(SoundDeviceInstance);
-}
-
+ PWAVE_STREAM_INFO StreamInfo;
+
+ SOUND_TRACE("Wave completion routine\n");
+
+ SOUND_ASSERT(SoundDeviceInstance);
+
+ StreamInfo = &SoundDeviceInstance->Streaming.Wave;
+
+ /* Decrease the number of outstanding buffers */
+ SOUND_ASSERT(StreamInfo->BuffersOutstanding > 0);
+ -- StreamInfo->BuffersOutstanding;
+
+ PerformWaveIo(SoundDeviceInstance);
+
+ SOUND_TRACE("Wave completion routine done\n");
+}
MMRESULT
QueueBuffer_Request(
@@ -208,11 +189,12 @@
StreamInfo->CurrentBuffer = WaveHeader;
/* Initialise the stream state */
- StreamInfo->BufferOffset = 0;
- StreamInfo->BytesOutstanding = 0;
+ //StreamInfo->BufferOffset = 0;
+ //StreamInfo->BytesOutstanding = 0;
+ StreamInfo->BuffersOutstanding = 0;
/* Get the streaming started */
- StreamWaveIo(SoundDeviceInstance);
+ StreamWaveBuffers(SoundDeviceInstance);
}
else
{