Merge pull request #1835 from RadWolfie/fix-wfx-format-sanity
Fix Sanity and Organize wfxformat into Functions
This commit is contained in:
commit
951520ece1
|
@ -141,6 +141,7 @@ file (GLOB CXBXR_HEADER_EMU
|
|||
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/XbState.h"
|
||||
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/XbVertexBuffer.h"
|
||||
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/XbVertexShader.h"
|
||||
"${CXBXR_ROOT_DIR}/src/core/hle/DSOUND/common/windows/WFXformat.hpp"
|
||||
"${CXBXR_ROOT_DIR}/src/core/hle/DSOUND/DirectSound/DirectSound.hpp"
|
||||
"${CXBXR_ROOT_DIR}/src/core/hle/DSOUND/DirectSound/DirectSoundGlobal.hpp"
|
||||
"${CXBXR_ROOT_DIR}/src/core/hle/DSOUND/DirectSound/DirectSoundInline.hpp"
|
||||
|
|
|
@ -109,6 +109,7 @@ struct X_CDirectSoundBuffer
|
|||
X_DSENVOLOPEDESC Xb_EnvolopeDesc;
|
||||
X_DSVOICEPROPS Xb_VoiceProperties;
|
||||
DWORD Xb_Frequency;
|
||||
DWORD Xb_Flags;
|
||||
};
|
||||
|
||||
//Custom flags (4 bytes support up to 31 shifts,starting from 0)
|
||||
|
@ -263,7 +264,8 @@ class X_CDirectSoundStream
|
|||
X_DSENVOLOPEDESC Xb_EnvolopeDesc;
|
||||
X_DSVOICEPROPS Xb_VoiceProperties;
|
||||
DWORD Xb_Frequency;
|
||||
DWORD Host_dwLastWritePos;
|
||||
DWORD Host_dwLastWritePos;
|
||||
DWORD Xb_Flags;
|
||||
};
|
||||
|
||||
// ******************************************************************
|
||||
|
|
|
@ -205,14 +205,14 @@ HRESULT WINAPI XTL::EMUPATCH(DirectSoundCreateBuffer)
|
|||
// TODO: Garbage Collection
|
||||
*ppBuffer = new X_CDirectSoundBuffer();
|
||||
|
||||
DSoundBufferSetDefault((*ppBuffer), 0);
|
||||
DSoundBufferSetDefault((*ppBuffer), 0, pdsbd->dwFlags);
|
||||
(*ppBuffer)->Host_lock = { 0 };
|
||||
(*ppBuffer)->Xb_rtStopEx = 0LL;
|
||||
|
||||
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,
|
||||
GeneratePCMFormat(DSBufferDesc, pdsbd->lpwfxFormat, pdsbd->dwFlags, (*ppBuffer)->EmuFlags, pdsbd->dwBufferBytes,
|
||||
&(*ppBuffer)->X_BufferCache, (*ppBuffer)->X_BufferCacheSize, (*ppBuffer)->Xb_VoiceProperties, pdsbd->lpMixBinsOutput);
|
||||
(*ppBuffer)->EmuBufferDesc = DSBufferDesc;
|
||||
|
||||
|
@ -929,8 +929,8 @@ HRESULT WINAPI XTL::EMUPATCH(IDirectSoundBuffer_SetFormat)
|
|||
LOG_FUNC_ARG(pwfxFormat)
|
||||
LOG_FUNC_END;
|
||||
|
||||
HRESULT hRet = HybridDirectSoundBuffer_SetFormat(pThis->EmuDirectSoundBuffer8, pwfxFormat,
|
||||
pThis->EmuBufferDesc, pThis->EmuFlags,
|
||||
HRESULT hRet = HybridDirectSoundBuffer_SetFormat(pThis->EmuDirectSoundBuffer8, pwfxFormat, pThis->Xb_Flags,
|
||||
pThis->EmuBufferDesc, pThis->EmuFlags,
|
||||
pThis->EmuPlayFlags, pThis->EmuDirectSound3DBuffer8,
|
||||
0, pThis->X_BufferCache, pThis->X_BufferCacheSize,
|
||||
pThis->Xb_VoiceProperties, xbnullptr, pThis->Xb_Frequency);
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "common/XADPCM.h"
|
||||
#include "core/hle/DSOUND/XbDSoundTypes.h"
|
||||
#include "core/hle/DSOUND/common/windows/WFXformat.hpp"
|
||||
|
||||
#include <mmreg.h>
|
||||
|
||||
|
@ -85,75 +86,6 @@ static void DSoundBufferOutputXBtoHost(DWORD emuFlags, DSBUFFERDESC &DSBufferDes
|
|||
}
|
||||
}
|
||||
|
||||
// Convert XADPCM to PCM format helper function
|
||||
static inline void XADPCM2PCMFormat(LPWAVEFORMATEX lpwfxFormat)
|
||||
{
|
||||
|
||||
#if 0 //For testing purpose if XADPCM to PCM is not accurate.
|
||||
EmuLog(LOG_LEVEL::DEBUG,
|
||||
"EmuDSound: XADPCM WAVEFORMATEX\n"
|
||||
"{\n"
|
||||
" wFormatTag : 0x%.04hX\n"
|
||||
" nChannels : 0x%.02hd\n"
|
||||
" nSamplesPerSec : 0x%.08X\n"
|
||||
" nAvgBytesPerSec : 0x%.08X\n"
|
||||
" nBlockAlign : 0x%.02hd\n"
|
||||
" wBitsPerSample : 0x%.04hX\n"
|
||||
" cbSize : 0x%.04hX\n"
|
||||
"}\n",
|
||||
lpwfxFormat->wFormatTag,
|
||||
lpwfxFormat->nChannels,
|
||||
lpwfxFormat->nSamplesPerSec,
|
||||
lpwfxFormat->nAvgBytesPerSec,
|
||||
lpwfxFormat->nBlockAlign,
|
||||
lpwfxFormat->wBitsPerSample,
|
||||
lpwfxFormat->cbSize);
|
||||
#endif
|
||||
|
||||
lpwfxFormat->wFormatTag = WAVE_FORMAT_PCM;
|
||||
|
||||
//lpwfxFormat.wFormatTag; /* format type */
|
||||
//lpwfxFormat.nChannels; /* number of channels (i.e. mono, stereo...) */ NO CHANGE
|
||||
//lpwfxFormat.nSamplesPerSec; /* sample rate */ NO CHANGE
|
||||
//lpwfxFormat.nAvgBytesPerSec; /* for buffer estimation */
|
||||
//lpwfxFormat.nBlockAlign; /* block size of data */
|
||||
//lpwfxFormat.wBitsPerSample; /* number of bits per sample of mono data */
|
||||
//lpwfxFormat.cbSize; /* the count in bytes of the size of extra information (after cbSize) */
|
||||
|
||||
lpwfxFormat->wBitsPerSample = 16;
|
||||
lpwfxFormat->nBlockAlign = 2 * lpwfxFormat->nChannels;
|
||||
lpwfxFormat->nAvgBytesPerSec = lpwfxFormat->nSamplesPerSec * lpwfxFormat->nBlockAlign;
|
||||
lpwfxFormat->cbSize = 0;
|
||||
//Enable this only if you have Xbox ADPCM Codec installed on your PC, or else it will fail every time.
|
||||
//This is just to verify format conversion is correct or not.
|
||||
#if 0
|
||||
if (waveOutOpen(nullptr, WAVE_MAPPER, lpwfxFormat, NULL, NULL, WAVE_FORMAT_QUERY) != MMSYSERR_NOERROR) {
|
||||
return DSERR_BADFORMAT;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0 //For testing purpose if XADPCM to PCM is not accurate.
|
||||
EmuLog(LOG_LEVEL::DEBUG,
|
||||
"EmuDSound: Converted to PCM WAVEFORMATEX\n"
|
||||
"{\n"
|
||||
" wFormatTag : 0x%.04hX\n"
|
||||
" nChannels : 0x%.02hd\n"
|
||||
" nSamplesPerSec : 0x%.08X\n"
|
||||
" nAvgBytesPerSec : 0x%.08X\n"
|
||||
" nBlockAlign : 0x%.02hd\n"
|
||||
" wBitsPerSample : 0x%.04hX\n"
|
||||
" cbSize : 0x%.04hX\n"
|
||||
"}\n",
|
||||
lpwfxFormat->wFormatTag,
|
||||
lpwfxFormat->nChannels,
|
||||
lpwfxFormat->nSamplesPerSec,
|
||||
lpwfxFormat->nAvgBytesPerSec,
|
||||
lpwfxFormat->nBlockAlign,
|
||||
lpwfxFormat->wBitsPerSample,
|
||||
lpwfxFormat->cbSize);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void GenerateXboxBufferCache(
|
||||
DSBUFFERDESC &DSBufferDesc,
|
||||
DWORD &dwEmuFlags,
|
||||
|
@ -312,7 +244,8 @@ static inline void GenerateMixBinDefault(
|
|||
|
||||
static inline void GeneratePCMFormat(
|
||||
DSBUFFERDESC &DSBufferDesc,
|
||||
LPCWAVEFORMATEX lpwfxFormat,
|
||||
LPCWAVEFORMATEX Xb_lpwfxFormat,
|
||||
DWORD &Xb_flags,
|
||||
DWORD &dwEmuFlags,
|
||||
DWORD X_BufferSizeRequest,
|
||||
LPVOID* X_BufferCache,
|
||||
|
@ -321,186 +254,61 @@ static inline void GeneratePCMFormat(
|
|||
XTL::X_LPDSMIXBINS mixbins_output)
|
||||
{
|
||||
bool bIsSpecial = false;
|
||||
DWORD checkAvgBps;
|
||||
|
||||
GenerateMixBinDefault(Xb_VoiceProperties, lpwfxFormat, mixbins_output, ((DSBufferDesc.dwFlags & DSBCAPS_CTRL3D) > 0));
|
||||
GenerateMixBinDefault(Xb_VoiceProperties, Xb_lpwfxFormat, mixbins_output, ((DSBufferDesc.dwFlags & DSBCAPS_CTRL3D) > 0));
|
||||
|
||||
// convert from Xbox to PC DSound
|
||||
{
|
||||
DSBufferDesc.dwReserved = 0;
|
||||
|
||||
if (lpwfxFormat != xbnullptr) {
|
||||
// Allocate only once, does not need to re-allocate.
|
||||
if (DSBufferDesc.lpwfxFormat == nullptr) {
|
||||
// Only allocate extra value for setting extra values later on. WAVEFORMATEXTENSIBLE is the highest size I had seen.
|
||||
DSBufferDesc.lpwfxFormat = (WAVEFORMATEX*)calloc(1, sizeof(WAVEFORMATEXTENSIBLE));
|
||||
}
|
||||
|
||||
//TODO: RadWolfie - Need implement support for WAVEFORMATEXTENSIBLE as stated in CDirectSoundStream_SetFormat function note below
|
||||
// Do we need to convert it? Or just do the WAVEFORMATEX only?
|
||||
if (DSBufferDesc.lpwfxFormat == nullptr) {
|
||||
CxbxKrnlCleanup("Unable to allocate DSBufferDesc.Xb_lpwfxFormat");
|
||||
}
|
||||
|
||||
// NOTE: pwfxFormat is not always a WAVEFORMATEX structure, it can
|
||||
// be WAVEFORMATEXTENSIBLE if that's what the programmer(s) wanted
|
||||
// in the first place, FYI.
|
||||
if (Xb_lpwfxFormat != xbnullptr) {
|
||||
|
||||
// Allocate only once, does not need to re-allocate.
|
||||
if (DSBufferDesc.lpwfxFormat == nullptr) {
|
||||
// Only allocate extra value for setting extra values later on. WAVEFORMATEXTENSIBLE is the highest size I had seen.
|
||||
DSBufferDesc.lpwfxFormat = (WAVEFORMATEX*)calloc(1, sizeof(WAVEFORMATEXTENSIBLE));
|
||||
}
|
||||
WAVEFORMATEX* lpwfxFormatHost = DSBufferDesc.lpwfxFormat;
|
||||
PWAVEFORMATEXTENSIBLE lpwfxFormatHost = reinterpret_cast<PWAVEFORMATEXTENSIBLE>(DSBufferDesc.lpwfxFormat);
|
||||
|
||||
if (lpwfxFormat->wFormatTag == WAVE_FORMAT_PCM) {
|
||||
// Test case: Hulk crash due to cbSize is not a valid size.
|
||||
memcpy(lpwfxFormatHost, lpwfxFormat, sizeof(WAVEFORMATEX));
|
||||
lpwfxFormatHost->cbSize = 0; // Let's enforce this value to prevent any other exception later on.
|
||||
}
|
||||
else if (lpwfxFormat->wFormatTag == 0 && (DSBufferDesc.dwFlags & DSBCAPS_LOCDEFER) > 0) {
|
||||
// NOTE: This is currently a hack for ability to create buffer class with DSBCAPS_LOCDEFER flag.
|
||||
lpwfxFormatHost->wFormatTag = WAVE_FORMAT_PCM;
|
||||
lpwfxFormatHost->nChannels = 2;
|
||||
lpwfxFormatHost->nSamplesPerSec = 44100;
|
||||
lpwfxFormatHost->wBitsPerSample = 8;
|
||||
lpwfxFormatHost->nBlockAlign = lpwfxFormatHost->nChannels * static_cast<uint32_t>(lpwfxFormatHost->wBitsPerSample) / 8;
|
||||
lpwfxFormatHost->nAvgBytesPerSec = lpwfxFormatHost->nSamplesPerSec * lpwfxFormatHost->nBlockAlign;
|
||||
if (Xb_lpwfxFormat->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
|
||||
memcpy(lpwfxFormatHost, Xb_lpwfxFormat, sizeof(WAVEFORMATEX) + Xb_lpwfxFormat->cbSize);
|
||||
}
|
||||
else {
|
||||
memcpy(lpwfxFormatHost, lpwfxFormat, sizeof(WAVEFORMATEX) + lpwfxFormat->cbSize);
|
||||
}
|
||||
|
||||
// NOTE: Currently a workaround hack fix until custom management for buffer/stream can allow unallocated buffer.
|
||||
// Without this fix, some titles wouldn't progress further. Plus no matter what values are set in Xbox's wfxFormat
|
||||
// are approved. It does need further investigation which require LLE APU stubbed and a HLE verbose plugin.
|
||||
if (X_BufferSizeRequest == 0 &&
|
||||
(lpwfxFormatHost->nSamplesPerSec == 0 || lpwfxFormatHost->nAvgBytesPerSec == 0)) {
|
||||
// NOTE: When X_BufferSizeRequest is 0, creation is allow to be performed until allocated size is given from different API.
|
||||
// Set dwBufferBytes is not needed as it is handled later on.
|
||||
// Test case: Hobbit did not input nSamplesPerSec & nAvgBytesPerSec variable, yet isn't a requirement.
|
||||
if (lpwfxFormatHost->nChannels == 0) {
|
||||
lpwfxFormatHost->nChannels = 2;
|
||||
}
|
||||
if (lpwfxFormatHost->wBitsPerSample == 0) {
|
||||
lpwfxFormatHost->wBitsPerSample = 8;
|
||||
}
|
||||
|
||||
if (lpwfxFormatHost->nBlockAlign == 0) {
|
||||
lpwfxFormatHost->nBlockAlign = lpwfxFormatHost->nChannels * static_cast<uint32_t>(lpwfxFormatHost->wBitsPerSample) / 8;
|
||||
}
|
||||
|
||||
if (lpwfxFormatHost->nSamplesPerSec == 0) {
|
||||
lpwfxFormatHost->nSamplesPerSec = 44100;
|
||||
lpwfxFormatHost->nAvgBytesPerSec = lpwfxFormatHost->nSamplesPerSec * lpwfxFormatHost->nBlockAlign;
|
||||
}
|
||||
|
||||
// TODO: I don't think we need WAVEFORMATEXTENSIBLE stub for this fix.
|
||||
if (lpwfxFormat->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
|
||||
EmuLog(LOG_LEVEL::WARNING, "Is WAVE_FORMAT_EXTENSIBLE having problem with creation?");
|
||||
}
|
||||
// Other formats will enforce use WAVEFORMATEX size, we cannot allow corruption sneak into WAVEFORMATEXTENSIBLE's structure.
|
||||
memcpy(lpwfxFormatHost, Xb_lpwfxFormat, sizeof(WAVEFORMATEX));
|
||||
lpwfxFormatHost->Format.cbSize = 0;
|
||||
}
|
||||
|
||||
dwEmuFlags = dwEmuFlags & ~DSE_FLAG_AUDIO_CODECS;
|
||||
|
||||
switch (DSBufferDesc.lpwfxFormat->wFormatTag) {
|
||||
case WAVE_FORMAT_PCM:
|
||||
CODEC_FORMAT cf_audio = WFXformat_SyncHostFormat(DSBufferDesc.lpwfxFormat, Xb_lpwfxFormat, X_BufferSizeRequest, Xb_flags);
|
||||
if (cf_audio == CF_PCM) {
|
||||
dwEmuFlags |= DSE_FLAG_PCM;
|
||||
|
||||
//TODO: Phantasy Star Online Episode I & II made an attempt to use avg byte/second below sample/second requirement.
|
||||
//In other word, this is a workaround to fix title mistake...
|
||||
checkAvgBps = lpwfxFormat->nSamplesPerSec * lpwfxFormat->nBlockAlign;
|
||||
if (lpwfxFormat->nAvgBytesPerSec < checkAvgBps) {
|
||||
DSBufferDesc.lpwfxFormat->nAvgBytesPerSec = checkAvgBps;
|
||||
}
|
||||
break;
|
||||
case WAVE_FORMAT_XBOX_ADPCM:
|
||||
dwEmuFlags |= DSE_FLAG_XADPCM;
|
||||
XADPCM2PCMFormat(DSBufferDesc.lpwfxFormat);
|
||||
break;
|
||||
default:
|
||||
dwEmuFlags |= DSE_FLAG_PCM_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
else if (cf_audio == CF_XADPCM) {
|
||||
dwEmuFlags |= DSE_FLAG_XADPCM;
|
||||
}
|
||||
else {
|
||||
dwEmuFlags |= DSE_FLAG_PCM_UNKNOWN;
|
||||
}
|
||||
|
||||
} else {
|
||||
bIsSpecial = true;
|
||||
dwEmuFlags |= DSE_FLAG_RECIEVEDATA;
|
||||
|
||||
EmuLog(LOG_LEVEL::WARNING, "Creating dummy WAVEFORMATEX (pdsbd->lpwfxFormat = xbnullptr)...");
|
||||
|
||||
// HACK: This is a special sound buffer, create dummy WAVEFORMATEX data.
|
||||
// It's supposed to recieve data rather than generate it. Buffers created
|
||||
// with flags DSBCAPS_MIXIN, DSBCAPS_FXIN, and DSBCAPS_FXIN2 will have no
|
||||
// WAVEFORMATEX structure by default.
|
||||
|
||||
// TODO: A better response to this scenario if possible.
|
||||
|
||||
DSBufferDesc.lpwfxFormat = (WAVEFORMATEX*)malloc(sizeof(WAVEFORMATEXTENSIBLE));
|
||||
|
||||
//memset(pDSBufferDescSpecial->lpwfxFormat, 0, sizeof(WAVEFORMATEX));
|
||||
//memset(pDSBufferDescSpecial, 0, sizeof(DSBUFFERDESC));
|
||||
|
||||
DSBufferDesc.lpwfxFormat->wFormatTag = WAVE_FORMAT_PCM;
|
||||
DSBufferDesc.lpwfxFormat->nChannels = 2;
|
||||
DSBufferDesc.lpwfxFormat->nSamplesPerSec = 22050;
|
||||
DSBufferDesc.lpwfxFormat->nBlockAlign = 4;
|
||||
DSBufferDesc.lpwfxFormat->nAvgBytesPerSec = DSBufferDesc.lpwfxFormat->nSamplesPerSec * DSBufferDesc.lpwfxFormat->nBlockAlign;
|
||||
DSBufferDesc.lpwfxFormat->wBitsPerSample = 16;
|
||||
DSBufferDesc.lpwfxFormat->cbSize = 0;
|
||||
(void)WFXformat_SyncHostFormat(DSBufferDesc.lpwfxFormat, Xb_lpwfxFormat, X_BufferSizeRequest, Xb_flags);
|
||||
|
||||
DSBufferDesc.dwFlags = DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
|
||||
DSBufferDesc.dwBufferBytes = 3 * DSBufferDesc.lpwfxFormat->nAvgBytesPerSec;
|
||||
|
||||
// DSBufferDesc.lpwfxFormat = (WAVEFORMATEX*)malloc(sizeof(WAVEFORMATEX)/*+pdsbd->lpwfxFormat->cbSize*/);
|
||||
|
||||
//// DSBufferDesc.lpwfxFormat->cbSize = sizeof( WAVEFORMATEX );
|
||||
// DSBufferDesc.lpwfxFormat->nChannels = 1;
|
||||
// DSBufferDesc.lpwfxFormat->wFormatTag = WAVE_FORMAT_PCM;
|
||||
// DSBufferDesc.lpwfxFormat->nSamplesPerSec = 22050;
|
||||
// DSBufferDesc.lpwfxFormat->nBlockAlign = 4;
|
||||
// DSBufferDesc.lpwfxFormat->nAvgBytesPerSec = 4 * 22050;
|
||||
// DSBufferDesc.lpwfxFormat->wBitsPerSample = 16;
|
||||
|
||||
// Give this buffer 3 seconds of data if needed
|
||||
/*if(pdsbd->dwBufferBytes == 0) {
|
||||
DSBufferDesc.dwBufferBytes = 3 * DSBufferDesc.lpwfxFormat->nAvgBytesPerSec;
|
||||
}*/
|
||||
DSBufferDesc.dwBufferBytes = 5 * DSBufferDesc.lpwfxFormat->nAvgBytesPerSec;
|
||||
}
|
||||
|
||||
DSBufferDesc.guid3DAlgorithm = DS3DALG_DEFAULT;
|
||||
}
|
||||
|
||||
// TODO: Still a requirement? Need to retest it again. Can't remember which title cause problem or had been resolved.
|
||||
// sanity check
|
||||
if (!bIsSpecial) {
|
||||
if (DSBufferDesc.lpwfxFormat->nBlockAlign != DSBufferDesc.lpwfxFormat->nChannels* static_cast<uint32_t>(DSBufferDesc.lpwfxFormat->wBitsPerSample) / 8) {
|
||||
DSBufferDesc.lpwfxFormat->nBlockAlign = (2 * DSBufferDesc.lpwfxFormat->wBitsPerSample) / 8;
|
||||
DSBufferDesc.lpwfxFormat->nAvgBytesPerSec = DSBufferDesc.lpwfxFormat->nSamplesPerSec * DSBufferDesc.lpwfxFormat->nBlockAlign;
|
||||
}
|
||||
}
|
||||
|
||||
if (DSBufferDesc.lpwfxFormat != nullptr) {
|
||||
|
||||
// NOTE: This process check for 2+ channels whenever XADPCM or PCM format from xbox titles input in nChannels.
|
||||
// Since the host do not support 2+ channels on PCM only format. We must convert/update allocated wfxFormat to EXTENSIBLE
|
||||
// format which had been allocated enough to update.
|
||||
if (DSBufferDesc.lpwfxFormat->nChannels > 2 && DSBufferDesc.lpwfxFormat->wFormatTag != WAVE_FORMAT_EXTENSIBLE) {
|
||||
PWAVEFORMATEXTENSIBLE lpwfxFormatExtensible = (PWAVEFORMATEXTENSIBLE)DSBufferDesc.lpwfxFormat;
|
||||
lpwfxFormatExtensible->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
|
||||
lpwfxFormatExtensible->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
|
||||
lpwfxFormatExtensible->Samples.wValidBitsPerSample = lpwfxFormatExtensible->Format.wBitsPerSample;
|
||||
lpwfxFormatExtensible->Samples.wSamplesPerBlock = 0;
|
||||
lpwfxFormatExtensible->Samples.wReserved = 0;
|
||||
lpwfxFormatExtensible->dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
|
||||
|
||||
// Add rear speakers
|
||||
if (lpwfxFormat->nChannels >= 4) {
|
||||
lpwfxFormatExtensible->dwChannelMask |= SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
|
||||
}
|
||||
// Add center speaker
|
||||
if (lpwfxFormat->nChannels >= 5) {
|
||||
lpwfxFormatExtensible->dwChannelMask |= SPEAKER_FRONT_CENTER;
|
||||
}
|
||||
// Add subwoofer mask (pretty sure 3 channels is 2.1, not 3.0 for xbox purpose)
|
||||
if (lpwfxFormat->nChannels == 6 || lpwfxFormat->nChannels == 3) {
|
||||
lpwfxFormatExtensible->dwChannelMask |= SPEAKER_LOW_FREQUENCY;
|
||||
}
|
||||
lpwfxFormatExtensible->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
|
||||
}
|
||||
}
|
||||
|
||||
if (X_BufferSizeRequest < DSBSIZE_MIN) {
|
||||
X_BufferSizeRequest = DSBSIZE_MIN;
|
||||
} else if (X_BufferSizeRequest > DSBSIZE_MAX) {
|
||||
|
@ -572,7 +380,7 @@ static inline void DSound3DBufferCreate(LPDIRECTSOUNDBUFFER8 pDSBuffer, LPDIRECT
|
|||
}
|
||||
}
|
||||
|
||||
#define DSoundBufferSetDefault(pThis, dwEmuPlayFlags) \
|
||||
#define DSoundBufferSetDefault(pThis, dwEmuPlayFlags, Xb_dwFlags) \
|
||||
pThis->EmuDirectSoundBuffer8 = nullptr; \
|
||||
pThis->EmuDirectSound3DBuffer8 = nullptr; \
|
||||
pThis->X_BufferCache = xbnullptr; \
|
||||
|
@ -585,7 +393,8 @@ static inline void DSound3DBufferCreate(LPDIRECTSOUNDBUFFER8 pDSBuffer, LPDIRECT
|
|||
pThis->Xb_dwHeadroom = 600; /* default for 2D voice */ \
|
||||
pThis->Xb_EnvolopeDesc = { 0 }; \
|
||||
InitVoiceProperties(pThis->Xb_VoiceProperties); /* The rest will initialize in GeneratePCMFormat to GenerateMixBinDefault. */ \
|
||||
pThis->Xb_Frequency = XTL_DSXFREQUENCY_ORIGINAL;
|
||||
pThis->Xb_Frequency = XTL_DSXFREQUENCY_ORIGINAL; \
|
||||
pThis->Xb_Flags = Xb_dwFlags;
|
||||
//pThis->EmuBufferDesc = { 0 }; // Enable this when become necessary.
|
||||
/*
|
||||
pThis->EmuLockPtr1 = xbnullptr; \
|
||||
|
@ -1259,7 +1068,8 @@ static inline HRESULT HybridDirectSoundBuffer_SetFilter(
|
|||
//IDirectSoundBuffer
|
||||
static inline HRESULT HybridDirectSoundBuffer_SetFormat(
|
||||
LPDIRECTSOUNDBUFFER8 &pDSBuffer,
|
||||
LPCWAVEFORMATEX pwfxFormat,
|
||||
LPCWAVEFORMATEX Xb_pwfxFormat,
|
||||
DWORD Xb_flags,
|
||||
DSBUFFERDESC &BufferDesc,
|
||||
DWORD &dwEmuFlags,
|
||||
DWORD &dwPlayFlags,
|
||||
|
@ -1274,10 +1084,10 @@ static inline HRESULT HybridDirectSoundBuffer_SetFormat(
|
|||
pDSBuffer->Stop();
|
||||
|
||||
if (X_BufferAllocate) {
|
||||
GeneratePCMFormat(BufferDesc, pwfxFormat, dwEmuFlags, X_BufferCacheSize, xbnullptr, X_BufferCacheSize, Xb_VoiceProperties, mixbins_output);
|
||||
GeneratePCMFormat(BufferDesc, Xb_pwfxFormat, Xb_flags, 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, Xb_VoiceProperties, mixbins_output);
|
||||
GeneratePCMFormat(BufferDesc, Xb_pwfxFormat, Xb_flags, dwEmuFlags, 0, xbnullptr, X_BufferCacheSize, Xb_VoiceProperties, mixbins_output);
|
||||
}
|
||||
HRESULT hRet = DS_OK;
|
||||
if (g_pDSoundPrimaryBuffer == pDSBuffer) {
|
||||
|
|
|
@ -230,11 +230,11 @@ HRESULT WINAPI XTL::EMUPATCH(DirectSoundCreateStream)
|
|||
DSBufferDesc.dwFlags |= DSBCAPS_CTRLPAN;
|
||||
}
|
||||
|
||||
DSoundBufferSetDefault((*ppStream), DSBPLAY_LOOPING);
|
||||
DSoundBufferSetDefault((*ppStream), DSBPLAY_LOOPING, pdssd->dwFlags);
|
||||
(*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,
|
||||
GeneratePCMFormat(DSBufferDesc, pdssd->lpwfxFormat, pdssd->dwFlags, (*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 allow stream to work until
|
||||
|
@ -896,10 +896,11 @@ HRESULT WINAPI XTL::EMUPATCH(CDirectSoundStream_SetFormat)
|
|||
|
||||
while (DSStream_Packet_Flush(pThis));
|
||||
|
||||
HRESULT hRet = HybridDirectSoundBuffer_SetFormat(pThis->EmuDirectSoundBuffer8, pwfxFormat, pThis->EmuBufferDesc,
|
||||
pThis->EmuFlags, pThis->EmuPlayFlags, pThis->EmuDirectSound3DBuffer8,
|
||||
0, pThis->X_BufferCache, pThis->X_BufferCacheSize,
|
||||
pThis->Xb_VoiceProperties, xbnullptr, pThis->Xb_Frequency);
|
||||
HRESULT hRet = HybridDirectSoundBuffer_SetFormat(pThis->EmuDirectSoundBuffer8, pwfxFormat, pThis->Xb_Flags,
|
||||
pThis->EmuBufferDesc, pThis->EmuFlags, pThis->EmuPlayFlags,
|
||||
pThis->EmuDirectSound3DBuffer8, 0, pThis->X_BufferCache,
|
||||
pThis->X_BufferCacheSize, pThis->Xb_VoiceProperties,
|
||||
xbnullptr, pThis->Xb_Frequency);
|
||||
|
||||
return hRet;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,336 @@
|
|||
// ******************************************************************
|
||||
// *
|
||||
// * This file is part of the Cxbx project.
|
||||
// *
|
||||
// * Cxbx and Cxbe are free software; you can redistribute them
|
||||
// * and/or modify them under the terms of the GNU General Public
|
||||
// * License as published by the Free Software Foundation; either
|
||||
// * version 2 of the license, or (at your option) any later version.
|
||||
// *
|
||||
// * This program is distributed in the hope that it will be useful,
|
||||
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// * GNU General Public License for more details.
|
||||
// *
|
||||
// * You should have recieved a copy of the GNU General Public License
|
||||
// * along with this program; see the file COPYING.
|
||||
// * If not, write to the Free Software Foundation, Inc.,
|
||||
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
|
||||
// *
|
||||
// * (c) 2017-2020 RadWolfie
|
||||
// *
|
||||
// * All rights reserved
|
||||
// *
|
||||
// ******************************************************************
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <mmreg.h>
|
||||
#include "core/kernel/init/CxbxKrnl.h"
|
||||
#include "core/hle/DSOUND/XbDSoundTypes.h"
|
||||
|
||||
#include "Logging.h"
|
||||
#include "core/hle/DSOUND/DirectSound/DirectSoundLogging.hpp"
|
||||
#include "core/hle/DSOUND/XbDSoundLogging.hpp"
|
||||
|
||||
// Only use as last resort instead of alternative duplicates (an error occur between keyboard and chair)
|
||||
static void WFXformat_GeneratePCMFormat(
|
||||
uint16_t nChannels,
|
||||
uint32_t nSamplesPerSec,
|
||||
uint16_t wBitPerSample,
|
||||
PWAVEFORMATEXTENSIBLE Host_wfxFormat)
|
||||
{
|
||||
Host_wfxFormat->Format.wFormatTag = WAVE_FORMAT_PCM;
|
||||
Host_wfxFormat->Format.nChannels = nChannels;
|
||||
Host_wfxFormat->Format.nSamplesPerSec = nSamplesPerSec;
|
||||
Host_wfxFormat->Format.wBitsPerSample = wBitPerSample;
|
||||
Host_wfxFormat->Format.nBlockAlign = wBitPerSample / 8 * nChannels;
|
||||
Host_wfxFormat->Format.nAvgBytesPerSec = nSamplesPerSec * Host_wfxFormat->Format.nBlockAlign;
|
||||
}
|
||||
|
||||
static void WFXformat_GenerateXADPCMFormat(
|
||||
uint16_t nChannels,
|
||||
uint32_t nSamplesPerSec,
|
||||
PWAVEFORMATEXTENSIBLE Host_pwfxFormat)
|
||||
{
|
||||
Host_pwfxFormat->Format.nChannels = nChannels;
|
||||
Host_pwfxFormat->Format.nSamplesPerSec = nSamplesPerSec;
|
||||
Host_pwfxFormat->Format.wBitsPerSample = 4; // Always 4 (even if they're mono or stereo)
|
||||
Host_pwfxFormat->Format.nBlockAlign = 36 * nChannels;
|
||||
// nAvgBytesPerSec's equation is confirmed.
|
||||
Host_pwfxFormat->Format.nAvgBytesPerSec = (nSamplesPerSec / 64/*Always 64 samples per block*/) * Host_pwfxFormat->Format.nBlockAlign;
|
||||
}
|
||||
|
||||
// Convert XADPCM to PCM format helper function
|
||||
static void XADPCM2PCMFormat(PWAVEFORMATEXTENSIBLE Host_pwfxFormat)
|
||||
{
|
||||
|
||||
#if 0 //For testing purpose if XADPCM to PCM is not accurate.
|
||||
EmuLog(LOG_LEVEL::DEBUG,
|
||||
"EmuDSound: XADPCM WAVEFORMATEX\n"
|
||||
"{\n"
|
||||
" wFormatTag : 0x%.04hX\n"
|
||||
" nChannels : 0x%.02hd\n"
|
||||
" nSamplesPerSec : 0x%.08X\n"
|
||||
" nAvgBytesPerSec : 0x%.08X\n"
|
||||
" nBlockAlign : 0x%.02hd\n"
|
||||
" wBitsPerSample : 0x%.04hX\n"
|
||||
" cbSize : 0x%.04hX\n"
|
||||
"}\n",
|
||||
Host_pwfxFormat->Format.wFormatTag,
|
||||
Host_pwfxFormat->Format.nChannels,
|
||||
Host_pwfxFormat->Format.nSamplesPerSec,
|
||||
Host_pwfxFormat->Format.nAvgBytesPerSec,
|
||||
Host_pwfxFormat->Format.nBlockAlign,
|
||||
Host_pwfxFormat->Format.wBitsPerSample,
|
||||
Host_pwfxFormat->Format.cbSize);
|
||||
#endif
|
||||
|
||||
//Xb_lpwfxFormat.wFormatTag; /* format type */
|
||||
//Xb_lpwfxFormat.nChannels; /* number of channels (i.e. mono, stereo...) */ NO CHANGE
|
||||
//Xb_lpwfxFormat.nSamplesPerSec; /* sample rate */ NO CHANGE
|
||||
//Xb_lpwfxFormat.nAvgBytesPerSec; /* for buffer estimation */
|
||||
//Xb_lpwfxFormat.nBlockAlign; /* block size of data */
|
||||
//Xb_lpwfxFormat.wBitsPerSample; /* number of bits per sample of mono data */
|
||||
//Xb_lpwfxFormat.cbSize; /* the count in bytes of the size of extra information (after cbSize) */
|
||||
WFXformat_GeneratePCMFormat(Host_pwfxFormat->Format.nChannels,
|
||||
Host_pwfxFormat->Format.nSamplesPerSec,
|
||||
16,
|
||||
Host_pwfxFormat);
|
||||
//Enable this only if you have Xbox ADPCM Codec installed on your PC, or else it will fail every time.
|
||||
//This is just to verify format conversion is correct or not.
|
||||
#if 0
|
||||
if (waveOutOpen(nullptr, WAVE_MAPPER, Xb_lpwfxFormat, NULL, NULL, WAVE_FORMAT_QUERY) != MMSYSERR_NOERROR) {
|
||||
return DSERR_BADFORMAT;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0 //For testing purpose if XADPCM to PCM is not accurate.
|
||||
EmuLog(LOG_LEVEL::DEBUG,
|
||||
"EmuDSound: Converted to PCM WAVEFORMATEX\n"
|
||||
"{\n"
|
||||
" wFormatTag : 0x%.04hX\n"
|
||||
" nChannels : 0x%.02hd\n"
|
||||
" nSamplesPerSec : 0x%.08X\n"
|
||||
" nAvgBytesPerSec : 0x%.08X\n"
|
||||
" nBlockAlign : 0x%.02hd\n"
|
||||
" wBitsPerSample : 0x%.04hX\n"
|
||||
" cbSize : 0x%.04hX\n"
|
||||
"}\n",
|
||||
Host_pwfxFormat->Format.wFormatTag,
|
||||
Host_pwfxFormat->Format.nChannels,
|
||||
Host_pwfxFormat->Format.nSamplesPerSec,
|
||||
Host_pwfxFormat->Format.nAvgBytesPerSec,
|
||||
Host_pwfxFormat->Format.nBlockAlign,
|
||||
Host_pwfxFormat->Format.wBitsPerSample,
|
||||
Host_pwfxFormat->Format.cbSize);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void WFXformat_SyncPCMFormat(
|
||||
PWAVEFORMATEXTENSIBLE Host_pwfxFormat)
|
||||
{
|
||||
PWAVEFORMATEX ex_pwfxFormat = &Host_pwfxFormat->Format;
|
||||
// NOTE: This process check for 2+ channels whenever XADPCM or PCM format from xbox titles input in nChannels.
|
||||
// Since the host do not support 2+ channels on PCM only format. We must convert/update allocated wfxFormat to EXTENSIBLE
|
||||
// format which had been allocated enough to update.
|
||||
if (ex_pwfxFormat->nChannels > 2) {
|
||||
Host_pwfxFormat->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
|
||||
Host_pwfxFormat->dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
|
||||
Host_pwfxFormat->Samples.wValidBitsPerSample = ex_pwfxFormat->wBitsPerSample;
|
||||
Host_pwfxFormat->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
|
||||
Host_pwfxFormat->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
|
||||
|
||||
if (ex_pwfxFormat->nChannels >= 4) {
|
||||
Host_pwfxFormat->dwChannelMask |= SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
|
||||
}
|
||||
if (ex_pwfxFormat->nChannels == 6) {
|
||||
Host_pwfxFormat->dwChannelMask |= SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Host_pwfxFormat->Format.wFormatTag = WAVE_FORMAT_PCM;
|
||||
// Test case: Hulk crash due to cbSize is not a valid size.
|
||||
// If Xbox applications didn't enfore cbSize, we'll have to enforce from host side.
|
||||
// Also, we're enforcing it anyway.
|
||||
Host_pwfxFormat->Format.cbSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void WFXformat_SyncXADPCMFormat(
|
||||
PWAVEFORMATEXTENSIBLE Host_wfxFormat)
|
||||
{
|
||||
XADPCM2PCMFormat(Host_wfxFormat);
|
||||
WFXformat_SyncPCMFormat(Host_wfxFormat);
|
||||
}
|
||||
|
||||
typedef enum _CODEC_FORMAT {
|
||||
CF_PCM=0,
|
||||
CF_XADPCM,
|
||||
CF_UNKNOWN
|
||||
} CODEC_FORMAT;
|
||||
|
||||
static void WFXformat_SanityFix(
|
||||
PWAVEFORMATEXTENSIBLE Host_pwfxFormat,
|
||||
CODEC_FORMAT codec_format,
|
||||
uint32_t Xb_buffer_request_size,
|
||||
uint32_t Xb_flags)
|
||||
{
|
||||
WAVEFORMATEXTENSIBLE before_wfxFormat = *Host_pwfxFormat;
|
||||
bool isNotSanity = false;
|
||||
uint32_t nSamplesPerSec = Host_pwfxFormat->Format.nSamplesPerSec;
|
||||
|
||||
// Generic enforcement
|
||||
// If Xbox applications supply invalid total channels, enforce to use either mono or stereo channel
|
||||
if (Host_pwfxFormat->Format.nChannels == 0 || Host_pwfxFormat->Format.nChannels > 6) {
|
||||
Host_pwfxFormat->Format.nChannels = 2;
|
||||
isNotSanity = true;
|
||||
}
|
||||
// If nSamplesPerSec is zero'd then use 44.1kHz by default
|
||||
if (nSamplesPerSec == 0) {
|
||||
Host_pwfxFormat->Format.nSamplesPerSec = 44100;
|
||||
isNotSanity = true;
|
||||
}
|
||||
|
||||
if (Host_pwfxFormat->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
|
||||
if (Host_pwfxFormat->Format.cbSize != sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)) {
|
||||
Host_pwfxFormat->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
|
||||
//isNotSanity = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Test case: Hulk crash due to cbSize is not a valid size.
|
||||
// If Xbox applications didn't enfore cbSize, we'll have to enforce from host side.
|
||||
/* NOTE: cbSize is already handled in WFXformat_SyncPCMFormat function as enforcement.
|
||||
if (Host_pwfxFormat->Format.cbSize != 0) {
|
||||
Host_pwfxFormat->Format.cbSize = 0;
|
||||
//isNotSanity = true;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// Generic handler
|
||||
if (codec_format == CF_PCM || codec_format == CF_UNKNOWN) {
|
||||
// If wBitsPerSample is zero'd then use 16 by default
|
||||
if (Host_pwfxFormat->Format.wBitsPerSample == 0) {
|
||||
isNotSanity = true;
|
||||
}
|
||||
|
||||
// testcase: Phantasy Star Online Episode I & II made an attempt to use avg byte/second below sample/second requirement.
|
||||
// Defender is another title made an attempt to use avg byte/second way above the sample/second requirement.
|
||||
// In other word, this is a workaround to fix titles' mistake...
|
||||
uint32_t checkAvgBps = Host_pwfxFormat->Format.nSamplesPerSec * Host_pwfxFormat->Format.nBlockAlign;
|
||||
|
||||
if (isNotSanity) {
|
||||
WFXformat_GeneratePCMFormat(Host_pwfxFormat->Format.nChannels, Host_pwfxFormat->Format.nSamplesPerSec, 16, Host_pwfxFormat);
|
||||
}
|
||||
else if (Host_pwfxFormat->Format.nAvgBytesPerSec != checkAvgBps) {
|
||||
Host_pwfxFormat->Format.nAvgBytesPerSec = checkAvgBps;
|
||||
isNotSanity = true;
|
||||
}
|
||||
}
|
||||
// CF_XADPCM
|
||||
else if (codec_format == CF_XADPCM) {
|
||||
// If wBitsPerSample is not equal to 4, then wfx format is not sane.
|
||||
if (Host_pwfxFormat->Format.wBitsPerSample != 4) {
|
||||
//Host_pwfxFormat->Format.wBitsPerSample = 4;
|
||||
isNotSanity = true;
|
||||
}
|
||||
|
||||
if (isNotSanity) {
|
||||
WFXformat_GenerateXADPCMFormat(Host_pwfxFormat->Format.nChannels, Host_pwfxFormat->Format.nSamplesPerSec, Host_pwfxFormat);
|
||||
}
|
||||
}
|
||||
|
||||
if (isNotSanity) {
|
||||
std::stringstream before, after;
|
||||
before << before_wfxFormat;
|
||||
after << Host_pwfxFormat;
|
||||
EmuLog(LOG_LEVEL::WARNING, "One or more values were not set properly before: %s\nvs after: %s", before.str().c_str(), after.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
static CODEC_FORMAT WFXformat_SyncHostFormat(
|
||||
void* Host_wfx_ptr,
|
||||
const void* Xb_wfx_ptr,
|
||||
uint32_t Xb_buffer_request_size,
|
||||
uint32_t Xb_flags)
|
||||
{
|
||||
PWAVEFORMATEXTENSIBLE Xb_wfxFormat = (PWAVEFORMATEXTENSIBLE)Xb_wfx_ptr;
|
||||
PWAVEFORMATEXTENSIBLE Host_wfxFormat = (PWAVEFORMATEXTENSIBLE)Host_wfx_ptr;
|
||||
CODEC_FORMAT codec_format_ret = CF_PCM;
|
||||
bool require_validate = true;
|
||||
|
||||
// If no format is provided, then use default.
|
||||
if (Xb_wfx_ptr == xbnullptr) {
|
||||
WFXformat_GeneratePCMFormat(2, 44100, 16, Host_wfxFormat);
|
||||
require_validate = false;
|
||||
}
|
||||
// HACK: This is a special sound buffer, create dummy WAVEFORMATEX data.
|
||||
// It's supposed to recieve data rather than generate it. Buffers created
|
||||
// with flags DSBCAPS_MIXIN, DSBCAPS_FXIN, and DSBCAPS_FXIN2 will have no
|
||||
// WAVEFORMATEX structure by default.
|
||||
else if ((Xb_flags & (XTL_DSBCAPS_MIXIN | XTL_DSBCAPS_FXIN | XTL_DSBCAPS_FXIN2)) > 0) {
|
||||
EmuLog(LOG_LEVEL::WARNING, "Creating dummy WAVEFORMATEX (pdsbd->Xb_lpwfxFormat = xbnullptr)...");
|
||||
WFXformat_GeneratePCMFormat(2, 44100, 16, Host_wfxFormat);
|
||||
require_validate = false;
|
||||
}
|
||||
// Otherwise, let's process given format.
|
||||
else {
|
||||
switch (Xb_wfxFormat->Format.wFormatTag) {
|
||||
case WAVE_FORMAT_PCM:
|
||||
// No further steps require here.
|
||||
break;
|
||||
case WAVE_FORMAT_XBOX_ADPCM:
|
||||
codec_format_ret = CF_XADPCM;
|
||||
break;
|
||||
case WAVE_FORMAT_EXTENSIBLE:
|
||||
if (Xb_wfxFormat->SubFormat.Data1 = WAVE_FORMAT_PCM) {
|
||||
// No further steps require here.
|
||||
}
|
||||
else if (Xb_wfxFormat->SubFormat.Data1 == WAVE_FORMAT_XBOX_ADPCM) {
|
||||
codec_format_ret = CF_XADPCM;
|
||||
}
|
||||
else {
|
||||
codec_format_ret = CF_UNKNOWN;
|
||||
require_validate = false;
|
||||
std::stringstream oss;
|
||||
oss << Xb_wfxFormat->SubFormat;
|
||||
std::string msg = "Please report unknown extensible format : " + oss.str();
|
||||
LOG_TEST_CASE(msg.c_str());
|
||||
}
|
||||
break;
|
||||
// Both 0 and default will use static structure until given a valid one.
|
||||
case 0:
|
||||
// NOTE: This is currently a hack for ability to create buffer class with DSBCAPS_LOCDEFER flag.
|
||||
WFXformat_GeneratePCMFormat(2, 44100, 16, Host_wfxFormat);
|
||||
require_validate = false;
|
||||
LOG_TEST_CASE("WAVE_FORMAT_(0) found");
|
||||
break;
|
||||
default:
|
||||
codec_format_ret = CF_UNKNOWN;
|
||||
require_validate = false;
|
||||
EmuLog(LOG_LEVEL::WARNING, "Unknown Xbox format: %08X", Xb_wfxFormat->Format.wFormatTag);
|
||||
LOG_TEST_CASE("Unknown Xbox format, check your log output");
|
||||
break;
|
||||
}
|
||||
|
||||
if (require_validate) {
|
||||
// First, perform sanity fix
|
||||
WFXformat_SanityFix(Host_wfxFormat, codec_format_ret, Xb_buffer_request_size, Xb_flags);
|
||||
}
|
||||
|
||||
// Then re-convert to Host's PCM format.
|
||||
if (codec_format_ret == CF_PCM) {
|
||||
WFXformat_SyncPCMFormat(Host_wfxFormat);
|
||||
}
|
||||
else if (codec_format_ret == CF_XADPCM) {
|
||||
WFXformat_SyncXADPCMFormat(Host_wfxFormat);
|
||||
}
|
||||
// Any unknown formats will be using default PCM format.
|
||||
else {
|
||||
WFXformat_GeneratePCMFormat(2, 44100, 16, Host_wfxFormat);
|
||||
}
|
||||
}
|
||||
return codec_format_ret;
|
||||
}
|
Loading…
Reference in New Issue