Merge pull request #1983 from CookiePLMonster/mixbin-improvements

Improvements to old style (mask based) mixbin
This commit is contained in:
RadWolfie 2020-10-11 09:27:58 -05:00 committed by GitHub
commit 216b5c274e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 104 additions and 61 deletions

View File

@ -493,7 +493,7 @@ xbox::hresult_xt WINAPI EMUPATCH(IDirectSound_SetMixBinHeadroom)
xbox::hresult_xt WINAPI EMUPATCH(IDirectSoundBuffer_SetMixBins)
(
XbHybridDSBuffer* pHybridThis,
dword_xt dwMixBinMask
X_DSMIXBINBUNION mixBins
);
// ******************************************************************
@ -974,7 +974,7 @@ xbox::hresult_xt WINAPI EMUPATCH(CDirectSoundStream_SetI3DL2Source)
xbox::hresult_xt WINAPI EMUPATCH(CDirectSoundStream_SetMixBins)
(
X_CDirectSoundStream* pThis,
dword_xt dwMixBinMask
X_DSMIXBINBUNION mixBins
);
// s+
@ -1681,7 +1681,7 @@ xbox::hresult_xt WINAPI EMUPATCH(IDirectSoundStream_SetFrequency)
xbox::hresult_xt WINAPI EMUPATCH(IDirectSoundStream_SetMixBins)
(
X_CDirectSoundStream* pThis,
dword_xt dwMixBinMask);
X_DSMIXBINBUNION mixBins);
// ******************************************************************
// * patch: CDirectSound3DCalculator_Calculate3D

View File

@ -224,7 +224,7 @@ xbox::hresult_xt WINAPI xbox::EMUPATCH(DirectSoundCreateBuffer)
// 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, (DWORD &)pdsbd->dwFlags, pEmuBuffer->EmuFlags, pdsbd->dwBufferBytes,
&pEmuBuffer->X_BufferCache, pEmuBuffer->X_BufferCacheSize, pEmuBuffer->Xb_VoiceProperties, pdsbd->lpMixBinsOutput,
&pEmuBuffer->X_BufferCache, pEmuBuffer->X_BufferCacheSize, pEmuBuffer->Xb_VoiceProperties, pdsbd->mixBinsOutput,
pHybridBuffer->p_CDSVoice);
pEmuBuffer->EmuBufferDesc = DSBufferDesc;
@ -1182,31 +1182,25 @@ xbox::hresult_xt WINAPI xbox::EMUPATCH(IDirectSoundBuffer_SetMinDistance)
xbox::hresult_xt WINAPI xbox::EMUPATCH(IDirectSoundBuffer_SetMixBins)
(
XbHybridDSBuffer* pHybridThis,
dword_xt dwMixBinMask)
X_DSMIXBINBUNION mixBins)
{
DSoundMutexGuardLock;
HRESULT hRet = DS_OK;
X_LPDSMIXBINS pMixBins = reinterpret_cast<X_LPDSMIXBINS>(dwMixBinMask);
if (g_LibVersion_DSOUND < 4039) {
LOG_FUNC_BEGIN
LOG_FUNC_ARG(pHybridThis)
LOG_FUNC_ARG(dwMixBinMask)
LOG_FUNC_ARG(mixBins.dwMixBinMask)
LOG_FUNC_END;
LOG_UNIMPLEMENTED();
}
else {
LOG_FUNC_BEGIN
LOG_FUNC_ARG(pHybridThis)
LOG_FUNC_ARG(pMixBins)
LOG_FUNC_ARG(mixBins.pMixBins)
LOG_FUNC_END;
EmuDirectSoundBuffer* pThis = pHybridThis->emuDSBuffer;
hRet = HybridDirectSoundBuffer_SetMixBins(pThis->Xb_VoiceProperties, pMixBins, pThis->EmuBufferDesc);
}
return hRet;
EmuDirectSoundBuffer* pThis = pHybridThis->emuDSBuffer;
return HybridDirectSoundBuffer_SetMixBins(pThis->Xb_VoiceProperties, mixBins, pThis->EmuBufferDesc);
}
// ******************************************************************
@ -1227,12 +1221,11 @@ xbox::hresult_xt WINAPI xbox::EMUPATCH(IDirectSoundBuffer_SetMixBinVolumes_12)
LOG_FUNC_ARG(alVolumes)
LOG_FUNC_END;
// NOTE: Use this function for XDK 3911 only because the implementation was changed
// somewhere around the December 2001 (4134) update (or earlier, maybe).
EmuDirectSoundBuffer* pThis = pHybridThis->emuDSBuffer;
HRESULT hRet = HybridDirectSoundBuffer_SetMixBinVolumes_12(pThis->EmuDirectSoundBuffer8, dwMixBinMask, alVolumes, pThis->Xb_VoiceProperties,
pThis->EmuFlags, pThis->Xb_VolumeMixbin, pHybridThis->p_CDSVoice);
LOG_UNIMPLEMENTED();
return DS_OK;
return hRet;
}
// ******************************************************************

View File

@ -134,22 +134,25 @@ static inline void InitVoiceProperties(xbox::X_DSVOICEPROPS& Xb_VoiceProperties)
static inline void GenerateMixBinDefault(
xbox::X_DSVOICEPROPS &Xb_VoiceProperties,
::LPCWAVEFORMATEX lpwfxFormat,
xbox::X_LPDSMIXBINS mixbins_output,
xbox::X_DSMIXBINBUNION mixbins_output,
bool is3D)
{
std::unique_ptr<xbox::DSOUND::CMixBinConverter> convertedMixBins;
if (g_LibVersion_DSOUND < 4039) {
// Do not apply any update since below 4039 doesn't provide access to get properties.
return;
// Convert old style mixbin to a new style mixbin
convertedMixBins = std::make_unique<xbox::DSOUND::CMixBinConverter>(mixbins_output.dwMixBinMask, nullptr);
mixbins_output.pMixBins = convertedMixBins->GetMixBins();
}
auto& xb_mixbinArray = Xb_VoiceProperties.MixBinVolumePairs;
unsigned int i;
// Use custom mixbin if provided.
if (mixbins_output != xbox::zeroptr) {
if (mixbins_output.pMixBins != xbox::zeroptr) {
Xb_VoiceProperties.dwMixBinCount = mixbins_output->dwCount;
auto& mixbinArray_output = mixbins_output->lpMixBinVolumePairs;
Xb_VoiceProperties.dwMixBinCount = mixbins_output.pMixBins->dwCount;
auto& mixbinArray_output = mixbins_output.pMixBins->lpMixBinVolumePairs;
for (i = 0; i < Xb_VoiceProperties.dwMixBinCount; i++) {
xb_mixbinArray[i].dwMixBin = mixbinArray_output[i].dwMixBin;
@ -254,7 +257,7 @@ static inline void GeneratePCMFormat(
LPVOID* X_BufferCache,
DWORD &X_BufferCacheSize,
xbox::X_DSVOICEPROPS& Xb_VoiceProperties,
xbox::X_LPDSMIXBINS mixbins_output,
xbox::X_DSMIXBINBUNION mixbins_output,
xbox::CDirectSoundVoice* Xb_Voice)
{
bool bIsSpecial = false;
@ -1124,13 +1127,16 @@ static inline HRESULT HybridDirectSoundBuffer_SetFormat(
{
pDSBuffer->Stop();
xbox::X_DSMIXBINBUNION mixBins;
mixBins.pMixBins = mixbins_output;
if (X_BufferAllocate) {
GeneratePCMFormat(BufferDesc, Xb_pwfxFormat, Xb_flags, dwEmuFlags, X_BufferCacheSize,
xbox::zeroptr, X_BufferCacheSize, Xb_VoiceProperties, mixbins_output, Xb_Voice);
xbox::zeroptr, X_BufferCacheSize, Xb_VoiceProperties, mixBins, Xb_Voice);
// Don't allocate for DS Stream class, it is using straight from the source.
} else {
GeneratePCMFormat(BufferDesc, Xb_pwfxFormat, Xb_flags, dwEmuFlags, 0,
xbox::zeroptr, X_BufferCacheSize, Xb_VoiceProperties, mixbins_output, Xb_Voice);
xbox::zeroptr, X_BufferCacheSize, Xb_VoiceProperties, mixBins, Xb_Voice);
}
HRESULT hRet = DS_OK;
if ((void*)g_pDSoundPrimaryBuffer == (void*)pDSBuffer) {
@ -1260,13 +1266,13 @@ static inline HRESULT HybridDirectSound3DBuffer_SetMinDistance(
//IDirectSoundBuffer
static inline HRESULT HybridDirectSoundBuffer_SetMixBins(
xbox::X_DSVOICEPROPS& Xb_VoiceProperties,
xbox::X_LPDSMIXBINS in_MixBins,
xbox::X_DSMIXBINBUNION mixBins,
DSBUFFERDESC& BufferDesc
)
{
HRESULT ret = DS_OK;
GenerateMixBinDefault(Xb_VoiceProperties, BufferDesc.lpwfxFormat, in_MixBins, ((BufferDesc.dwFlags & DSBCAPS_CTRL3D) > 0));
GenerateMixBinDefault(Xb_VoiceProperties, BufferDesc.lpwfxFormat, mixBins, ((BufferDesc.dwFlags & DSBCAPS_CTRL3D) > 0));
return ret;
}
@ -1275,7 +1281,7 @@ static inline HRESULT HybridDirectSoundBuffer_SetMixBins(
//IDirectSoundBuffer x2
static inline HRESULT HybridDirectSoundBuffer_SetMixBinVolumes_8(
LPDIRECTSOUNDBUFFER8 pDSBuffer,
xbox::X_LPDSMIXBINS pMixBins,
xbox::X_LPDSMIXBINS pMixBins,
xbox::X_DSVOICEPROPS& Xb_VoiceProperties,
DWORD EmuFlags,
LONG &Xb_volumeMixBin,
@ -1291,7 +1297,7 @@ static inline HRESULT HybridDirectSoundBuffer_SetMixBinVolumes_8(
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];
const auto& it_in = pMixBins->lpMixBinVolumePairs[i];
for (DWORD ii = 0; ii < Xb_VoiceProperties.dwMixBinCount; ii++) {
auto& it_internal = Xb_VoiceProperties.MixBinVolumePairs[ii];
@ -1319,7 +1325,7 @@ static inline HRESULT HybridDirectSoundBuffer_SetMixBinVolumes_8(
}
if (counter > 0) {
Xb_volumeMixBin = volume / (LONG)counter;
int32_t Xb_volume = Xb_Voice->GetVolume();
int32_t Xb_volume = Xb_Voice->GetVolume() + Xb_Voice->GetHeadroom();
hRet = HybridDirectSoundBuffer_SetVolume(pDSBuffer, Xb_volume, EmuFlags,
Xb_volumeMixBin, Xb_Voice);
} else {
@ -1331,6 +1337,23 @@ static inline HRESULT HybridDirectSoundBuffer_SetMixBinVolumes_8(
return hRet;
}
//IDirectSoundStream x2
//IDirectSoundBuffer x2
static inline HRESULT HybridDirectSoundBuffer_SetMixBinVolumes_12(
LPDIRECTSOUNDBUFFER8 pDSBuffer,
xbox::dword_xt dwMixBinMask,
const xbox::long_xt* alVolumes,
xbox::X_DSVOICEPROPS& Xb_VoiceProperties,
DWORD EmuFlags,
LONG &Xb_volumeMixBin,
xbox::CDirectSoundVoice* Xb_Voice)
{
// Convert volumes/mask to xbox::X_DSMIXBINS and call the newer version of the function to keep implementations consistent
xbox::DSOUND::CMixBinConverter convertedMixBins(dwMixBinMask, alVolumes);
return HybridDirectSoundBuffer_SetMixBinVolumes_8(pDSBuffer, convertedMixBins.GetMixBins(), Xb_VoiceProperties, EmuFlags, Xb_volumeMixBin, Xb_Voice);
}
//IDirectSoundStream
//IDirectSoundBuffer
static inline HRESULT HybridDirectSound3DBuffer_SetMode(

View File

@ -233,7 +233,7 @@ xbox::hresult_xt WINAPI xbox::EMUPATCH(DirectSoundCreateStream)
// 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, (DWORD &)pdssd->dwFlags, (*ppStream)->EmuFlags, 0,
xbox::zeroptr, (*ppStream)->X_BufferCacheSize, (*ppStream)->Xb_VoiceProperties, pdssd->lpMixBinsOutput,
xbox::zeroptr, (*ppStream)->X_BufferCacheSize, (*ppStream)->Xb_VoiceProperties, pdssd->mixBinsOutput,
&(*ppStream)->Xb_Voice);
// Test case: Star Wars: KotOR has one packet greater than 5 seconds worth. Increasing to 10 seconds allow stream to work until
@ -1105,31 +1105,24 @@ xbox::hresult_xt WINAPI xbox::EMUPATCH(CDirectSoundStream_SetMinDistance)
xbox::hresult_xt WINAPI xbox::EMUPATCH(CDirectSoundStream_SetMixBins)
(
X_CDirectSoundStream* pThis,
dword_xt dwMixBinMask) // Also can be X_LPDSMIXBINS (4039+)
X_DSMIXBINBUNION mixBins) // Can be dword_xt (up to 4039) or X_LPDSMIXBINS (4039+)
{
DSoundMutexGuardLock;
HRESULT hRet = DS_OK;
X_LPDSMIXBINS pMixBins = reinterpret_cast<X_LPDSMIXBINS>(dwMixBinMask);
if (g_LibVersion_DSOUND < 4039) {
LOG_FUNC_BEGIN
LOG_FUNC_ARG(pThis)
LOG_FUNC_ARG(dwMixBinMask)
LOG_FUNC_ARG(mixBins.dwMixBinMask)
LOG_FUNC_END;
LOG_UNIMPLEMENTED();
}
else {
LOG_FUNC_BEGIN
LOG_FUNC_ARG(pThis)
LOG_FUNC_ARG(pMixBins)
LOG_FUNC_ARG(mixBins.pMixBins)
LOG_FUNC_END;
hRet = HybridDirectSoundBuffer_SetMixBins(pThis->Xb_VoiceProperties, pMixBins, pThis->EmuBufferDesc);
}
return hRet;
return HybridDirectSoundBuffer_SetMixBins(pThis->Xb_VoiceProperties, mixBins, pThis->EmuBufferDesc);
}
// ******************************************************************
@ -1138,13 +1131,13 @@ xbox::hresult_xt WINAPI xbox::EMUPATCH(CDirectSoundStream_SetMixBins)
xbox::hresult_xt WINAPI xbox::EMUPATCH(IDirectSoundStream_SetMixBins)
(
X_CDirectSoundStream* pThis,
dword_xt dwMixBinMask) // Also can be X_LPDSMIXBINS (4039+)
X_DSMIXBINBUNION mixBins) // Can be dword_xt (up to 4039) or X_LPDSMIXBINS (4039+)
{
DSoundMutexGuardLock;
LOG_FORWARD("CDirectSoundStream_SetMixBins");
return xbox::EMUPATCH(CDirectSoundStream_SetMixBins)(pThis, dwMixBinMask);
return xbox::EMUPATCH(CDirectSoundStream_SetMixBins)(pThis, mixBins);
}
// ******************************************************************
@ -1187,12 +1180,10 @@ xbox::hresult_xt WINAPI xbox::EMUPATCH(CDirectSoundStream_SetMixBinVolumes_12)
LOG_FUNC_ARG(alVolumes)
LOG_FUNC_END;
// NOTE: Use this function for XDK 3911 only because the implementation was changed
// somewhere around the March 2002 (4361) update (or earlier, maybe).
HRESULT hRet = HybridDirectSoundBuffer_SetMixBinVolumes_12(pThis->EmuDirectSoundBuffer8, dwMixBinMask, alVolumes, pThis->Xb_VoiceProperties,
pThis->EmuFlags, pThis->Xb_VolumeMixbin, &pThis->Xb_Voice);
LOG_UNIMPLEMENTED();
return S_OK;
return hRet;
}
// ******************************************************************

View File

@ -38,5 +38,35 @@ namespace xbox {
return 2; // Default to stereo channel
}
// A helper class, converting old (pre-XDK 4039) mixbin format to the new (XDK 4039 and newer) format
class CMixBinConverter
{
public:
CMixBinConverter(xbox::dword_xt dwMixBinMask, const xbox::long_xt* alVolumes) {
if (dwMixBinMask != 0) {
for (unsigned int i = 0; i < 32; i++) {
if ((dwMixBinMask & (1 << i)) != 0) {
xbox::X_DSMIXBINVOLUMEPAIR pair { i, alVolumes != nullptr ? *alVolumes++ : 0 };
m_volumePairs.emplace_back(pair);
}
}
m_mixBins.dwCount = static_cast<xbox::dword_xt>(m_volumePairs.size());
m_mixBins.lpMixBinVolumePairs = m_volumePairs.data();
}
else {
m_mixBins.dwCount = 0;
m_mixBins.lpMixBinVolumePairs = nullptr;
}
}
xbox::X_LPDSMIXBINS GetMixBins() { return m_mixBins.dwCount != 0 ? &m_mixBins : nullptr; }
private:
std::vector<xbox::X_DSMIXBINVOLUMEPAIR> m_volumePairs;
xbox::X_DSMIXBINS m_mixBins;
};
}
}

View File

@ -358,7 +358,7 @@ LOGRENDER(X_DSBUFFERDESC)
LOGRENDER_MEMBER_TYPE(DSBCAPS_FLAG, dwFlags)
LOGRENDER_MEMBER(dwBufferBytes)
LOGRENDER_MEMBER_TYPE(LPWAVEFORMATEX, lpwfxFormat)
LOGRENDER_MEMBER_TYPE(DWORD, lpMixBinsOutput)
LOGRENDER_MEMBER(mixBinsOutput.dwMixBinMask)
LOGRENDER_MEMBER(dwInputMixBin)
;
}
@ -368,7 +368,7 @@ LOGRENDER(X_DSBUFFERDESC)
LOGRENDER_MEMBER_TYPE(DSBCAPS_FLAG, dwFlags)
LOGRENDER_MEMBER(dwBufferBytes)
LOGRENDER_MEMBER_TYPE(LPWAVEFORMATEX, lpwfxFormat)
LOGRENDER_MEMBER(lpMixBinsOutput)
LOGRENDER_MEMBER(mixBinsOutput.pMixBins)
LOGRENDER_MEMBER(dwInputMixBin)
;
}
@ -384,7 +384,7 @@ LOGRENDER(X_DSSTREAMDESC)
LOGRENDER_MEMBER_TYPE(LPWAVEFORMATEX, lpwfxFormat)
LOGRENDER_MEMBER_TYPE(void*, lpfnCallback)
LOGRENDER_MEMBER(lpvContext)
LOGRENDER_MEMBER_TYPE(DWORD, lpMixBinsOutput)
LOGRENDER_MEMBER(mixBinsOutput.dwMixBinMask)
;
}
else {
@ -394,7 +394,7 @@ LOGRENDER(X_DSSTREAMDESC)
LOGRENDER_MEMBER_TYPE(LPWAVEFORMATEX, lpwfxFormat)
LOGRENDER_MEMBER_TYPE(void*, lpfnCallback)
LOGRENDER_MEMBER(lpvContext)
LOGRENDER_MEMBER(lpMixBinsOutput)
LOGRENDER_MEMBER(mixBinsOutput.pMixBins)
;
}
}

View File

@ -85,6 +85,12 @@ typedef struct _XDSMIXBINS {
X_LPDSMIXBINVOLUMEPAIR lpMixBinVolumePairs;
} X_DSMIXBINS, *X_LPDSMIXBINS;
// A convenience union combining Revision 1 (3911-4034) and Revision 2 (4039+) mixbin function parameters
union X_DSMIXBINBUNION {
dword_xt dwMixBinMask;
X_LPDSMIXBINS pMixBins;
};
// EmuIDirectSoundBuffer_Play flags
#define X_DSBPLAY_LOOPING 0x00000001
#define X_DSBPLAY_FROMSTART 0x00000002
@ -149,7 +155,7 @@ struct X_DSBUFFERDESC
dword_xt dwFlags;
dword_xt dwBufferBytes;
LPWAVEFORMATEX lpwfxFormat;
X_LPDSMIXBINS lpMixBinsOutput;
X_DSMIXBINBUNION mixBinsOutput;
dword_xt dwInputMixBin;
};
@ -190,7 +196,7 @@ struct X_DSSTREAMDESC
LPWAVEFORMATEX lpwfxFormat;
LPFNXMOCALLBACK lpfnCallback;
LPVOID lpvContext;
X_LPDSMIXBINS lpMixBinsOutput;
X_DSMIXBINBUNION mixBinsOutput;
};
// ******************************************************************

View File

@ -117,7 +117,7 @@ uint32_t GetVolume(T& settings)
// Interface for set volume
template<class T>
void SetVolume(T& settings, uint32_t volume)
void SetVolume(T& settings, int32_t volume)
{
settings.volume = volume - settings.headroom;
}
@ -133,7 +133,7 @@ uint32_t GetHeadroom(T& settings)
template<class T>
void SetHeadroom(T& settings, uint32_t set_headroom)
{
settings.volume = settings.volume - set_headroom - settings.headroom;
settings.volume = settings.volume + settings.headroom - set_headroom;
settings.headroom = set_headroom;
}