diff --git a/src/core/hle/DSOUND/DirectSound/DirectSound.cpp b/src/core/hle/DSOUND/DirectSound/DirectSound.cpp index fa94b1661..d1d9950e1 100644 --- a/src/core/hle/DSOUND/DirectSound/DirectSound.cpp +++ b/src/core/hle/DSOUND/DirectSound/DirectSound.cpp @@ -719,11 +719,11 @@ HRESULT WINAPI XTL::EMUPATCH(IDirectSoundBuffer_SetMixBins) LOG_FUNC_ARG(pMixBins) LOG_FUNC_END; - LOG_UNIMPLEMENTED(); + HRESULT hRet = HybridDirectSoundBuffer_SetMixBins(pThis->Xb_VoiceProperties, pMixBins, pThis->EmuBufferDesc.lpwfxFormat, pThis->EmuBufferDesc); leaveCriticalSection; - return DS_OK; + return hRet; } // ****************************************************************** @@ -768,7 +768,7 @@ HRESULT WINAPI XTL::EMUPATCH(IDirectSoundBuffer_SetMixBinVolumes_8) LOG_FUNC_ARG(pMixBins) LOG_FUNC_END; - return HybridDirectSoundBuffer_SetMixBinVolumes_8(pThis->EmuDirectSoundBuffer8, pMixBins, pThis->EmuFlags, pThis->Xb_Volume, pThis->Xb_VolumeMixbin, pThis->Xb_dwHeadroom); + return HybridDirectSoundBuffer_SetMixBinVolumes_8(pThis->EmuDirectSoundBuffer8, pMixBins, pThis->Xb_VoiceProperties, pThis->EmuFlags, pThis->Xb_Volume, pThis->Xb_VolumeMixbin, pThis->Xb_dwHeadroom); } // ****************************************************************** @@ -932,7 +932,8 @@ HRESULT WINAPI XTL::EMUPATCH(DirectSoundCreateBuffer) DSoundBufferRegionSetDefault(*ppBuffer); // We have to set DSBufferDesc last due to EmuFlags must be either 0 or previously written value to preserve other flags. - GeneratePCMFormat(DSBufferDesc, pdsbd->lpwfxFormat, (*ppBuffer)->EmuFlags, pdsbd->dwBufferBytes, &(*ppBuffer)->X_BufferCache, (*ppBuffer)->X_BufferCacheSize); + GeneratePCMFormat(DSBufferDesc, pdsbd->lpwfxFormat, (*ppBuffer)->EmuFlags, pdsbd->dwBufferBytes, + &(*ppBuffer)->X_BufferCache, (*ppBuffer)->X_BufferCacheSize, (*ppBuffer)->Xb_VoiceProperties, pdsbd->lpMixBinsOutput); (*ppBuffer)->EmuBufferDesc = DSBufferDesc; EmuLog(LOG_LEVEL::DEBUG, "DirectSoundCreateBuffer, *ppBuffer := 0x%08X, bytes := 0x%08X", *ppBuffer, (*ppBuffer)->EmuBufferDesc.dwBufferBytes); @@ -1727,7 +1728,8 @@ HRESULT WINAPI XTL::EMUPATCH(DirectSoundCreateStream) (*ppStream)->Xb_rtFlushEx = 0LL; // We have to set DSBufferDesc last due to EmuFlags must be either 0 or previously written value to preserve other flags. - GeneratePCMFormat(DSBufferDesc, pdssd->lpwfxFormat, (*ppStream)->EmuFlags, 0, xbnullptr, (*ppStream)->X_BufferCacheSize); + GeneratePCMFormat(DSBufferDesc, pdssd->lpwfxFormat, (*ppStream)->EmuFlags, 0, + xbnullptr, (*ppStream)->X_BufferCacheSize, (*ppStream)->Xb_VoiceProperties, pdssd->lpMixBinsOutput); // Test case: Star Wars: KotOR has one packet greater than 5 seconds worth. Increasing to 10 seconds works out fine, can increase more if need to. // Allocate at least 10 second worth of bytes in PCM format. @@ -2409,11 +2411,11 @@ HRESULT WINAPI XTL::EMUPATCH(CDirectSoundStream_SetMixBins) LOG_FUNC_ARG(pMixBins) LOG_FUNC_END; - LOG_UNIMPLEMENTED(); + HRESULT hRet = HybridDirectSoundBuffer_SetMixBins(pThis->Xb_VoiceProperties, pMixBins, pThis->EmuBufferDesc.lpwfxFormat, pThis->EmuBufferDesc); leaveCriticalSection; - return S_OK; + return hRet; } // s+ @@ -2688,7 +2690,8 @@ HRESULT WINAPI XTL::EMUPATCH(IDirectSoundBuffer_SetFormat) HRESULT hRet = HybridDirectSoundBuffer_SetFormat(pThis->EmuDirectSoundBuffer8, pwfxFormat, pThis->EmuBufferDesc, pThis->EmuFlags, pThis->EmuPlayFlags, pThis->EmuDirectSound3DBuffer8, - 0, pThis->X_BufferCache, pThis->X_BufferCacheSize); + 0, pThis->X_BufferCache, pThis->X_BufferCacheSize, + pThis->Xb_VoiceProperties, xbnullptr); leaveCriticalSection; @@ -3285,7 +3288,7 @@ HRESULT WINAPI XTL::EMUPATCH(CDirectSoundStream_SetMixBinVolumes_8) LOG_FUNC_ARG(pMixBins) LOG_FUNC_END; - return HybridDirectSoundBuffer_SetMixBinVolumes_8(pThis->EmuDirectSoundBuffer8, pMixBins, pThis->EmuFlags, pThis->Xb_Volume, pThis->Xb_VolumeMixbin, pThis->Xb_dwHeadroom); + return HybridDirectSoundBuffer_SetMixBinVolumes_8(pThis->EmuDirectSoundBuffer8, pMixBins, pThis->Xb_VoiceProperties, pThis->EmuFlags, pThis->Xb_Volume, pThis->Xb_VolumeMixbin, pThis->Xb_dwHeadroom); } // ****************************************************************** @@ -3359,7 +3362,8 @@ HRESULT WINAPI XTL::EMUPATCH(CDirectSoundStream_SetFormat) HRESULT hRet = HybridDirectSoundBuffer_SetFormat(pThis->EmuDirectSoundBuffer8, pwfxFormat, pThis->EmuBufferDesc, pThis->EmuFlags, pThis->EmuPlayFlags, pThis->EmuDirectSound3DBuffer8, - 0, pThis->X_BufferCache, pThis->X_BufferCacheSize); + 0, pThis->X_BufferCache, pThis->X_BufferCacheSize, + pThis->Xb_VoiceProperties, xbnullptr); leaveCriticalSection; @@ -4105,8 +4109,6 @@ HRESULT WINAPI XTL::EMUPATCH(IDirectSoundBuffer_GetVoiceProperties) X_CDirectSoundBuffer* pThis, OUT X_DSVOICEPROPS* pVoiceProps) { - enterCriticalSection; - LOG_FUNC_BEGIN LOG_FUNC_ARG(pThis) LOG_FUNC_ARG_OUT(pVoiceProps) @@ -4116,30 +4118,8 @@ HRESULT WINAPI XTL::EMUPATCH(IDirectSoundBuffer_GetVoiceProperties) LOG_TEST_CASE("pVoiceProps == xbnullptr"); RETURN(DS_OK); } - - // HACK: Set values that are known to prevent crashes/hangs - // TODO: Investigate and implement proper mixbin functionality - pVoiceProps->dwMixBinCount = 2; - pVoiceProps->l3DConeVolume = 0; - pVoiceProps->l3DDistanceVolume = 0; - pVoiceProps->l3DDopplerPitch = 0; - pVoiceProps->lI3DL2DirectVolume = 0; - pVoiceProps->lI3DL2RoomVolume = 0; - pVoiceProps->lPitch = -4597; - - for (int i = 0; i < 8; i++) { - if (i < pVoiceProps->dwMixBinCount) { - pVoiceProps->MixBinVolumePairs[i].dwMixBin = i; - pVoiceProps->MixBinVolumePairs[i].lVolume = 0; - } else { - pVoiceProps->MixBinVolumePairs[i].dwMixBin = 0xFFFFFFFF; - pVoiceProps->MixBinVolumePairs[i].lVolume = -10000; - } - } - leaveCriticalSection; - - return DS_OK; + return HybridDirectSoundBuffer_GetVoiceProperties(pThis->Xb_VoiceProperties, pVoiceProps); } // ****************************************************************** @@ -4151,9 +4131,7 @@ HRESULT WINAPI XTL::EMUPATCH(CDirectSoundStream_GetVoiceProperties) OUT X_DSVOICEPROPS* pVoiceProps ) { - enterCriticalSection; - - LOG_FUNC_BEGIN + LOG_FUNC_BEGIN LOG_FUNC_ARG(pThis) LOG_FUNC_ARG_OUT(pVoiceProps) LOG_FUNC_END; @@ -4163,29 +4141,7 @@ HRESULT WINAPI XTL::EMUPATCH(CDirectSoundStream_GetVoiceProperties) RETURN(DS_OK); } - // HACK: Set values that are known to prevent crashes/hangs - // TODO: Investigate and implement proper mixbin functionality - pVoiceProps->dwMixBinCount = 2; - pVoiceProps->l3DConeVolume = 0; - pVoiceProps->l3DDistanceVolume = 0; - pVoiceProps->l3DDopplerPitch = 0; - pVoiceProps->lI3DL2DirectVolume = 0; - pVoiceProps->lI3DL2RoomVolume = 0; - pVoiceProps->lPitch = -4597; - - for (int i = 0; i < 8; i++) { - if (i < pVoiceProps->dwMixBinCount) { - pVoiceProps->MixBinVolumePairs[i].dwMixBin = i; - pVoiceProps->MixBinVolumePairs[i].lVolume = 0; - } else { - pVoiceProps->MixBinVolumePairs[i].dwMixBin = 0xFFFFFFFF; - pVoiceProps->MixBinVolumePairs[i].lVolume = -10000; - } - } - - leaveCriticalSection; - - return DS_OK; + return HybridDirectSoundBuffer_GetVoiceProperties(pThis->Xb_VoiceProperties, pVoiceProps); } // ****************************************************************** diff --git a/src/core/hle/DSOUND/DirectSound/DirectSoundInline.hpp b/src/core/hle/DSOUND/DirectSound/DirectSoundInline.hpp index 3996b336e..88d460ee8 100644 --- a/src/core/hle/DSOUND/DirectSound/DirectSoundInline.hpp +++ b/src/core/hle/DSOUND/DirectSound/DirectSoundInline.hpp @@ -316,10 +316,14 @@ inline void GeneratePCMFormat( DWORD &dwEmuFlags, DWORD X_BufferSizeRequest, LPVOID* X_BufferCache, - DWORD &X_BufferCacheSize) + DWORD &X_BufferCacheSize, + XTL::X_DSVOICEPROPS& Xb_VoiceProperties, + XTL::X_LPDSMIXBINS mixbins_output) { bool bIsSpecial = false; DWORD checkAvgBps; + + GenerateMixBinDefault(Xb_VoiceProperties, lpwfxFormat, mixbins_output, ((DSBufferDesc.dwFlags & DSBCAPS_CTRL3D) > 0)); // convert from Xbox to PC DSound { @@ -1475,7 +1479,9 @@ inline HRESULT HybridDirectSoundBuffer_SetFormat( LPDIRECTSOUND3DBUFFER8 &pDS3DBuffer, bool X_BufferAllocate, LPVOID &X_BufferCache, - DWORD &X_BufferCacheSize) + DWORD &X_BufferCacheSize, + XTL::X_DSVOICEPROPS &Xb_VoiceProperties, + XTL::X_LPDSMIXBINS mixbins_output) { enterCriticalSection; @@ -1483,10 +1489,10 @@ inline HRESULT HybridDirectSoundBuffer_SetFormat( pDSBuffer->Stop(); if (X_BufferAllocate) { - GeneratePCMFormat(BufferDesc, pwfxFormat, dwEmuFlags, X_BufferCacheSize, xbnullptr, X_BufferCacheSize); + GeneratePCMFormat(BufferDesc, pwfxFormat, dwEmuFlags, X_BufferCacheSize, xbnullptr, X_BufferCacheSize, Xb_VoiceProperties, mixbins_output); // Don't allocate for DS Stream class, it is using straight from the source. } else { - GeneratePCMFormat(BufferDesc, pwfxFormat, dwEmuFlags, 0, xbnullptr, X_BufferCacheSize); + GeneratePCMFormat(BufferDesc, pwfxFormat, dwEmuFlags, 0, xbnullptr, X_BufferCacheSize, Xb_VoiceProperties, mixbins_output); } HRESULT hRet = DS_OK; if (g_pDSoundPrimaryBuffer == pDSBuffer) { @@ -1645,6 +1651,7 @@ inline HRESULT HybridDirectSoundBuffer_SetMixBins( inline HRESULT HybridDirectSoundBuffer_SetMixBinVolumes_8( LPDIRECTSOUNDBUFFER8 pDSBuffer, XTL::X_LPDSMIXBINS pMixBins, + XTL::X_DSVOICEPROPS& Xb_VoiceProperties, DWORD EmuFlags, LONG Xb_volume, LONG &Xb_volumeMixBin, @@ -1660,6 +1667,21 @@ inline HRESULT HybridDirectSoundBuffer_SetMixBinVolumes_8( if (pMixBins->lpMixBinVolumePairs != xbnullptr) { // Let's normalize audio level except for low frequency (subwoofer) for (DWORD i = 0; i < count; i++) { + // Update the mixbin volume only, do not reassign volume pair array. + for (DWORD i = 0; i < count; i++) { + auto& it_in = pMixBins->lpMixBinVolumePairs[i]; + for (DWORD ii = 0; ii < Xb_VoiceProperties.dwMixBinCount; ii++) { + auto& it_internal = Xb_VoiceProperties.MixBinVolumePairs[ii]; + + // Once found a match, set the volume. + // NOTE If titles input duplicate with different volume, + // it will override previous value. + if (it_in.dwMixBin == it_internal.dwMixBin) { + it_internal.lVolume = it_in.lVolume; + } + } + } + #if 0 // This code isn't ideal for DirectSound, since it's not possible to set volume for each speakers. if (pMixBins->lpMixBinVolumePairs[i].dwMixBin != XDSMIXBIN_LOW_FREQUENCY // We only want to focus on speaker volumes, nothing else.