Introduce DirectSoundStream fixes

XADPCM audio are much better now, need tester's ears to verify the
errors.

Test cases:
- Battlestar Galactica (sit back and enjoy the intro video! Get popcorns
too!)
- Rayman Arena (sounds about the same as original intended, before fps
was fixed)
- Ghost Recon (PCM, sound like no change)
- Taz: Wanted (sound like it is normal?)
- Turok Evolution (sound fine but video is little bit too slow?)

Testers, please test this for ANY functional intro videos (which uses
DirectSoundStream 85% of the time).
This commit is contained in:
RadWolfie 2018-03-13 17:26:48 -05:00
parent b5be48c4a1
commit db19158254
3 changed files with 66 additions and 38 deletions

View File

@ -460,13 +460,13 @@ VOID WINAPI XTL::EMUPATCH(DirectSoundDoWork)()
//TODO: This need a lock in each frame. I think it does not wait for each frame.
XTL::X_CDirectSoundBuffer* *pDSBuffer = g_pDSoundBufferCache;
for (int v = 0; v < SOUNDBUFFER_CACHE_SIZE; v++, pDSBuffer++) {
if ((*pDSBuffer) == nullptr || (*pDSBuffer)->EmuBuffer == nullptr || (*pDSBuffer)->EmuBufferToggle != X_DSB_TOGGLE_DEFAULT) {
if ((*pDSBuffer) == nullptr || (*pDSBuffer)->X_BufferCache == xbnullptr || (*pDSBuffer)->EmuBufferToggle != X_DSB_TOGGLE_DEFAULT) {
continue;
}
/* Bypass Update buffer, audio appear to be working just fine without need to update audio.
DSoundBufferUpdate((*pDSBuffer)->EmuDirectSoundBuffer8,
(*pDSBuffer)->EmuBufferDesc,
(*pDSBuffer)->EmuBuffer,
(*pDSBuffer)->X_BufferCache,
(*pDSBuffer)->EmuFlags,
(*pDSBuffer)->EmuLockOffset,
(*pDSBuffer)->EmuLockPtr1,
@ -491,12 +491,12 @@ VOID WINAPI XTL::EMUPATCH(DirectSoundDoWork)()
/*
XTL::X_CDirectSoundStream* *pDSStream = g_pDSoundStreamCache;
for (int v = 0; v < SOUNDSTREAM_CACHE_SIZE; v++, pDSStream++) {
if ((*pDSStream) == nullptr || (*pDSStream)->EmuBuffer == nullptr) {
if ((*pDSStream) == nullptr || (*pDSStream)->X_BufferCache == nullptr) {
continue;
}
DSoundBufferUpdate((*pDSStream)->EmuDirectSoundBuffer8,
(*pDSStream)->EmuBufferDesc,
(*pDSStream)->EmuBuffer,
(*pDSStream)->X_BufferCache,
(*pDSStream)->EmuFlags,
0,
(*pDSStream)->EmuLockPtr1,
@ -1004,12 +1004,15 @@ HRESULT WINAPI XTL::EMUPATCH(IDirectSoundBuffer_SetBufferData)
if (pThis->EmuLockPtr1 != xbnullptr) {
memcpy(pThis->EmuLockPtr1, pvBufferData, pThis->EmuLockBytes1);
// TODO: We could reduce allocate and free buffer if the size is the same.
if (pThis->EmuBuffer != xbnullptr) {
free(pThis->EmuBuffer);
// Increase allocate memory size only.
if (pThis->X_BufferCacheSize < dwBufferBytes) {
if (pThis->X_BufferCache != xbnullptr) {
free(pThis->X_BufferCache);
}
pThis->X_BufferCache = malloc(dwBufferBytes);
pThis->X_BufferCacheSize = dwBufferBytes;
}
pThis->EmuBuffer = malloc(dwBufferBytes);
memcpy(pThis->EmuBuffer, pvBufferData, dwBufferBytes);
memcpy(pThis->X_BufferCache, pvBufferData, dwBufferBytes);
}
DSoundGenericUnlock(pThis->EmuFlags,
@ -1089,11 +1092,19 @@ HRESULT WINAPI XTL::EMUPATCH(IDirectSoundBuffer_Lock)
HRESULT hRet = D3D_OK;
if (dwBytes > pThis->EmuBufferDesc->dwBufferBytes) {
if (pThis->EmuBuffer != xbnullptr) {
free(pThis->EmuBuffer);
pThis->EmuBuffer = xbnullptr;
if (dwBytes > pThis->X_BufferCacheSize) {
PVOID X_tempBuffer = pThis->X_BufferCache;
pThis->X_BufferCache = malloc(dwBytes);
if (X_tempBuffer != xbnullptr) {
memcpy(pThis->X_BufferCache, X_tempBuffer, pThis->X_BufferCacheSize);
free(X_tempBuffer);
}
pThis->X_BufferCacheSize = dwBytes;
}
if (dwBytes > pThis->EmuBufferDesc->dwBufferBytes) {
ResizeIDirectSoundBuffer(pThis->EmuDirectSoundBuffer8, pThis->EmuBufferDesc,
pThis->EmuPlayFlags, dwBytes, pThis->EmuDirectSound3DBuffer8);
DSoundBufferRegionRelease(pThis);
@ -1151,8 +1162,8 @@ HRESULT WINAPI XTL::EMUPATCH(IDirectSoundBuffer_Unlock)
LOG_FUNC_ARG(pdwAudioBytes2)
LOG_FUNC_END;
if (pThis->EmuBuffer != xbnullptr) {
memcpy_s((PBYTE)pThis->EmuBuffer + pThis->EmuLockOffset,
if (pThis->X_BufferCache != xbnullptr) {
memcpy_s((PBYTE)pThis->X_BufferCache + pThis->EmuLockOffset,
pThis->EmuBufferDesc->dwBufferBytes - pThis->EmuLockOffset,
pThis->EmuLockPtr1,
pThis->EmuLockBytes1);
@ -1263,8 +1274,9 @@ ULONG WINAPI XTL::EMUPATCH(IDirectSoundBuffer_Release)
if (pThis->EmuBufferDesc->lpwfxFormat != nullptr) {
free(pThis->EmuBufferDesc->lpwfxFormat);
}
if (pThis->EmuBuffer != xbnullptr) {
free(pThis->EmuBuffer);
if (pThis->X_BufferCache != xbnullptr) {
free(pThis->X_BufferCache);
pThis->X_BufferCacheSize = 0;
}
if (pThis->EmuDirectSoundBuffer8Region != nullptr) {
pThis->EmuDirectSoundBuffer8Region->Release();
@ -1469,7 +1481,7 @@ HRESULT WINAPI XTL::EMUPATCH(IDirectSoundBuffer_Play)
CxbxKrnlCleanup("Unable to lock region buffer!");
}
if (pThis->EmuLockPtr1 != xbnullptr) {
memcpy_s(pThis->EmuLockPtr1, pThis->EmuLockBytes1, (PVOID)((PBYTE)pThis->EmuBuffer + startOffset), byteLength);
memcpy_s(pThis->EmuLockPtr1, pThis->EmuLockBytes1, (PVOID)((PBYTE)pThis->X_BufferCache + startOffset), byteLength);
if (pThis->EmuFlags & DSB_FLAG_XADPCM) {
DSoundBufferXboxAdpcmDecoder(pThis->EmuDirectSoundBuffer8Region,
emuBufferDescRegion, 0, pThis->EmuLockPtr1,
@ -1840,7 +1852,7 @@ ULONG WINAPI XTL::EMUPATCH(CDirectSoundStream_Release)
if (pThis->EmuBufferDesc->lpwfxFormat != NULL) {
free(pThis->EmuBufferDesc->lpwfxFormat);
}
// NOTE: Do not release EmuBuffer! EmuBuffer is using xbox buffer.
// NOTE: Do not release X_BufferCache! X_BufferCache is using xbox buffer.
free(pThis->EmuBufferDesc);
delete pThis;
@ -1923,17 +1935,17 @@ HRESULT WINAPI XTL::EMUPATCH(CDirectSoundStream_Process)
if (pThis->EmuDirectSoundBuffer8 != nullptr) {
// update buffer data cache
pThis->EmuBuffer = pInputBuffer->pvBuffer;
pThis->X_BufferCache = pInputBuffer->pvBuffer;
ResizeIDirectSoundBuffer(pThis->EmuDirectSoundBuffer8, pThis->EmuBufferDesc,
pThis->EmuPlayFlags, pInputBuffer->dwMaxSize, pThis->EmuDirectSound3DBuffer8);
pThis->EmuPlayFlags, DSoundBufferGetPCMBufferSize(pThis, pInputBuffer->dwMaxSize), pThis->EmuDirectSound3DBuffer8);
if (pInputBuffer->pdwStatus != 0) {
*pInputBuffer->pdwStatus = S_OK;
}
PVOID pAudioPtr, pAudioPtr2;
DWORD dwAudioBytes, dwAudioBytes2;
PVOID pAudioPtr;
DWORD dwAudioBytes;
HRESULT hRet;
@ -1943,7 +1955,7 @@ HRESULT WINAPI XTL::EMUPATCH(CDirectSoundStream_Process)
DSoundBufferXboxAdpcmDecoder(pThis->EmuDirectSoundBuffer8,
pThis->EmuBufferDesc,
0,
pThis->EmuBuffer,
pThis->X_BufferCache,
pInputBuffer->dwMaxSize,
0,
0,
@ -1951,17 +1963,14 @@ HRESULT WINAPI XTL::EMUPATCH(CDirectSoundStream_Process)
} else {
hRet = pThis->EmuDirectSoundBuffer8->Lock(0, pThis->EmuBufferDesc->dwBufferBytes, &pAudioPtr, &dwAudioBytes,
&pAudioPtr2, &dwAudioBytes2, 0);
nullptr, nullptr, 0);
if (hRet == DS_OK) {
if (pAudioPtr != 0) {
memcpy(pAudioPtr, pThis->EmuBuffer, dwAudioBytes);
DSoundBufferOutputXBtoPC(pThis->EmuFlags, pThis->EmuBufferDesc, pThis->X_BufferCache, pInputBuffer->dwMaxSize, pAudioPtr, dwAudioBytes);
}
if (pAudioPtr2 != 0) {
memcpy(pAudioPtr2, (PVOID)((DWORD)pThis->EmuBuffer + dwAudioBytes), dwAudioBytes2);
}
pThis->EmuDirectSoundBuffer8->Unlock(pAudioPtr, dwAudioBytes, pAudioPtr2, dwAudioBytes2);
pThis->EmuDirectSoundBuffer8->Unlock(pAudioPtr, dwAudioBytes, nullptr, 0);
}
}
//TODO: RadWolfie - If remove this part, XADPCM audio will stay running, Rayman Arena, except...
@ -2046,7 +2055,7 @@ HRESULT WINAPI XTL::EMUPATCH(CDirectSound_SynchPlayback)
XTL::X_CDirectSoundBuffer* *pDSBuffer = g_pDSoundBufferCache;
for (int v = 0; v < SOUNDBUFFER_CACHE_SIZE; v++, pDSBuffer++) {
if ((*pDSBuffer) == nullptr || (*pDSBuffer)->EmuBuffer == nullptr) {
if ((*pDSBuffer) == nullptr || (*pDSBuffer)->X_BufferCache == nullptr) {
continue;
}
@ -2060,7 +2069,7 @@ HRESULT WINAPI XTL::EMUPATCH(CDirectSound_SynchPlayback)
XTL::X_CDirectSoundStream* *pDSStream = g_pDSoundStreamCache;
for (int v = 0; v < SOUNDSTREAM_CACHE_SIZE; v++, pDSStream++) {
if ((*pDSStream) == nullptr || (*pDSStream)->EmuBuffer == nullptr) {
if ((*pDSStream) == nullptr || (*pDSStream)->X_BufferCache == nullptr) {
continue;
}
if ((*pDSStream)->EmuFlags & DSB_FLAG_SYNCHPLAYBACK_CONTROL) {

View File

@ -305,7 +305,7 @@ struct X_CDirectSoundBuffer
};
BYTE UnknownB[0x0C]; // Offset: 0x24
PVOID EmuBuffer; // Offset: 0x28
PVOID X_BufferCache; // Offset: 0x28
DSBUFFERDESC* EmuBufferDesc; // Offset: 0x2C
PVOID EmuLockPtr1; // Offset: 0x30
DWORD EmuLockBytes1; // Offset: 0x34
@ -324,6 +324,7 @@ struct X_CDirectSoundBuffer
DWORD EmuRegionPlayLength;
LPDIRECTSOUNDBUFFER8 EmuDirectSoundBuffer8Region;
LPDIRECTSOUND3DBUFFER8 EmuDirectSound3DBuffer8Region;
DWORD X_BufferCacheSize;
};
#define WAVE_FORMAT_XBOX_ADPCM 0x0069
@ -439,7 +440,7 @@ class X_CDirectSoundStream
// cached data
LPDIRECTSOUNDBUFFER8 EmuDirectSoundBuffer8;
LPDIRECTSOUND3DBUFFER8 EmuDirectSound3DBuffer8;
PVOID EmuBuffer;
PVOID X_BufferCache;
LPDSBUFFERDESC EmuBufferDesc;
PVOID EmuLockPtr1;
DWORD EmuLockBytes1;
@ -447,6 +448,7 @@ class X_CDirectSoundStream
DWORD EmuLockBytes2;
DWORD EmuPlayFlags;
DWORD EmuFlags;
DWORD X_BufferCacheSize;
};
// ******************************************************************

View File

@ -89,9 +89,9 @@ void DSoundBufferXboxAdpcmDecoder(
}
// Attempt to decode Xbox ADPCM data to PCM
//EmuWarning( "Guessing output size to be 0x%X bytes as opposed to 0x%X bytes.", TXboxAdpcmDecoder_guess_output_size(dwAudioBytes), dwAudioBytes );
TXboxAdpcmDecoder_Decode_Memory((uint8_t*)pAudioPtr, dwAudioBytes, &buffer1[0], pDSBufferDesc->lpwfxFormat->nChannels);
TXboxAdpcmDecoder_Decode_Memory((uint8_t*)pAudioPtr, dwAudioBytes, buffer1, pDSBufferDesc->lpwfxFormat->nChannels);
if (dwAudioBytes2 != 0) {
TXboxAdpcmDecoder_Decode_Memory((uint8_t*)pAudioPtr2, dwAudioBytes2, &buffer2[0], pDSBufferDesc->lpwfxFormat->nChannels);
TXboxAdpcmDecoder_Decode_Memory((uint8_t*)pAudioPtr2, dwAudioBytes2, buffer2, pDSBufferDesc->lpwfxFormat->nChannels);
}
// Lock this Xbox ADPCM buffer
void* pPtrX = xbnullptr, *pPtrX2 = xbnullptr;
@ -134,6 +134,22 @@ void DSoundBufferXboxAdpcmDecoder(
if (buffer2) free(buffer2);
}
#define DSoundBufferGetPCMBufferSize(pThis, size) (pThis->EmuFlags & DSB_FLAG_XADPCM) > 0 ? TXboxAdpcmDecoder_guess_output_size(size) : size
void DSoundBufferOutputXBtoPC(DWORD emuFlags, DSBUFFERDESC* pDSBufferDesc, LPVOID pXBaudioPtr, DWORD dwXBAudioBytes, LPVOID pPCaudioPtr, DWORD dwPCMAudioBytes) {
if ((emuFlags & DSB_FLAG_XADPCM) > 0) {
DWORD dwDecodedAudioBytes = TXboxAdpcmDecoder_guess_output_size(dwXBAudioBytes) * pDSBufferDesc->lpwfxFormat->nChannels;
if (dwDecodedAudioBytes > dwPCMAudioBytes) dwDecodedAudioBytes = dwPCMAudioBytes;
TXboxAdpcmDecoder_Decode_Memory((uint8_t*)pXBaudioPtr, dwXBAudioBytes / pDSBufferDesc->lpwfxFormat->nChannels, (uint8_t*)pPCaudioPtr, pDSBufferDesc->lpwfxFormat->nChannels);
// PCM format, no changes requirement.
} else {
memcpy_s(pPCaudioPtr, dwPCMAudioBytes, pXBaudioPtr, dwPCMAudioBytes);
}
}
// Convert XADPCM to PCM format helper function
inline void XADPCM2PCMFormat(LPWAVEFORMATEX lpwfxFormat)
{
@ -399,14 +415,15 @@ inline void DSound3DBufferCreate(LPDIRECTSOUNDBUFFER8 pDSBuffer, LPDIRECTSOUND3D
#define DSoundBufferSetDefault(pThis, pdsd, dwEmuFlags, dwEmuPlayFlags) \
pThis->EmuDirectSoundBuffer8 = nullptr; \
pThis->EmuDirectSound3DBuffer8 = nullptr; \
pThis->EmuBuffer = xbnullptr; \
pThis->X_BufferCache = xbnullptr; \
pThis->EmuBufferDesc = pdsd; \
pThis->EmuLockPtr1 = xbnullptr; \
pThis->EmuLockBytes1 = 0; \
pThis->EmuLockPtr2 = xbnullptr; \
pThis->EmuLockBytes2 = 0; \
pThis->EmuFlags = dwEmuFlags; \
pThis->EmuPlayFlags = dwEmuPlayFlags;
pThis->EmuPlayFlags = dwEmuPlayFlags; \
pThis->X_BufferCacheSize = 0;
inline void DSoundBufferRegionSetDefault(XTL::X_CDirectSoundBuffer *pThis) {
pThis->EmuBufferToggle = XTL::X_DSB_TOGGLE_DEFAULT;