[ros-diffs] [silverblade] 34416: 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.

silverblade at svn.reactos.org silverblade at svn.reactos.org
Fri Jul 11 01:32:48 CEST 2008


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/sndblst/sndblst.c?rev=34416&r1=34415&r2=34416&view=diff
==============================================================================
--- 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/reactos/libs/sound/mmebuddy.h?rev=34416&r1=34415&r2=34416&view=diff
==============================================================================
--- 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/sound/mmebuddy/wave/wavethread.c?rev=34416&r1=34415&r2=34416&view=diff
==============================================================================
--- 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
     {



More information about the Ros-diffs mailing list