Author: silverblade
Date: Wed Jul 9 12:41:18 2008
New Revision: 34395
URL: http://svn.reactos.org/svn/reactos?rev=34395&view=rev
Log:
Various adjustments to the wave audio playback code. Seems to work OK when
playing large buffers that require splitting up however doesn't work if
multiple buffers are sent in succession.
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/thread.c
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] Wed Jul 9 12:41:18 2008
@@ -117,8 +117,10 @@
}
-WORD Buffer[65536];
-WAVEHDR WaveHeader;
+#include <stdio.h>
+
+WORD Buffer[5347700 / 2];
+WAVEHDR WaveHeaders[534];
int APIENTRY wWinMain(
HINSTANCE hInstance,
@@ -126,57 +128,78 @@
LPWSTR lpCmdLine,
int nCmdShow)
{
- WCHAR msg[1024];
- WAVEOUTCAPS Caps;
+// WCHAR msg[1024];
+// WAVEOUTCAPS Caps;
WAVEOPENDESC OpenDesc;
WAVEFORMATEX Format;
MMRESULT Result;
PVOID InstanceData;
- int i;
-
- for ( i = 0; i < 65536; ++ i )
- Buffer[i] = rand();
+// int i;
+
+ FILE* f;
+
+ f = fopen("27may2_a.wav", "rb");
+ fseek(f, 50, SEEK_SET);
+ fread(Buffer, 1, 5340000, f);
+ fclose(f);
/* DRV_LOAD */
DriverProc(0, 0, DRV_LOAD, 0, 0);
/* WODM_GETNUMDEVS */
- SOUND_DEBUG_HEX(wodMessage(0, WODM_GETNUMDEVS, 0, 0, 0));
-
- Result = wodMessage(0, WODM_GETDEVCAPS, 0,
- (DWORD) &Caps, sizeof(WAVEOUTCAPS));
+ //SOUND_DEBUG_HEX(wodMessage(0, WODM_GETNUMDEVS, 0, 0, 0));
+
+ //Result = wodMessage(0, WODM_GETDEVCAPS, 0,
+ //(DWORD) &Caps, sizeof(WAVEOUTCAPS));
/* WODM_GETDEVCAPS */
- wsprintf(msg, L"Device name: %ls\nManufacturer ID: %d\nProduct ID: %d\nDriver version: %x\nChannels: %d", Caps.szPname, Caps.wMid, Caps.wPid, Caps.vDriverVersion, Caps.wChannels);
-
- MessageBox(0, msg, L"Device capabilities", MB_OK | MB_TASKMODAL);
+ //wsprintf(msg, L"Device name: %ls\nManufacturer ID: %d\nProduct ID: %d\nDriver version: %x\nChannels: %d", Caps.szPname, Caps.wMid, Caps.wPid, Caps.vDriverVersion, Caps.wChannels);
+
+ //MessageBox(0, msg, L"Device capabilities", MB_OK | MB_TASKMODAL);
/* WODM_OPEN */
Format.wFormatTag = WAVE_FORMAT_PCM;
- Format.nChannels = 1;
- Format.nSamplesPerSec = 22050;
+ Format.nChannels = 2;
+ Format.nSamplesPerSec = 44100;
Format.wBitsPerSample = 16;
Format.nBlockAlign = Format.nChannels * (Format.wBitsPerSample / 8);
Format.nAvgBytesPerSec = Format.nSamplesPerSec * Format.nBlockAlign;
Format.cbSize = 0;
- SOUND_DEBUG(L"WODM_OPEN test 1 (query format support only)");
- OpenDesc.lpFormat = &Format;
- Result = wodMessage(0, WODM_OPEN, 0, (DWORD) &OpenDesc, WAVE_FORMAT_QUERY);
- SOUND_DEBUG_HEX(Result);
-
- SOUND_DEBUG(L"WODM_OPEN test 2");
+ //SOUND_DEBUG(L"WODM_OPEN test 1 (query format support only)");
+ //OpenDesc.lpFormat = &Format;
+ //Result = wodMessage(0, WODM_OPEN, 0, (DWORD) &OpenDesc, WAVE_FORMAT_QUERY);
+ //SOUND_DEBUG_HEX(Result);
+
+ //SOUND_DEBUG(L"WODM_OPEN test 2");
OpenDesc.lpFormat = &Format;
Result = wodMessage(0, WODM_OPEN, (DWORD) &InstanceData, (DWORD) &OpenDesc, 0);
SOUND_DEBUG_HEX(Result);
SOUND_DEBUG(L"WODM_WRITE test");
- WaveHeader.lpData = (PVOID) Buffer;
- WaveHeader.dwBufferLength = 65536;
- WaveHeader.dwFlags = WHDR_PREPARED;
-
- Result = wodMessage(0, WODM_WRITE, (DWORD) InstanceData, (DWORD) &WaveHeader, 0);
- SOUND_DEBUG_HEX(Result);
+ WaveHeaders[0].lpData = (PVOID) Buffer;
+ WaveHeaders[0].dwBufferLength = 1000000;
+ WaveHeaders[0].dwFlags = WHDR_PREPARED;
+
+ WaveHeaders[1].lpData = (PVOID) ((PCHAR)Buffer + 1000000);
+ WaveHeaders[1].dwBufferLength = 1000000;
+ WaveHeaders[1].dwFlags = WHDR_PREPARED;
+
+ WaveHeaders[2].lpData = (PVOID) ((PCHAR)Buffer + (1000000 *2));
+ WaveHeaders[2].dwBufferLength = 1000000;
+ WaveHeaders[2].dwFlags = WHDR_PREPARED;
+
+// WaveHeader2.lpData = (PVOID) Buffer2;
+// WaveHeader2.dwBufferLength = 10;
+// WaveHeader2.dwFlags = WHDR_PREPARED;
+
+ Result = wodMessage(0, WODM_WRITE, (DWORD) InstanceData, (DWORD) &WaveHeaders[0], 0);
+ Result = wodMessage(0, WODM_WRITE, (DWORD) InstanceData, (DWORD) &WaveHeaders[1], 0);
+ Result = wodMessage(0, WODM_WRITE, (DWORD) InstanceData, (DWORD) &WaveHeaders[2], 0);
+
+ //Result = wodMessage(0, WODM_WRITE, (DWORD) InstanceData, (DWORD) &WaveHeader2, 0);
+
+// SOUND_DEBUG_HEX(Result);
SOUND_DEBUG(L"WODM_CLOSE test");
Result = wodMessage(0, WODM_CLOSE, (DWORD) InstanceData, (DWORD) 0, 0);
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] Wed Jul 9 12:41:18 2008
@@ -112,6 +112,7 @@
{
OVERLAPPED General;
struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance;
+ PVOID PrivateThreadData;
PVOID ContextData; /* eg: PWAVEHDR */
PSOUND_THREAD_COMPLETED_IO CompletionData;
} SOUND_THREAD_OVERLAPPED, *PSOUND_THREAD_OVERLAPPED;
@@ -124,6 +125,7 @@
typedef VOID (*SOUND_THREAD_IO_COMPLETION_HANDLER)(
IN struct _SOUND_DEVICE_INSTANCE* Instance,
+ IN PVOID PrivateThreadData,
IN PVOID ContextData,
IN DWORD BytesTransferred);
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] Wed Jul 9 12:41:18 2008
@@ -88,7 +88,7 @@
PSOUND_THREAD_COMPLETED_IO CompletionData;
SOUND_ASSERT(Thread->FirstCompletedIo);
- SOUND_DEBUG(L"Outside I/O completion APC");
+ //SOUND_DEBUG(L"Outside I/O completion APC");
/*
Purge the completed data queue
@@ -100,6 +100,7 @@
{
/* Call high-level custom I/O completion routine */
Thread->IoCompletionHandler(Instance,
+ Thread->PrivateData,
CompletionData->ContextData,
CompletionData->BytesTransferred);
@@ -290,6 +291,8 @@
if ( ! SoundDeviceInstance->Thread )
return MMSYSERR_ERROR;
+ //SOUND_DEBUG(L"Waiting for Ready event");
+
/* Wait for the thread to be ready */
WaitForSingleObject(SoundDeviceInstance->Thread->ReadyEvent, INFINITE);
@@ -350,7 +353,7 @@
SOUND_ASSERT(SoundDeviceInstance);
SOUND_ASSERT(SoundDeviceInstance->Thread);
- SOUND_DEBUG(L"New I/O Completion Callback Called");
+ //SOUND_DEBUG(L"New I/O Completion Callback Called");
/* This is going at the start of the list */
CompletionData->Next = SoundDeviceInstance->Thread->FirstCompletedIo;
@@ -365,7 +368,7 @@
/* Overlapped structure gets freed now, but we still need the completion */
FreeMemory(SoundThreadOverlapped);
- SOUND_DEBUG(L"New I/O Completion Callback Done");
+ //SOUND_DEBUG(L"New I/O Completion Callback Done");
}
MMRESULT
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] Wed Jul 9 12:41:18 2008
@@ -30,7 +30,7 @@
Should it be configurable? Some sound drivers let you set buffer size...
*/
-#define MAX_SOUND_BUFFER_SIZE 16383
+#define MAX_SOUND_BUFFER_SIZE 1500000
/*
@@ -54,64 +54,80 @@
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;
+ while ( ( Buffer = ThreadData->CurrentBuffer ) && ( BytesAvailable > 0 ) )
+ {
+ /* The 'reserved' member of Buffer contains the offset */
+ BufferOffset = Buffer->reserved;
+
+ /*
+ 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;
+
+ /*
+ We may find that there's nothing to be done with the current
+ buffer, either on initial entry to this loop or after having
+ been through a few iterations. Once the buffer has been squeezed
+ dry, move on to the next victim...
+ */
+ if ( BytesToStream == 0 )
+ {
+ /* TODO */
+ SOUND_DEBUG(L"Advancing buffer");
+ ThreadData->CurrentBuffer = ThreadData->CurrentBuffer->lpNext;
+ continue;
+ }
+
+ /*
+ 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.
+ */
+ SOUND_DEBUG(L"Writing data");
+ Result = OverlappedWriteToSoundDevice(SoundDeviceInstance,
+ (PVOID) Buffer,
+ 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 these get updated, too */
+ ThreadData->RemainingBytes += BytesToStream;
+ BytesAvailable = MAX_SOUND_BUFFER_SIZE - ThreadData->RemainingBytes;
+
+ /*
+ If the offset is now equal to the buffer length, this will be
+ because the entirety of the buffer has been sent.
+ */
+/*
+ if ( BufferOffset == Buffer->dwBufferLength )
+ {
+ SOUND_DEBUG(L"Advancing buffer");
+ ThreadData->CurrentBuffer = ThreadData->CurrentBuffer->lpNext;
+ }
+*/
+ }
+
+ SOUND_DEBUG(L"Leaving");
return MMSYSERR_NOERROR;
}
@@ -140,12 +156,14 @@
/* Set the head of the buffer list if this is the first buffer */
if ( ! ThreadData->FirstBuffer )
{
+ SOUND_DEBUG(L"First buffer");
ThreadData->FirstBuffer = Buffer;
}
/* Attach the buffer to the end of the list, unless this is the first */
if ( ThreadData->LastBuffer )
{
+ SOUND_DEBUG(L"Adding to end of list");
ThreadData->LastBuffer->lpNext = Buffer;
}
@@ -158,6 +176,7 @@
/* If nothing is playing, we'll need to start things off */
if ( ThreadData->RemainingBytes == 0 )
{
+ SOUND_DEBUG(L"Kicking off processing");
ThreadData->CurrentBuffer = ThreadData->FirstBuffer;
StreamWaveData(Instance, ThreadData);
}
@@ -210,10 +229,12 @@
VOID
ProcessWaveIoCompletion(
IN struct _SOUND_DEVICE_INSTANCE* Instance,
+ IN PVOID PrivateThreadData,
IN PVOID ContextData,
IN DWORD BytesTransferred)
{
- PWAVE_THREAD_DATA ThreadData = (PWAVE_THREAD_DATA) ContextData;
+ PWAVE_THREAD_DATA ThreadData = (PWAVE_THREAD_DATA) PrivateThreadData;
+ PWAVEHDR WaveHeader = (PWAVEHDR) ContextData;
SOUND_ASSERT(ThreadData);
WCHAR msg[1024];
@@ -244,8 +265,8 @@
ThreadData->RemainingBytes -= BytesTransferred;
wsprintf(msg, L"Wave header: %x\nOffset: %d\nTransferred: %d bytes\nRemaining: %d bytes",
- ThreadData->CurrentBuffer,
- ThreadData->CurrentBuffer->reserved,
+ WaveHeader,
+ WaveHeader->reserved,
BytesTransferred,
ThreadData->RemainingBytes);