mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
[MMEBUDDY] Implement support for looped wave playback (#6761)
Fix playing wave header multiple times in case the caller requests to do it. In Windows, it is supported by WHDR_BEGINLOOP and WHDR_ENDLOOP flags (specified together) and dwLoops member of WAVEHDR structure (ususally set to 0xFFFFFFFF (INFINITE constant)). - Check whenther WHDR_BEGINLOOP | WHDR_ENDLOOP flags are set by the caller. - If they are, get the amount of times to play the header from WAVEHDR.dwLoops. - Perform wave header competion only when the loop count is equal to zero. Otherwise, don't do it. - When the header is entirely committed, in case completion is not needed, reset committed bytes count to the starting value to allow the header play again. - Decrement loop count in case it isn't set to INFINITE, to mark loop as played correctly. When this count becomes zero, then the playback is finished. - Get rid from SOUND_OVERLAPPED.PerformCompletion member. Use SOUND_DEVICE_INSTANCE.LoopsRemaining == 0 condition instead. - Do this only for WaveOut devices, since MSDN states it works only with output buffers. Hence, there is nothing changed for WaveIn. - Update an appropriate statement about unimplemented functionality from mmebuddy notes. TODO: handle the case when multiple headers are requested to be looped (WHDR_BEGINLOOP and WHDR_ENDLOOP are set separatedly: 1st flag - in the 1st header, and 2nd in the last header). Currently, only looping a single wave header is supported. This fixes the playback in the apps those request looped wave playback of some audio data (e. g., BRD Demo app, which did play its sound only first 500 ms before, now it plays endlessly until closing it manually). CORE-10118
This commit is contained in:
parent
d23573beed
commit
24e088daa8
3 changed files with 37 additions and 12 deletions
|
@ -120,7 +120,6 @@ typedef struct _SOUND_OVERLAPPED
|
|||
OVERLAPPED Standard;
|
||||
struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance;
|
||||
PWAVEHDR Header;
|
||||
BOOL PerformCompletion;
|
||||
|
||||
LPOVERLAPPED_COMPLETION_ROUTINE OriginalCompletionRoutine;
|
||||
PVOID CompletionContext;
|
||||
|
|
|
@ -26,7 +26,7 @@ Unsupported MME messages:
|
|||
* Any not mentioned above
|
||||
|
||||
Notes/Bugs:
|
||||
* WHDR_BEGINLOOP and WHDR_ENDLOOP are ignored
|
||||
* WHDR_BEGINLOOP and WHDR_ENDLOOP are not working for looping multiple wave headers, only for a single header.
|
||||
* Not possible to pause/restart playback
|
||||
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
#include "precomp.h"
|
||||
|
||||
|
||||
/*
|
||||
DoWaveStreaming
|
||||
Check if there is streaming to be done, and if so, do it.
|
||||
|
@ -54,6 +53,22 @@ DoWaveStreaming(
|
|||
return;
|
||||
}
|
||||
|
||||
/* Do we need to loop a header? */
|
||||
if (DeviceType == WAVE_OUT_DEVICE_TYPE && (Header->dwFlags & WHDR_BEGINLOOP))
|
||||
{
|
||||
if ((Header->dwFlags & WHDR_ENDLOOP))
|
||||
{
|
||||
/* Get loop count */
|
||||
SoundDeviceInstance->LoopsRemaining = Header->dwLoops;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Report and help notice such a case */
|
||||
SND_WARN(L"Looping multiple headers is UNIMPLEMENTED. Will play once only\n");
|
||||
SND_ASSERT((Header->dwFlags & (WHDR_BEGINLOOP | WHDR_ENDLOOP)) == (WHDR_BEGINLOOP | WHDR_ENDLOOP));
|
||||
}
|
||||
}
|
||||
|
||||
while ( ( SoundDeviceInstance->OutstandingBuffers < SoundDeviceInstance->BufferCount ) &&
|
||||
( Header ) && SoundDeviceInstance->ResetInProgress == FALSE)
|
||||
{
|
||||
|
@ -106,10 +121,6 @@ DoWaveStreaming(
|
|||
Overlap->SoundDeviceInstance = SoundDeviceInstance;
|
||||
Overlap->Header = Header;
|
||||
|
||||
/* Don't complete this header if it's part of a loop */
|
||||
Overlap->PerformCompletion = TRUE;
|
||||
// ( SoundDeviceInstance->LoopsRemaining > 0 );
|
||||
|
||||
/* Adjust the commit-related counters */
|
||||
HeaderExtension->BytesCommitted += BytesToCommit;
|
||||
++ SoundDeviceInstance->OutstandingBuffers;
|
||||
|
@ -189,8 +200,8 @@ CompleteIO(
|
|||
-- SoundDeviceInstance->OutstandingBuffers;
|
||||
|
||||
/* Did we finish a WAVEHDR and aren't looping? */
|
||||
if ( HdrExtension->BytesCompleted + dwNumberOfBytesTransferred >= WaveHdr->dwBufferLength &&
|
||||
SoundOverlapped->PerformCompletion )
|
||||
if (HdrExtension->BytesCompleted + dwNumberOfBytesTransferred >= WaveHdr->dwBufferLength &&
|
||||
SoundDeviceInstance->LoopsRemaining == 0)
|
||||
{
|
||||
/* Wave buffer fully completed */
|
||||
Bytes = WaveHdr->dwBufferLength - HdrExtension->BytesCompleted;
|
||||
|
@ -203,9 +214,24 @@ CompleteIO(
|
|||
}
|
||||
else
|
||||
{
|
||||
/* Partially completed */
|
||||
HdrExtension->BytesCompleted += dwNumberOfBytesTransferred;
|
||||
SND_TRACE(L"%d/%d bytes of wavehdr completed\n", HdrExtension->BytesCompleted, WaveHdr->dwBufferLength);
|
||||
/* Do we loop a header? */
|
||||
if (HdrExtension->BytesCommitted == WaveHdr->dwBufferLength &&
|
||||
SoundDeviceInstance->LoopsRemaining != 0)
|
||||
{
|
||||
/* Reset amount of bytes and decrement loop count, to play next iteration */
|
||||
HdrExtension->BytesCommitted = 0;
|
||||
|
||||
if (SoundDeviceInstance->LoopsRemaining != INFINITE)
|
||||
--SoundDeviceInstance->LoopsRemaining;
|
||||
SND_TRACE(L"Looping the header, remaining loops %u\n", SoundDeviceInstance->LoopsRemaining);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Partially completed */
|
||||
HdrExtension->BytesCompleted += dwNumberOfBytesTransferred;
|
||||
SND_TRACE(L"%u/%u bytes of wavehdr completed\n", HdrExtension->BytesCompleted, WaveHdr->dwBufferLength);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue