Skip to content

Commit

Permalink
Merge pull request #2039 from RadWolfie/dsound-fixes
Browse files Browse the repository at this point in the history
Another Round of DSound's Stream fixes
  • Loading branch information
PatrickvL committed Dec 9, 2020
2 parents 4d4f6dd + e2fcedd commit efee57a
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 93 deletions.
67 changes: 43 additions & 24 deletions src/core/hle/DSOUND/DirectSound/DSStream_PacketManager.cpp
Expand Up @@ -75,13 +75,6 @@ void DSStream_Packet_Clear(

free(buffer->pBuffer_data);

// Peform release only, don't trigger any events below.
if (status == XMP_STATUS_RELEASE_CXBXR) {
DSoundSGEMemDealloc(buffer->xmp_data.dwMaxSize);
buffer = pThis->Host_BufferPacketArray.erase(buffer);
return;
}

if (buffer->xmp_data.pdwStatus != xbox::zeroptr) {
(*buffer->xmp_data.pdwStatus) = status;
}
Expand Down Expand Up @@ -163,7 +156,7 @@ static inline void DSStream_Packet_Stop(
{
DSStream_Packet_Stop_Internal(pThis);

if (pThis->Host_BufferPacketArray.size() == 0) {
if (pThis->Host_BufferPacketArray.empty()) {
if ((pThis->EmuFlags & DSE_FLAG_ENVELOPE2) > 0) {
pThis->Xb_Status |= X_DSSSTATUS_ENVELOPECOMPLETE;
}
Expand All @@ -186,6 +179,18 @@ static inline void DSStream_Packet_Starved(
);
}

static inline void DSStream_Packet_Complete(
xbox::X_CDirectSoundStream* pThis
)
{
if ((pThis->EmuFlags & DSE_FLAG_ENVELOPE2) != 0) {
pThis->Xb_Status = X_DSSSTATUS_ENVELOPECOMPLETE;
}
else {
pThis->Xb_Status = 0;
}
}

// Prefill buffer with at least 1 second worth of buffer. See "nAvgBytesPerSec" below for inspection.
static void DSStream_Packet_Prefill(
xbox::X_CDirectSoundStream* pThis,
Expand Down Expand Up @@ -214,10 +219,24 @@ bool DSStream_Packet_Process(
{

// Do not allow to process if there is no packets.
if (pThis->Host_BufferPacketArray.size() == 0) {
if (pThis->Host_BufferPacketArray.empty()) {
return 0;
}

// Do not allow to process when the voice is not activated.
if ((pThis->EmuFlags & DSE_FLAG_PAUSENOACTIVATE) != 0 &&
(pThis->EmuFlags & DSE_FLAG_IS_ACTIVATED) == 0) {
return 0;
}

if (pThis->EmuFlags & DSE_FLAG_IS_FLUSHING) {
return 0;
}

if (!(pThis->EmuFlags & DSE_FLAG_IS_ACTIVATED)) {
pThis->EmuFlags |= DSE_FLAG_IS_ACTIVATED;
}

// If title want to pause, then don't process the packets.
// If media object is being used as playback synch, then don't process the packets.
if ((pThis->EmuFlags & DSE_FLAG_PAUSE) > 0 ||
Expand All @@ -228,16 +247,6 @@ bool DSStream_Packet_Process(
return 0;
}

if ((pThis->Xb_Status & X_DSSSTATUS_PAUSED) > 0) {
pThis->Xb_Status &= ~X_DSSSTATUS_PAUSED;
}

if (pThis->Host_isProcessing == false) {
if (!(pThis->EmuFlags & DSE_FLAG_IS_ACTIVATED)) {
pThis->EmuFlags |= DSE_FLAG_IS_ACTIVATED;
}
}

DWORD dwAudioBytes;
HRESULT hRet = pThis->EmuDirectSoundBuffer8->GetStatus(&dwAudioBytes);
if (hRet == DS_OK) {
Expand Down Expand Up @@ -289,9 +298,10 @@ bool DSStream_Packet_Process(
bool isStreamEnd = packetCurrent->isStreamEnd;
DSStream_Packet_Clear(packetCurrent, XMP_STATUS_SUCCESS, pThis->Xb_lpfnCallback, pThis->Xb_lpvContext, pThis);

if (pThis->Host_BufferPacketArray.size() == 0) {
if (pThis->Host_BufferPacketArray.empty()) {
if (isStreamEnd) {
DSStream_Packet_Stop(pThis);
DSStream_Packet_Complete(pThis);
}
else {
DSStream_Packet_Starved(pThis);
Expand Down Expand Up @@ -325,7 +335,7 @@ bool DSStream_Packet_Process(
DSStream_Packet_Prefill(pThis, packetCurrent);
}
// Out of packets, let's stop stream's buffer.
if (pThis->Host_BufferPacketArray.size() == 0) {
if (pThis->Host_BufferPacketArray.empty()) {
DSStream_Packet_Starved(pThis);
return 0;
}
Expand All @@ -345,7 +355,7 @@ void DSStream_Packet_FlushEx_Reset(
xbox::X_CDirectSoundStream* pThis
)
{
// Remove flags only (This is the only place it will remove other than FlushEx perform set/remove the flags.)
// Remove flags only (This is the only place it will remove beside FlushEx perform re-set the flags.)
pThis->EmuFlags &= ~(DSE_FLAG_FLUSH_ASYNC | DSE_FLAG_ENVELOPE | DSE_FLAG_ENVELOPE2);
pThis->Xb_rtFlushEx = 0LL;
}
Expand All @@ -354,6 +364,9 @@ bool DSStream_Packet_Flush(
xbox::X_CDirectSoundStream* pThis
)
{
if ((pThis->EmuFlags & DSE_FLAG_IS_FLUSHING) == 0) {
pThis->EmuFlags |= DSE_FLAG_IS_FLUSHING;
}
// If host's audio is still playing then return busy-state until buffer has stop playing.
DWORD dwStatus;
pThis->EmuDirectSoundBuffer8->GetStatus(&dwStatus);
Expand All @@ -371,8 +384,14 @@ bool DSStream_Packet_Flush(
DSStream_Packet_Clear(buffer, XMP_STATUS_FLUSHED, pThis->Xb_lpfnCallback, pThis->Xb_lpvContext, pThis);
}
// Clear flags and set status to zero.
DSStream_Packet_Complete(pThis);
DSStream_Packet_FlushEx_Reset(pThis);
pThis->EmuFlags &= ~DSE_FLAG_PAUSE;
pThis->Xb_Status = 0;

// TESTCASE: Burnout 3 sets stream to pause state then calling SetFormat without processing any packets.
// Which then doesn't need to clear pause flag.
if ((pThis->EmuFlags & DSE_FLAG_IS_ACTIVATED) != 0) {
pThis->EmuFlags &= ~(DSE_FLAG_PAUSE | DSE_FLAG_IS_ACTIVATED);
}
pThis->EmuFlags &= ~DSE_FLAG_IS_FLUSHING;
return false;
}
2 changes: 1 addition & 1 deletion src/core/hle/DSOUND/DirectSound/DirectSound.cpp
Expand Up @@ -899,7 +899,7 @@ xbox::hresult_xt WINAPI xbox::EMUPATCH(CDirectSound_SynchPlayback)

vector_ds_stream::iterator ppDSStream = g_pDSoundStreamCache.begin();
for (; ppDSStream != g_pDSoundStreamCache.end(); ppDSStream++) {
if ((*ppDSStream)->Host_BufferPacketArray.size() == 0) {
if ((*ppDSStream)->Host_BufferPacketArray.empty()) {
continue;
}
if (((*ppDSStream)->EmuFlags & DSE_FLAG_SYNCHPLAYBACK_CONTROL) > 0) {
Expand Down
8 changes: 5 additions & 3 deletions src/core/hle/DSOUND/DirectSound/DirectSound.hpp
Expand Up @@ -133,11 +133,13 @@ struct SharedDSBuffer : DSBUFFER_S {
#define DSE_FLAG_PCM_UNKNOWN (1 << 2)
#define DSE_FLAG_SYNCHPLAYBACK_CONTROL (1 << 10)
#define DSE_FLAG_PAUSE (1 << 11)
#define DSE_FLAG_FLUSH_ASYNC (1 << 12)
#define DSE_FLAG_ENVELOPE (1 << 13)
#define DSE_FLAG_ENVELOPE2 (1 << 14) // NOTE: This flag is a requirement for GetStatus to return X_DSSSTATUS_ENVELOPECOMPLETE value.
#define DSE_FLAG_PAUSENOACTIVATE (1 << 12)
#define DSE_FLAG_FLUSH_ASYNC (1 << 13)
#define DSE_FLAG_ENVELOPE (1 << 14)
#define DSE_FLAG_ENVELOPE2 (1 << 15) // NOTE: This flag is a requirement for GetStatus to return X_DSSSTATUS_ENVELOPECOMPLETE value.
#define DSE_FLAG_RECIEVEDATA (1 << 20)
#define DSE_FLAG_IS_ACTIVATED (1 << 21) // Only used for DirectSoundStream class, to acknowledge pause's no activate flag.
#define DSE_FLAG_IS_FLUSHING (1 << 22) // Only used for DirectSoundStream class, to acknowledge pause's no activate flag.
#define DSE_FLAG_DEBUG_MUTE (1 << 30) // Cxbx-R debugging usage only
#define DSE_FLAG_BUFFER_EXTERNAL (1 << 31)
#define DSE_FLAG_AUDIO_CODECS (DSE_FLAG_PCM | DSE_FLAG_XADPCM | DSE_FLAG_PCM_UNKNOWN)
Expand Down
15 changes: 11 additions & 4 deletions src/core/hle/DSOUND/DirectSound/DirectSoundInline.hpp
Expand Up @@ -849,14 +849,16 @@ static inline HRESULT HybridDirectSoundBuffer_Pause(
pDSBuffer->Play(0, 0, dwEmuPlayFlags);
}
DSoundBufferSynchPlaybackFlagRemove(dwEmuFlags);
dwEmuFlags &= ~DSE_FLAG_PAUSE;
dwEmuFlags &= ~(DSE_FLAG_PAUSE | DSE_FLAG_PAUSENOACTIVATE);
Xb_rtTimeStamp = 0;
break;
case X_DSSPAUSE_PAUSE:
pDSBuffer->Stop();
DSoundBufferSynchPlaybackFlagRemove(dwEmuFlags);
dwEmuFlags |= DSE_FLAG_PAUSE;
Xb_rtTimeStamp = rtTimeStamp;
if ((dwEmuFlags & DSE_FLAG_PAUSENOACTIVATE) == 0) {
dwEmuFlags |= DSE_FLAG_PAUSE;
Xb_rtTimeStamp = rtTimeStamp;
}
break;
case X_DSSPAUSE_SYNCHPLAYBACK:
//TODO: Test case Rayman 3 - Hoodlum Havoc, Battlestar Galactica, Miami Vice, Star Wars: KotOR, and... ?
Expand All @@ -867,8 +869,13 @@ static inline HRESULT HybridDirectSoundBuffer_Pause(
pDSBuffer->Stop();
}
break;
// TODO: NOTE: If stream is playing, it perform same behavior as pause flag. If it is not played, it act as a queue until trigger to play it.
// NOTE: If stream is paused with packets, it will trigger to play. If it is not played, it act as a queue until trigger to play it.
case X_DSSPAUSE_PAUSENOACTIVATE:
dwEmuFlags &= ~DSE_FLAG_PAUSE;
if ((dwEmuFlags & DSE_FLAG_IS_ACTIVATED) == 0) {
dwEmuFlags |= DSE_FLAG_PAUSENOACTIVATE;
Xb_rtTimeStamp = rtTimeStamp;
}
break;
}

Expand Down

0 comments on commit efee57a

Please sign in to comment.