Merge pull request #1901 from RadWolfie/wwe-raw-2-fixup

Partial Implement of Xbox DSound's Class Structure
This commit is contained in:
PatrickvL 2020-05-18 11:10:22 +02:00 committed by GitHub
commit d1580cd19d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 982 additions and 357 deletions

View File

@ -130,6 +130,7 @@ file (GLOB CXBXR_HEADER_GUIv1
# Emulator (module)
file (GLOB CXBXR_HEADER_EMU
"${CXBXR_ROOT_DIR}/src/common/AddressRanges.h"
"${CXBXR_ROOT_DIR}/src/common/audio/converter.hpp"
"${CXBXR_ROOT_DIR}/src/common/util/gloffscreen/glextensions.h"
"${CXBXR_ROOT_DIR}/src/common/util/gloffscreen/gloffscreen.h"
"${CXBXR_ROOT_DIR}/src/common/XADPCM.h"
@ -154,6 +155,7 @@ file (GLOB CXBXR_HEADER_EMU
"${CXBXR_ROOT_DIR}/src/core/hle/DSOUND/DirectSound/DSStream_PacketManager.hpp"
"${CXBXR_ROOT_DIR}/src/core/hle/DSOUND/XbDSoundLogging.hpp"
"${CXBXR_ROOT_DIR}/src/core/hle/DSOUND/XbDSoundTypes.h"
"${CXBXR_ROOT_DIR}/src/core/hle/DSOUND/common/XbInternalStruct.hpp"
"${CXBXR_ROOT_DIR}/src/core/hle/Intercept.hpp"
"${CXBXR_ROOT_DIR}/src/core/hle/Patches.hpp"
"${CXBXR_ROOT_DIR}/src/core/hle/XACTENG/XactEng.h"
@ -296,6 +298,8 @@ file (GLOB CXBXR_SOURCE_EMU
"${CXBXR_ROOT_DIR}/src/core/hle/DSOUND/DirectSound/DSStream_PacketManager.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/DSOUND/DirectSound/XFileMediaObject.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/DSOUND/XbDSoundLogging.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/DSOUND/common/XbInternalDSVoice.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/DSOUND/common/XbInternalStruct.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/Intercept.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/Patches.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/XACTENG/XactEng.cpp"

View File

@ -0,0 +1,51 @@
// ******************************************************************
// *
// * 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, Boston, MA 02111-1307, USA.
// *
// * (c) 2020 RadWolfie
// *
// * All rights reserved
// *
// ******************************************************************
#pragma once
#include <cstdint>
// Convert frequency to pitch helper
static inline int32_t converter_freq2pitch(uint32_t freq) {
// NOTE: pitch = 0 is equal to 48 KHz.
/* For research purpose of how to convert frequency to pitch and back to frequency.
// Edit hertz variable to see the result.
float hertz = 12000.0f;
float hertzRatio = 48000.0f; // base frequency
float pitchRatio = 4096.0f; // pitch per octave
// Convert hertz to pitch
float pitch = log2(hertz / hertzRatio) * pitchRatio;
// Convert pitch to hertz
hertz = exp((pitch / pitchRatio) * log(2)) * hertzRatio;*/
return static_cast<int32_t>(log2(freq / 48000.0f) * 4096.0f);
}
// Convert pitch to frequency helper
static inline uint32_t converter_pitch2freq(int32_t pitch) {
//* See research documentation above for conversion example.
return static_cast<uint32_t>(exp((pitch / 4096.0f) * log(2)) * 48000.0f);
}

View File

@ -887,14 +887,15 @@ HRESULT WINAPI XTL::EMUPATCH(CDirectSound_SynchPlayback)
vector_ds_buffer::iterator ppDSBuffer = g_pDSoundBufferCache.begin();
for (; ppDSBuffer != g_pDSoundBufferCache.end(); ppDSBuffer++) {
if ((*ppDSBuffer)->X_BufferCache == nullptr) {
EmuDirectSoundBuffer* pDSBuffer = (*ppDSBuffer)->emuDSBuffer;
if (pDSBuffer->X_BufferCache == nullptr) {
continue;
}
if (((*ppDSBuffer)->EmuFlags & DSE_FLAG_SYNCHPLAYBACK_CONTROL) > 0) {
DSoundBufferSynchPlaybackFlagRemove((*ppDSBuffer)->EmuFlags);
EmuLog(LOG_LEVEL::DEBUG, "SynchPlayback - pDSBuffer: %08X; EmuPlayFlags: %08X", *ppDSBuffer, (*ppDSBuffer)->EmuPlayFlags);
(*ppDSBuffer)->EmuDirectSoundBuffer8->Play(0, 0, (*ppDSBuffer)->EmuPlayFlags);
if ((pDSBuffer->EmuFlags & DSE_FLAG_SYNCHPLAYBACK_CONTROL) > 0) {
DSoundBufferSynchPlaybackFlagRemove(pDSBuffer->EmuFlags);
EmuLog(LOG_LEVEL::DEBUG, "SynchPlayback - pDSBuffer: %08X; EmuPlayFlags: %08X", *ppDSBuffer, pDSBuffer->EmuPlayFlags);
pDSBuffer->EmuDirectSoundBuffer8->Play(0, 0, pDSBuffer->EmuPlayFlags);
}
}

View File

@ -28,6 +28,7 @@
#include "core\kernel\init\CxbxKrnl.h"
#include "core\hle\DSOUND\XbDSoundTypes.h"
#include "core\hle\DSOUND\common\XbInternalStruct.hpp"
typedef struct IDirectSound3DListener8* LPDIRECTSOUND3DLISTENER8;
typedef struct IDirectSound3DBuffer8* LPDIRECTSOUND3DBUFFER8;
@ -73,25 +74,25 @@ typedef struct _DSoundBuffer_Lock {
// ******************************************************************
// * X_CDirectSoundBuffer
// ******************************************************************
struct X_CDirectSoundBuffer
struct XbHybridDSBuffer;
struct EmuDirectSoundBuffer
{
BYTE UnknownA[0x20]; // Offset: 0x00
virtual ~EmuDirectSoundBuffer();
XbHybridDSBuffer* pHybridThis;
union // Offset: 0x20
union
{
PVOID pMpcxBuffer;
LPDIRECTSOUNDBUFFER8 EmuDirectSoundBuffer8;
};
BYTE UnknownB[0x0C]; // Offset: 0x24
LPVOID X_BufferCache; // Offset: 0x28
DSBUFFERDESC EmuBufferDesc; // Offset: 0x2C
/*LPVOID EmuLockPtr1; // Offset: 0x30
DWORD EmuLockBytes1; // Offset: 0x34
LPVOID EmuLockPtr2; // Offset: 0x38
DWORD EmuLockBytes2; // Offset: 0x3C*/
DWORD EmuPlayFlags; // Offset: 0x40
DWORD EmuFlags; // Offset: 0x44
LPVOID X_BufferCache;
DSBUFFERDESC EmuBufferDesc;
/*LPVOID EmuLockPtr1;
DWORD EmuLockBytes1;
LPVOID EmuLockPtr2;
DWORD EmuLockBytes2;*/
DWORD EmuPlayFlags;
DWORD EmuFlags;
LPDIRECTSOUND3DBUFFER8 EmuDirectSound3DBuffer8;
//DWORD EmuLockOffset;
//DWORD EmuLockFlags;
@ -106,14 +107,26 @@ struct X_CDirectSoundBuffer
DSoundBuffer_Lock X_lock;
REFERENCE_TIME Xb_rtPauseEx;
REFERENCE_TIME Xb_rtStopEx;
LONG Xb_Volume;
LONG Xb_VolumeMixbin;
DWORD Xb_dwHeadroom;
LONG Xb_VolumeMixbin;
X_DSENVOLOPEDESC Xb_EnvolopeDesc;
X_DSVOICEPROPS Xb_VoiceProperties;
DWORD Xb_Frequency;
DWORD Xb_Flags;
};
struct XbHybridDSBuffer : DSBUFFER_S::DSBUFFER_I {
EmuDirectSoundBuffer* emuDSBuffer;
};
struct SharedDSBuffer : DSBUFFER_S {
SharedDSBuffer(bool is3D) : DSBUFFER_S(is3D) {
emuDSBuffer = new EmuDirectSoundBuffer();
}
EmuDirectSoundBuffer* emuDSBuffer;
virtual ~SharedDSBuffer() {
delete emuDSBuffer;
}
};
//Custom flags (4 bytes support up to 31 shifts,starting from 0)
#define DSE_FLAG_PCM (1 << 0)
@ -188,7 +201,7 @@ class X_CDirectSoundStream
{
public:
// construct vtable (or grab ptr to existing)
X_CDirectSoundStream() : pVtbl(&vtbl) { pMcpxStream = new X_CMcpxStream(this); };
X_CDirectSoundStream(bool is3D) : pVtbl(&vtbl), Xb_Voice(is3D) { pMcpxStream = new X_CMcpxStream(this); };
private:
// vtable (cached by each instance, via constructor)
@ -243,6 +256,8 @@ class X_CDirectSoundStream
#endif
public:
// Placeholder until have positive offset
CDirectSoundVoice Xb_Voice;
// cached data
LPDIRECTSOUNDBUFFER8 EmuDirectSoundBuffer8;
LPDIRECTSOUND3DBUFFER8 EmuDirectSound3DBuffer8;
@ -263,12 +278,9 @@ class X_CDirectSoundStream
LPVOID Xb_lpvContext;
REFERENCE_TIME Xb_rtFlushEx;
REFERENCE_TIME Xb_rtPauseEx;
LONG Xb_Volume;
LONG Xb_VolumeMixbin;
DWORD Xb_dwHeadroom;
LONG Xb_VolumeMixbin;
X_DSENVOLOPEDESC Xb_EnvolopeDesc;
X_DSVOICEPROPS Xb_VoiceProperties;
DWORD Xb_Frequency;
DWORD Host_dwLastWritePos;
DWORD Xb_Flags;
DWORD Xb_Status;
@ -481,7 +493,7 @@ HRESULT WINAPI EMUPATCH(IDirectSound_SetMixBinHeadroom)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetMixBins)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
DWORD dwMixBinMask
);
@ -490,7 +502,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetMixBins)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetMixBinVolumes_12)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
DWORD dwMixBinMask,
const LONG* alVolumes
);
@ -500,7 +512,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetMixBinVolumes_12)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetMixBinVolumes_8)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
X_LPDSMIXBINS pMixBins
);
@ -551,10 +563,10 @@ HRESULT WINAPI EMUPATCH(CDirectSound_CommitDeferredSettings)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSound_CreateSoundBuffer)
(
LPDIRECTSOUND8 pThis,
X_DSBUFFERDESC* pdsbd,
X_CDirectSoundBuffer** ppBuffer,
LPUNKNOWN pUnkOuter
LPDIRECTSOUND8 pThis,
X_DSBUFFERDESC* pdsbd,
XbHybridDSBuffer** ppBuffer,
LPUNKNOWN pUnkOuter
);
// ******************************************************************
@ -562,8 +574,8 @@ HRESULT WINAPI EMUPATCH(IDirectSound_CreateSoundBuffer)
// ******************************************************************
HRESULT WINAPI EMUPATCH(DirectSoundCreateBuffer)
(
X_DSBUFFERDESC* pdsbd,
X_CDirectSoundBuffer** ppBuffer
X_DSBUFFERDESC* pdsbd,
XbHybridDSBuffer** ppBuffer
);
// ******************************************************************
@ -571,9 +583,9 @@ HRESULT WINAPI EMUPATCH(DirectSoundCreateBuffer)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetBufferData)
(
X_CDirectSoundBuffer* pThis,
LPVOID pvBufferData,
DWORD dwBufferBytes
XbHybridDSBuffer* pHybridThis,
LPVOID pvBufferData,
DWORD dwBufferBytes
);
// ******************************************************************
@ -581,9 +593,9 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetBufferData)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetPlayRegion)
(
X_CDirectSoundBuffer* pThis,
DWORD dwPlayStart,
DWORD dwPlayLength
XbHybridDSBuffer* pHybridThis,
DWORD dwPlayStart,
DWORD dwPlayLength
);
// ******************************************************************
@ -591,7 +603,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetPlayRegion)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_Lock)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
DWORD dwOffset,
DWORD dwBytes,
LPVOID* ppvAudioPtr1,
@ -605,7 +617,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_Lock)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_Unlock)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
LPVOID ppvAudioPtr1,
DWORD pdwAudioBytes1,
LPVOID ppvAudioPtr2,
@ -617,7 +629,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_Unlock)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetHeadroom)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
DWORD dwHeadroom
);
@ -626,7 +638,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetHeadroom)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetLoopRegion)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
DWORD dwLoopStart,
DWORD dwLoopLength
);
@ -636,7 +648,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetLoopRegion)
// ******************************************************************
ULONG WINAPI EMUPATCH(IDirectSoundBuffer_Release)
(
X_CDirectSoundBuffer* pThis
XbHybridDSBuffer* pHybridThis
);
// ******************************************************************
@ -644,7 +656,7 @@ ULONG WINAPI EMUPATCH(IDirectSoundBuffer_Release)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetPitch)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
LONG lPitch
);
@ -653,7 +665,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetPitch)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_GetStatus)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
LPDWORD pdwStatus
);
@ -662,7 +674,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_GetStatus)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetVolume)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
LONG lVolume
);
@ -671,7 +683,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetVolume)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetCurrentPosition)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
DWORD dwNewPosition
);
@ -680,7 +692,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetCurrentPosition)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_GetCurrentPosition)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
PDWORD pdwCurrentPlayCursor,
PDWORD pdwCurrentWriteCursor
);
@ -690,7 +702,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_GetCurrentPosition)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_Stop)
(
X_CDirectSoundBuffer* pThis
XbHybridDSBuffer* pHybridThis
);
// ******************************************************************
@ -698,9 +710,9 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_Stop)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_StopEx)
(
X_CDirectSoundBuffer *pBuffer,
REFERENCE_TIME rtTimeStamp,
DWORD dwFlags
XbHybridDSBuffer* pHybridThis,
REFERENCE_TIME rtTimeStamp,
DWORD dwFlags
);
// ******************************************************************
@ -708,7 +720,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_StopEx)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_Play)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
DWORD dwReserved1,
DWORD dwReserved2,
DWORD dwFlags
@ -719,7 +731,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_Play)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_PlayEx)
(
X_CDirectSoundBuffer* pBuffer,
XbHybridDSBuffer* pHybridThis,
REFERENCE_TIME rtTimeStamp,
DWORD dwFlags
);
@ -729,7 +741,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_PlayEx)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetVolume)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
LONG lVolume
);
@ -738,7 +750,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetVolume)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetFrequency)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
DWORD dwFrequency
);
@ -972,7 +984,7 @@ HRESULT WINAPI EMUPATCH(CDirectSoundStream_SetMixBins)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetMaxDistance)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
FLOAT flMaxDistance,
DWORD dwApply
);
@ -982,7 +994,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetMaxDistance)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetMinDistance)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
FLOAT flMaxDistance,
DWORD dwApply
);
@ -992,7 +1004,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetMinDistance)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetRolloffFactor)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
FLOAT flRolloffFactor,
DWORD dwApply
);
@ -1002,7 +1014,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetRolloffFactor)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetDistanceFactor)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
FLOAT flDistanceFactor,
DWORD dwApply
);
@ -1012,7 +1024,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetDistanceFactor)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetConeAngles)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
DWORD dwInsideConeAngle,
DWORD dwOutsideConeAngle,
DWORD dwApply
@ -1023,7 +1035,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetConeAngles)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetConeOrientation)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
FLOAT x,
FLOAT y,
FLOAT z,
@ -1035,7 +1047,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetConeOrientation)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetConeOutsideVolume)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
LONG lConeOutsideVolume,
DWORD dwApply
);
@ -1045,7 +1057,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetConeOutsideVolume)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetPosition)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
FLOAT x,
FLOAT y,
FLOAT z,
@ -1057,7 +1069,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetPosition)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetVelocity)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
FLOAT x,
FLOAT y,
FLOAT z,
@ -1069,7 +1081,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetVelocity)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetDopplerFactor)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
FLOAT flDopplerFactor,
DWORD dwApply
);
@ -1079,7 +1091,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetDopplerFactor)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetI3DL2Source)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
X_DSI3DL2BUFFER* pds3db,
DWORD dwApply
);
@ -1090,7 +1102,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetI3DL2Source)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetMode)
(
X_CDirectSoundBuffer* pBuffer,
XbHybridDSBuffer* pHybridThis,
DWORD dwMode,
DWORD dwApply
);
@ -1100,7 +1112,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetMode)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetFormat)
(
X_CDirectSoundBuffer *pBuffer,
XbHybridDSBuffer* pHybridThis,
LPCWAVEFORMATEX pwfxFormat
);
@ -1129,8 +1141,8 @@ void WINAPI EMUPATCH(DirectSoundUseLightHRTF4Channel)(void);
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetLFO)
(
LPDIRECTSOUNDBUFFER8 pThis,
LPCDSLFODESC pLFODesc
XbHybridDSBuffer* pHybridThis,
LPCDSLFODESC pLFODesc
);
// ******************************************************************
@ -1157,7 +1169,7 @@ VOID WINAPI EMUPATCH(XAudioCreateAdpcmFormat)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetRolloffCurve)
(
LPDIRECTSOUNDBUFFER8 pThis,
XbHybridDSBuffer* pHybridThis,
const FLOAT* pflPoints,
DWORD dwPointCount,
DWORD dwApply
@ -1186,7 +1198,7 @@ HRESULT WINAPI EMUPATCH(IDirectSound_EnableHeadphones)
// ******************************************************************
ULONG WINAPI EMUPATCH(IDirectSoundBuffer_AddRef)
(
X_CDirectSoundBuffer* pThis
XbHybridDSBuffer* pHybridThis
);
// ******************************************************************
@ -1194,7 +1206,7 @@ ULONG WINAPI EMUPATCH(IDirectSoundBuffer_AddRef)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_Pause)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
DWORD dwPause
);
@ -1203,7 +1215,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_Pause)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_PauseEx)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
REFERENCE_TIME rtTimestamp,
DWORD dwPause
);
@ -1263,8 +1275,8 @@ HRESULT WINAPI EMUPATCH(XAudioDownloadEffectsImage)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetFilter)
(
LPVOID pThis,
X_DSFILTERDESC* pFilterDesc
XbHybridDSBuffer* pHybridThis,
X_DSFILTERDESC* pFilterDesc
);
// ******************************************************************
@ -1333,7 +1345,7 @@ HRESULT WINAPI EMUPATCH(CDirectSoundStream_SetI3DL2Source)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetAllParameters)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
X_DS3DBUFFER* pc3DBufferParameters,
DWORD dwApply
);
@ -1352,8 +1364,8 @@ HRESULT WINAPI EMUPATCH(CDirectSoundStream_SetFormat)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetOutputBuffer)
(
X_CDirectSoundBuffer* pThis,
X_CDirectSoundBuffer* pOutputBuffer
XbHybridDSBuffer* pHybridThis,
XbHybridDSBuffer* pOutputBuffer
);
// ******************************************************************
@ -1361,8 +1373,8 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetOutputBuffer)
// ******************************************************************
HRESULT WINAPI EMUPATCH(CDirectSoundStream_SetOutputBuffer)
(
X_CDirectSoundStream* pThis,
X_CDirectSoundBuffer* pOutputBuffer
X_CDirectSoundStream* pThis,
XbHybridDSBuffer* pOutputBuffer
);
// ******************************************************************
@ -1389,8 +1401,8 @@ HRESULT WINAPI EMUPATCH(XWaveFileCreateMediaObject)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetEG)
(
X_CDirectSoundBuffer* pThis,
X_DSENVOLOPEDESC* pEnvelopeDesc
XbHybridDSBuffer* pHybridThis,
X_DSENVOLOPEDESC* pEnvelopeDesc
);
// ******************************************************************
@ -1410,8 +1422,8 @@ HRESULT WINAPI EMUPATCH(IDirectSound_GetEffectData)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetNotificationPositions)
(
X_CDirectSoundBuffer* pThis,
DWORD dwNotifyCount,
XbHybridDSBuffer* pHybridThis,
DWORD dwNotifyCount,
LPCDSBPOSITIONNOTIFY paNotifies
);
@ -1420,7 +1432,7 @@ HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_SetNotificationPositions)
// ******************************************************************
HRESULT WINAPI EMUPATCH(CDirectSoundStream_SetRolloffCurve)
(
X_CDirectSoundBuffer* pThis,
X_CDirectSoundStream* pThis,
const FLOAT* pflPoints,
DWORD dwPointCount,
DWORD dwApply
@ -1444,8 +1456,8 @@ HRESULT WINAPI EMUPATCH(IDirectSound_SetEffectData)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_Use3DVoiceData)
(
LPVOID pThis,
LPUNKNOWN pUnknown
XbHybridDSBuffer* pHybridThis,
LPUNKNOWN pUnknown
);
// ******************************************************************
@ -1597,7 +1609,7 @@ HRESULT WINAPI EMUPATCH(CDirectSoundStream_SetDopplerFactor)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_GetVoiceProperties)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
OUT X_DSVOICEPROPS* pVoiceProps);
// ******************************************************************
@ -1696,7 +1708,7 @@ VOID WINAPI EMUPATCH(CDirectSound3DCalculator_GetVoiceData)
// ******************************************************************
HRESULT WINAPI EMUPATCH(IDirectSoundBuffer_Set3DVoiceData)
(
X_CDirectSoundBuffer* pThis,
XbHybridDSBuffer* pHybridThis,
DWORD a2);
// ******************************************************************

File diff suppressed because it is too large Load Diff

View File

@ -45,7 +45,7 @@ extern std::recursive_mutex g_DSoundMutex;
// Xbox maximum synch playback audio
#define DSOUND_MAX_SYNCHPLAYBACK_AUDIO 29
#define vector_ds_buffer std::vector<XTL::X_CDirectSoundBuffer*>
#define vector_ds_buffer std::vector<XTL::XbHybridDSBuffer*>
#define vector_ds_stream std::vector<XTL::X_CDirectSoundStream*>
extern vector_ds_buffer g_pDSoundBufferCache;
extern vector_ds_stream g_pDSoundStreamCache;

View File

@ -254,7 +254,8 @@ static inline void GeneratePCMFormat(
LPVOID* X_BufferCache,
DWORD &X_BufferCacheSize,
XTL::X_DSVOICEPROPS& Xb_VoiceProperties,
XTL::X_LPDSMIXBINS mixbins_output)
XTL::X_LPDSMIXBINS mixbins_output,
XTL::CDirectSoundVoice* Xb_Voice)
{
bool bIsSpecial = false;
@ -289,7 +290,7 @@ static inline void GeneratePCMFormat(
dwEmuFlags = dwEmuFlags & ~DSE_FLAG_AUDIO_CODECS;
CODEC_FORMAT cf_audio = WFXformat_SyncHostFormat(DSBufferDesc.lpwfxFormat, Xb_lpwfxFormat, X_BufferSizeRequest, Xb_flags);
CODEC_FORMAT cf_audio = WFXformat_SyncHostFormat(DSBufferDesc.lpwfxFormat, Xb_lpwfxFormat, X_BufferSizeRequest, Xb_flags, Xb_Voice);
if (cf_audio == CF_PCM) {
dwEmuFlags |= DSE_FLAG_PCM;
}
@ -303,7 +304,7 @@ static inline void GeneratePCMFormat(
} else {
dwEmuFlags |= DSE_FLAG_RECIEVEDATA;
(void)WFXformat_SyncHostFormat(DSBufferDesc.lpwfxFormat, Xb_lpwfxFormat, X_BufferSizeRequest, Xb_flags);
(void)WFXformat_SyncHostFormat(DSBufferDesc.lpwfxFormat, Xb_lpwfxFormat, X_BufferSizeRequest, Xb_flags, Xb_Voice);
DSBufferDesc.dwFlags = DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
DSBufferDesc.dwBufferBytes = 5 * DSBufferDesc.lpwfxFormat->nAvgBytesPerSec;
@ -391,12 +392,9 @@ static inline void DSound3DBufferCreate(LPDIRECTSOUNDBUFFER8 pDSBuffer, LPDIRECT
pThis->EmuPlayFlags = dwEmuPlayFlags; \
pThis->X_BufferCacheSize = 0; \
pThis->Xb_rtPauseEx = 0LL; \
pThis->Xb_Volume = 0L; \
pThis->Xb_VolumeMixbin = 0L; \
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_Flags = Xb_dwFlags;
//pThis->EmuBufferDesc = { 0 }; // Enable this when become necessary.
/*
@ -405,7 +403,7 @@ static inline void DSound3DBufferCreate(LPDIRECTSOUNDBUFFER8 pDSBuffer, LPDIRECT
pThis->EmuLockPtr2 = xbnullptr; \
pThis->EmuLockBytes2 = 0; \ */
static inline void DSoundBufferRegionSetDefault(XTL::X_CDirectSoundBuffer *pThis) {
static inline void DSoundBufferRegionSetDefault(XTL::EmuDirectSoundBuffer *pThis) {
pThis->EmuBufferToggle = XTL::X_DSB_TOGGLE_DEFAULT;
pThis->EmuRegionLoopStartOffset = 0;
pThis->EmuRegionLoopLength = 0;
@ -419,7 +417,7 @@ static inline void DSoundBufferTransferSettings(
LPDIRECTSOUNDBUFFER8 &pDSBufferNew,
LPDIRECTSOUND3DBUFFER8 &pDS3DBufferOld,
LPDIRECTSOUND3DBUFFER8 &pDS3DBufferNew,
DWORD Xb_Frequency)
XTL::CDirectSoundVoice* Xb_Voice)
{
LONG lVolume, lPan;
DS3DBUFFER ds3dBuffer;
@ -428,7 +426,9 @@ static inline void DSoundBufferTransferSettings(
return;
}
pDSBufferNew->SetFrequency(Xb_Frequency);
// if sync current frequency used (then use pitch only).
uint32_t freq = converter_pitch2freq(Xb_Voice->GetPitch());
pDSBufferNew->SetFrequency(freq);
pDSBufferOld->GetVolume(&lVolume);
pDSBufferNew->SetVolume(lVolume);
@ -449,7 +449,7 @@ static inline void DSoundBufferReCreate(
LPDIRECTSOUND3DBUFFER8 &pDS3DBuffer,
LPDIRECTSOUNDBUFFER8 &pDSBufferNew,
LPDIRECTSOUND3DBUFFER8 &pDS3DBufferNew,
DWORD Xb_Frequency) {
XTL::CDirectSoundVoice* Xb_Voice) {
DSoundBufferCreate(&DSBufferDesc, pDSBufferNew);
@ -458,7 +458,7 @@ static inline void DSoundBufferReCreate(
DSound3DBufferCreate(pDSBufferNew, pDS3DBufferNew);
}
DSoundBufferTransferSettings(pDSBuffer, pDSBufferNew, pDS3DBuffer, pDS3DBufferNew, Xb_Frequency);
DSoundBufferTransferSettings(pDSBuffer, pDSBufferNew, pDS3DBuffer, pDS3DBufferNew, Xb_Voice);
}
static inline void DSoundBufferRelease(
@ -484,10 +484,11 @@ static inline void DSoundBufferRelease(
}
static inline void DSoundBufferResizeSetSize(
XTL::X_CDirectSoundBuffer* pThis,
XTL::XbHybridDSBuffer* pHybridThis,
HRESULT &hRet,
DWORD Xb_dwByteLength) {
XTL::EmuDirectSoundBuffer* pThis = pHybridThis->emuDSBuffer;
// General return OK, nothing needs to set as invalid for now.
hRet = DS_OK;
@ -508,7 +509,7 @@ static inline void DSoundBufferResizeSetSize(
LPDIRECTSOUND3DBUFFER8 pDS3DBufferNew = nullptr;
DSoundBufferReCreate(pThis->EmuDirectSoundBuffer8, pThis->EmuBufferDesc, pThis->EmuDirectSound3DBuffer8,
pDSBufferNew, pDS3DBufferNew, pThis->Xb_Frequency);
pDSBufferNew, pDS3DBufferNew, pHybridThis->p_CDSVoice);
// release old buffer
DSoundBufferRelease(pThis->EmuDirectSoundBuffer8, pThis->EmuDirectSound3DBuffer8, refCount);
@ -522,13 +523,14 @@ static inline void DSoundBufferResizeSetSize(
}
static inline void DSoundBufferResizeUpdate(
XTL::X_CDirectSoundBuffer* pThis,
XTL::XbHybridDSBuffer* pHybridThis,
DWORD dwPlayFlags,
HRESULT &hRet,
DWORD Xb_dwStartOffset,
DWORD Xb_dwByteLength) {
DSoundBufferResizeSetSize(pThis, hRet, Xb_dwByteLength);
XTL::EmuDirectSoundBuffer* pThis = pHybridThis->emuDSBuffer;
DSoundBufferResizeSetSize(pHybridThis, hRet, Xb_dwByteLength);
hRet = pThis->EmuDirectSoundBuffer8->Lock(0, 0, &pThis->Host_lock.pLockPtr1, &pThis->Host_lock.dwLockBytes1,
nullptr, nullptr, DSBLOCK_ENTIREBUFFER);
@ -546,11 +548,13 @@ static inline void DSoundBufferResizeUpdate(
}
static inline void DSoundBufferRegionCurrentLocation(
XTL::X_CDirectSoundBuffer* pThis,
XTL::XbHybridDSBuffer* pHybridThis,
DWORD dwPlayFlags,
HRESULT &hRet,
DWORD &Xb_dwStartOffset,
DWORD &Xb_dwByteLength) {
DWORD &Xb_dwByteLength)
{
XTL::EmuDirectSoundBuffer* pThis = pHybridThis->emuDSBuffer;
if ((dwPlayFlags & X_DSBPLAY_LOOPING) > 0) {
Xb_dwStartOffset = pThis->EmuRegionPlayStartOffset + pThis->EmuRegionLoopStartOffset;
@ -577,7 +581,7 @@ static inline void DSoundBufferRegionCurrentLocation(
}
static inline void DSoundBufferUpdate(
XTL::X_CDirectSoundBuffer* pThis,
XTL::XbHybridDSBuffer* pHybridThis,
DWORD dwPlayFlags,
HRESULT &hRet) {
@ -585,24 +589,24 @@ static inline void DSoundBufferUpdate(
DWORD Xb_dwByteLength;
DWORD Xb_dwStartOffset;
DSoundBufferRegionCurrentLocation(pThis, dwPlayFlags, hRet, Xb_dwStartOffset, Xb_dwByteLength);
DSoundBufferRegionCurrentLocation(pHybridThis, dwPlayFlags, hRet, Xb_dwStartOffset, Xb_dwByteLength);
DSoundBufferResizeUpdate(pThis, dwPlayFlags, hRet, Xb_dwStartOffset, Xb_dwByteLength);
DSoundBufferResizeUpdate(pHybridThis, dwPlayFlags, hRet, Xb_dwStartOffset, Xb_dwByteLength);
}
static inline void DSoundBufferReplace(
static inline void DSoundBufferRegenWithNewFormat(
LPDIRECTSOUNDBUFFER8 &pDSBuffer,
DSBUFFERDESC &DSBufferDesc,
DWORD PlayFlags,
LPDIRECTSOUND3DBUFFER8 &pDS3DBuffer,
DWORD Xb_Frequency)
XTL::CDirectSoundVoice* Xb_Voice)
{
DWORD refCount, dwPlayCursor, dwStatus;
LPDIRECTSOUNDBUFFER8 pDSBufferNew = nullptr;
LPDIRECTSOUND3DBUFFER8 pDS3DBufferNew = nullptr;
DSoundBufferReCreate(pDSBuffer, DSBufferDesc, pDS3DBuffer,
pDSBufferNew, pDS3DBufferNew, Xb_Frequency);
pDSBufferNew, pDS3DBufferNew, Xb_Voice);
HRESULT hRet = pDSBuffer->GetStatus(&dwStatus);
@ -680,6 +684,40 @@ static inline HRESULT DSoundBufferSynchPlaybackFlagAdd(
return DS_OK;
}
static inline HRESULT DSoundBufferUpdateHostVolume(
LPDIRECTSOUNDBUFFER8 pDSBuffer,
uint32_t dwEmuFlags,
int32_t volume
)
{
if ((dwEmuFlags & DSE_FLAG_PCM) > 0) {
if (!g_XBAudio.codec_pcm) {
volume = DSBVOLUME_MIN;
}
} else if ((dwEmuFlags & DSE_FLAG_XADPCM) > 0) {
if (!g_XBAudio.codec_xadpcm) {
volume = DSBVOLUME_MIN;
}
} else if ((dwEmuFlags & DSE_FLAG_PCM_UNKNOWN) > 0) {
if (!g_XBAudio.codec_unknown) {
volume = DSBVOLUME_MIN;
}
}
if (volume <= -6400 && volume != DSBVOLUME_MIN) {
volume = DSBVOLUME_MIN;
} else if (volume > 0) {
EmuLog(LOG_LEVEL::WARNING, "volume has received greater than 0: %ld", volume);
volume = 0;
}
if ((dwEmuFlags & DSE_FLAG_DEBUG_MUTE) > 0) {
volume = DSBVOLUME_MIN;
}
return pDSBuffer->SetVolume(volume);
}
//TODO: RadWolfie - Need to implement DirectSoundBuffer create support. Or not able to do so due to all three classes function differently.
//IDirectSound
//IDirectSoundStream
@ -1045,7 +1083,7 @@ static inline HRESULT HybridDirectSound3DListener_SetDopplerFactor(
RETURN_RESULT_CHECK(hRet);
}
/*
//TODO: PC DirectSound does not have SetHeadroom method function.
//TODO: PC DirectSound does not have SetEG method function.
//IDirectSoundStream
//IDirectSoundBuffer
static inline HRESULT HybridDirectSoundBuffer_SetEG(
@ -1056,7 +1094,7 @@ static inline HRESULT HybridDirectSoundBuffer_SetEG(
return DS_OK;
}
//TODO: PC DirectSound does not have SetHeadroom method function.
//TODO: PC DirectSound does not have SetFilter method function.
//IDirectSoundStream
//IDirectSoundBuffer
static inline HRESULT HybridDirectSoundBuffer_SetFilter(
@ -1082,15 +1120,17 @@ static inline HRESULT HybridDirectSoundBuffer_SetFormat(
DWORD &X_BufferCacheSize,
XTL::X_DSVOICEPROPS &Xb_VoiceProperties,
XTL::X_LPDSMIXBINS mixbins_output,
DWORD Xb_Frequency)
XTL::CDirectSoundVoice* Xb_Voice)
{
pDSBuffer->Stop();
if (X_BufferAllocate) {
GeneratePCMFormat(BufferDesc, Xb_pwfxFormat, Xb_flags, 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, 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, xbnullptr, X_BufferCacheSize, Xb_VoiceProperties, mixbins_output);
GeneratePCMFormat(BufferDesc, Xb_pwfxFormat, Xb_flags, dwEmuFlags, 0,
xbnullptr, X_BufferCacheSize, Xb_VoiceProperties, mixbins_output, Xb_Voice);
}
HRESULT hRet = DS_OK;
if ((void*)g_pDSoundPrimaryBuffer == (void*)pDSBuffer) {
@ -1101,28 +1141,31 @@ static inline HRESULT HybridDirectSoundBuffer_SetFormat(
// Allocate at least 5 second worth of bytes in PCM format.
BufferDesc.dwBufferBytes = BufferDesc.lpwfxFormat->nAvgBytesPerSec * 5;
}
DSoundBufferReplace(pDSBuffer, BufferDesc, dwPlayFlags, pDS3DBuffer, Xb_Frequency);
DSoundBufferRegenWithNewFormat(pDSBuffer, BufferDesc, dwPlayFlags, pDS3DBuffer, Xb_Voice);
}
RETURN_RESULT_CHECK(hRet);
}
static HRESULT HybridDirectSoundBuffer_SetPitch(LPDIRECTSOUNDBUFFER8, LONG, XTL::CDirectSoundVoice*);
//IDirectSoundStream
//IDirectSoundBuffer
static inline HRESULT HybridDirectSoundBuffer_SetFrequency(
LPDIRECTSOUNDBUFFER8 pDSBuffer,
DWORD dwFrequency,
DWORD &Xb_Frequency)
XTL::CDirectSoundVoice* Xb_Voice)
{
HRESULT hRet = S_OK;
Xb_Frequency = dwFrequency;
hRet = pDSBuffer->SetFrequency(dwFrequency);
int32_t pitch = converter_freq2pitch((dwFrequency!=0 ? dwFrequency : Xb_Voice->GetFrequencyDefault()));
hRet = HybridDirectSoundBuffer_SetPitch(pDSBuffer, pitch, Xb_Voice);
RETURN_RESULT_CHECK(hRet);
}
static HRESULT HybridDirectSoundBuffer_SetVolume(LPDIRECTSOUNDBUFFER8, LONG, DWORD, LPLONG, LONG, DWORD);
static HRESULT HybridDirectSoundBuffer_SetVolume(LPDIRECTSOUNDBUFFER8, LONG, DWORD, LONG, XTL::CDirectSoundVoice*);
//IDirectSoundStream
//IDirectSoundBuffer
@ -1130,18 +1173,18 @@ static HRESULT HybridDirectSoundBuffer_SetVolume(LPDIRECTSOUNDBUFFER8, LONG, DWO
static inline HRESULT HybridDirectSoundBuffer_SetHeadroom(
LPDIRECTSOUNDBUFFER8 pDSBuffer,
DWORD dwHeadroom,
DWORD &Xb_dwHeadroom,
LONG Xb_volume,
LONG Xb_volumeMixbin,
DWORD dwEmuFlags)
DWORD dwEmuFlags,
XTL::CDirectSoundVoice* Xb_Voice)
{
HRESULT hRet;
if (dwHeadroom > 10000) {
hRet = DSERR_INVALIDPARAM;
} else {
Xb_dwHeadroom = dwHeadroom;
hRet = DS_OK;
HybridDirectSoundBuffer_SetVolume(pDSBuffer, Xb_volume, dwEmuFlags, xbnullptr, Xb_volumeMixbin, dwHeadroom);
Xb_Voice->SetHeadroom(dwHeadroom);
int32_t volume = Xb_Voice->GetVolume();
hRet = DSoundBufferUpdateHostVolume(pDSBuffer, dwEmuFlags, volume);
}
return DS_OK;
@ -1231,9 +1274,8 @@ static inline HRESULT HybridDirectSoundBuffer_SetMixBinVolumes_8(
XTL::X_LPDSMIXBINS pMixBins,
XTL::X_DSVOICEPROPS& Xb_VoiceProperties,
DWORD EmuFlags,
LONG Xb_volume,
LONG &Xb_volumeMixBin,
DWORD Xb_dwHeadroom)
XTL::CDirectSoundVoice* Xb_Voice)
{
HRESULT hRet = DSERR_INVALIDPARAM;
@ -1273,8 +1315,9 @@ static inline HRESULT HybridDirectSoundBuffer_SetMixBinVolumes_8(
}
if (counter > 0) {
Xb_volumeMixBin = volume / (LONG)counter;
hRet = HybridDirectSoundBuffer_SetVolume(pDSBuffer, Xb_volume, EmuFlags, nullptr,
Xb_volumeMixBin, Xb_dwHeadroom);
int32_t Xb_volume = Xb_Voice->GetVolume();
hRet = HybridDirectSoundBuffer_SetVolume(pDSBuffer, Xb_volume, EmuFlags,
Xb_volumeMixBin, Xb_Voice);
} else {
hRet = DS_OK;
}
@ -1326,27 +1369,14 @@ static inline HRESULT HybridDirectSoundBuffer_SetOutputBuffer(
static inline HRESULT HybridDirectSoundBuffer_SetPitch(
LPDIRECTSOUNDBUFFER8 pDSBuffer,
LONG lPitch,
DWORD &Xb_Frequency)
XTL::CDirectSoundVoice* Xb_Voice)
{
Xb_Voice->SetPitch(lPitch);
// Convert pitch back to frequency
// NOTE: pitch = 0 is equal to 48 KHz.
Xb_Frequency = static_cast<DWORD>(exp((lPitch / 4096.0f) * log(2)) * 48000.0f);
uint32_t setFrequency = converter_pitch2freq(lPitch);
/* For research purpose of how to convert frequency to pitch and back to frequency.
// Edit hertz variable to see the result.
float hertz = 12000.0f;
float hertzRatio = 48000.0f;
float pitchRatio = 4096.0f;
// Convert hertz to pitch
float pitch = log2(hertz / hertzRatio) * pitchRatio;
// Convert pitch to hertz
hertz = exp((pitch / pitchRatio) * log(2)) * hertzRatio;*/
RETURN_RESULT_CHECK(pDSBuffer->SetFrequency(Xb_Frequency));
RETURN_RESULT_CHECK(pDSBuffer->SetFrequency(setFrequency));
}
/*
//Only has one function, this is not a requirement.
@ -1429,46 +1459,20 @@ static inline HRESULT HybridDirectSoundBuffer_SetVolume(
LPDIRECTSOUNDBUFFER8 pDSBuffer,
LONG lVolume,
DWORD dwEmuFlags,
LPLONG Xb_lpVolume,
LONG Xb_volumeMixbin,
DWORD Xb_dwHeadroom)
XTL::CDirectSoundVoice* Xb_Voice)
{
// Preserve original volume
if (Xb_lpVolume != xbnullptr) {
*Xb_lpVolume = lVolume;
}
#if 0 // TODO: Restore it once DSound work update comes up
// For time being, this log is kept in case of something changed somewhere making a wrong input into the API.
printf("DEBUG: SetVolume | lVolume = %ld | volumeMixbin = %ld | dwHeadroom = %8u\n", lVolume, Xb_volumeMixbin, Xb_dwHeadroom);
#endif
lVolume += Xb_volumeMixbin - Xb_dwHeadroom;
Xb_Voice->SetVolume(lVolume);
lVolume = Xb_Voice->GetVolume();
lVolume += Xb_volumeMixbin;
if ((dwEmuFlags & DSE_FLAG_PCM) > 0) {
if (!g_XBAudio.codec_pcm) {
lVolume = DSBVOLUME_MIN;
}
} else if ((dwEmuFlags & DSE_FLAG_XADPCM) > 0) {
if (!g_XBAudio.codec_xadpcm) {
lVolume = DSBVOLUME_MIN;
}
} else if ((dwEmuFlags & DSE_FLAG_PCM_UNKNOWN) > 0) {
if (!g_XBAudio.codec_unknown) {
lVolume = DSBVOLUME_MIN;
}
}
if (lVolume <= -6400 && lVolume != DSBVOLUME_MIN) {
lVolume = DSBVOLUME_MIN;
} else if (lVolume > 0) {
EmuLog(LOG_LEVEL::WARNING, "HybridDirectSoundBuffer_SetVolume has received greater than 0: %ld", lVolume);
lVolume = 0;
}
if ((dwEmuFlags & DSE_FLAG_DEBUG_MUTE) > 0) {
lVolume = DSBVOLUME_MIN;
}
HRESULT hRet = pDSBuffer->SetVolume(lVolume);
HRESULT hRet = DSoundBufferUpdateHostVolume(pDSBuffer, dwEmuFlags, lVolume);
RETURN_RESULT_CHECK(hRet);
}

View File

@ -70,9 +70,9 @@ XTL::X_CDirectSoundStream::_vtbl XTL::X_CDirectSoundStream::vtbl =
&XTL::EMUPATCH(CDirectSoundStream_Process), // 0x10
&XTL::EMUPATCH(CDirectSoundStream_Discontinuity), // 0x14
&XTL::EMUPATCH(CDirectSoundStream_Flush), // 0x18
0xBEEFB003, // 0x1C
0xBEEFB004, // 0x20
0xBEEFB005, // 0x24
0xBEEFB003, // 0x1C // unknown function
0xBEEFB004, // 0x20 // DS_CRefCount_AddRef
0xBEEFB005, // 0x24 // DS_CRefCount_Release
0xBEEFB006, // 0x28
0xBEEFB007, // 0x2C
0xBEEFB008, // 0x30
@ -208,8 +208,6 @@ HRESULT WINAPI XTL::EMUPATCH(DirectSoundCreateStream)
hRet = DSERR_OUTOFMEMORY;
*ppStream = xbnullptr;
} else {
// TODO: Garbage Collection
*ppStream = new X_CDirectSoundStream();
DSBUFFERDESC DSBufferDesc = { 0 };
@ -230,12 +228,16 @@ HRESULT WINAPI XTL::EMUPATCH(DirectSoundCreateStream)
DSBufferDesc.dwFlags |= DSBCAPS_CTRLPAN;
}
// TODO: Garbage Collection
*ppStream = new X_CDirectSoundStream((DSBufferDesc.dwFlags & DSBCAPS_CTRL3D) != 0);
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, pdssd->dwFlags, (*ppStream)->EmuFlags, 0,
xbnullptr, (*ppStream)->X_BufferCacheSize, (*ppStream)->Xb_VoiceProperties, pdssd->lpMixBinsOutput);
xbnullptr, (*ppStream)->X_BufferCacheSize, (*ppStream)->Xb_VoiceProperties, pdssd->lpMixBinsOutput,
&(*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
// another test case below proven host's buffer size does not matter since packet's size can be greater than host's buffer size.
@ -269,14 +271,13 @@ HRESULT WINAPI XTL::EMUPATCH(DirectSoundCreateStream)
else {
if (DSBufferDesc.dwFlags & DSBCAPS_CTRL3D) {
DSound3DBufferCreate((*ppStream)->EmuDirectSoundBuffer8, (*ppStream)->EmuDirectSound3DBuffer8);
(*ppStream)->Xb_dwHeadroom = 0; // Default for 3D
}
DSoundDebugMuteFlag((*ppStream)->EmuBufferDesc.dwBufferBytes, (*ppStream)->EmuFlags);
// Pre-set volume to enforce silence if one of audio codec is disabled.
HybridDirectSoundBuffer_SetVolume((*ppStream)->EmuDirectSoundBuffer8, 0L, (*ppStream)->EmuFlags, nullptr,
(*ppStream)->Xb_VolumeMixbin, (*ppStream)->Xb_dwHeadroom);
HybridDirectSoundBuffer_SetVolume((*ppStream)->EmuDirectSoundBuffer8, 0L, (*ppStream)->EmuFlags,
(*ppStream)->Xb_VolumeMixbin, &(*ppStream)->Xb_Voice);
g_pDSoundStreamCache.push_back(*ppStream);
}
@ -912,7 +913,7 @@ HRESULT WINAPI XTL::EMUPATCH(CDirectSoundStream_SetFormat)
pThis->EmuBufferDesc, pThis->EmuFlags, pThis->EmuPlayFlags,
pThis->EmuDirectSound3DBuffer8, 0, pThis->X_BufferCache,
pThis->X_BufferCacheSize, pThis->Xb_VoiceProperties,
xbnullptr, pThis->Xb_Frequency);
xbnullptr, &pThis->Xb_Voice);
return hRet;
}
@ -932,7 +933,7 @@ HRESULT WINAPI XTL::EMUPATCH(CDirectSoundStream_SetFrequency)
LOG_FUNC_ARG(dwFrequency)
LOG_FUNC_END;
HRESULT hRet = HybridDirectSoundBuffer_SetFrequency(pThis->EmuDirectSoundBuffer8, dwFrequency, pThis->Xb_Frequency);
HRESULT hRet = HybridDirectSoundBuffer_SetFrequency(pThis->EmuDirectSoundBuffer8, dwFrequency, &pThis->Xb_Voice);
return hRet;
}
@ -967,8 +968,8 @@ HRESULT WINAPI XTL::EMUPATCH(CDirectSoundStream_SetHeadroom)
LOG_FUNC_ARG(dwHeadroom)
LOG_FUNC_END;
HRESULT hRet = HybridDirectSoundBuffer_SetHeadroom(pThis->EmuDirectSoundBuffer8, dwHeadroom, pThis->Xb_dwHeadroom,
pThis->Xb_Volume, pThis->Xb_VolumeMixbin, pThis->EmuFlags);
HRESULT hRet = HybridDirectSoundBuffer_SetHeadroom(pThis->EmuDirectSoundBuffer8, dwHeadroom,
pThis->Xb_VolumeMixbin, pThis->EmuFlags, &pThis->Xb_Voice);
return hRet;
}
@ -1208,7 +1209,7 @@ HRESULT WINAPI XTL::EMUPATCH(CDirectSoundStream_SetMixBinVolumes_8)
LOG_FUNC_END;
HRESULT hRet = HybridDirectSoundBuffer_SetMixBinVolumes_8(pThis->EmuDirectSoundBuffer8, pMixBins, pThis->Xb_VoiceProperties,
pThis->EmuFlags, pThis->Xb_Volume, pThis->Xb_VolumeMixbin, pThis->Xb_dwHeadroom);
pThis->EmuFlags, pThis->Xb_VolumeMixbin, &pThis->Xb_Voice);
return hRet;
}
@ -1219,7 +1220,7 @@ HRESULT WINAPI XTL::EMUPATCH(CDirectSoundStream_SetMixBinVolumes_8)
HRESULT WINAPI XTL::EMUPATCH(CDirectSoundStream_SetOutputBuffer)
(
X_CDirectSoundStream* pThis,
X_CDirectSoundBuffer* pOutputBuffer)
XbHybridDSBuffer* pOutputBuffer)
{
DSoundMutexGuardLock;
@ -1252,7 +1253,7 @@ HRESULT WINAPI XTL::EMUPATCH(CDirectSoundStream_SetPitch)
LOG_FUNC_ARG(lPitch)
LOG_FUNC_END;
HRESULT hRet = HybridDirectSoundBuffer_SetPitch(pThis->EmuDirectSoundBuffer8, lPitch, pThis->Xb_Frequency);
HRESULT hRet = HybridDirectSoundBuffer_SetPitch(pThis->EmuDirectSoundBuffer8, lPitch, &pThis->Xb_Voice);
return hRet;
}
@ -1303,7 +1304,7 @@ HRESULT WINAPI XTL::EMUPATCH(CDirectSoundStream_SetPosition)
// ******************************************************************
HRESULT WINAPI XTL::EMUPATCH(CDirectSoundStream_SetRolloffCurve)
(
X_CDirectSoundBuffer* pThis,
X_CDirectSoundStream* pThis,
const FLOAT* pflPoints,
DWORD dwPointCount,
DWORD dwApply)
@ -1387,8 +1388,8 @@ HRESULT WINAPI XTL::EMUPATCH(CDirectSoundStream_SetVolume)
LOG_FUNC_ARG(lVolume)
LOG_FUNC_END;
HRESULT hRet = HybridDirectSoundBuffer_SetVolume(pThis->EmuDirectSoundBuffer8, lVolume, pThis->EmuFlags, &pThis->Xb_Volume,
pThis->Xb_VolumeMixbin, pThis->Xb_dwHeadroom);
HRESULT hRet = HybridDirectSoundBuffer_SetVolume(pThis->EmuDirectSoundBuffer8, lVolume, pThis->EmuFlags,
pThis->Xb_VolumeMixbin, &pThis->Xb_Voice);
return hRet;
}

View File

@ -0,0 +1,213 @@
// ******************************************************************
// *
// * 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, Boston, MA 02111-1307, USA.
// *
// * (c) 2020 RadWolfie
// *
// * All rights reserved
// *
// ******************************************************************
#include "common\Settings.hpp" // for g_LibVersion_DSOUND
#include "XbInternalStruct.hpp"
// Interface for get format
template<class T>
void GetFormat_4034_lower(T& settings, XTL::audio_format& format)
{
format.audio_codec = settings.p_audio_format->wfx.wFormatTag = format.audio_codec;
format.nChannels = settings.p_audio_format->wfx.nChannels;
format.cbSize = settings.p_audio_format->wfx.cbSize;
format.nSamplesPerSec = settings.p_audio_format->wfx.nSamplesPerSec;
format.bitsPerSample = settings.p_audio_format->wfx.wBitsPerSample;
}
template<class T>
void GetFormat_4039_upper(T& settings, XTL::audio_format& format)
{
format.audio_codec = settings.audio_codec;
format.nChannels = settings.nChannels;
format.cbSize = settings.cbSize;
format.nSamplesPerSec = settings.nSamplesPerSec_default;
format.bitsPerSample = settings.bitsPerSample;
}
// Interface for set format
template<class T>
void SetFormat_4034_lower(T& settings, XTL::audio_format format)
{
settings.p_audio_format->wfx.wFormatTag = format.audio_codec;
settings.p_audio_format->wfx.nChannels = static_cast<uint16_t>(format.nChannels);
settings.p_audio_format->wfx.cbSize = static_cast<uint16_t>(format.cbSize);
settings.p_audio_format->wfx.nSamplesPerSec = format.nSamplesPerSec;
settings.p_audio_format->wfx.wBitsPerSample = static_cast<uint16_t>(format.bitsPerSample);
if (format.audio_codec == WAVE_FORMAT_XBOX_ADPCM) {
settings.p_audio_format->wSamplesPerBlock = 64;
}
settings.pitch = converter_freq2pitch(format.nSamplesPerSec);
}
template<class T>
void SetFormat_4039_only(T& settings, XTL::audio_format format)
{
settings.audio_codec = format.audio_codec;
settings.nChannels = format.nChannels;
settings.cbSize = format.cbSize;
settings.nSamplesPerSec_default = format.nSamplesPerSec;
settings.bitsPerSample = format.bitsPerSample;
settings.pitch = converter_freq2pitch(format.nSamplesPerSec);
}
template<class T>
void SetFormat_4134_upper(T& settings, XTL::audio_format format)
{
settings.audio_codec = static_cast<uint16_t>(format.audio_codec);
settings.nChannels = static_cast<uint8_t>(format.nChannels);
settings.cbSize = static_cast<uint8_t>(format.cbSize);
settings.nSamplesPerSec_default = format.nSamplesPerSec;
settings.bitsPerSample = format.bitsPerSample;
settings.pitch = converter_freq2pitch(format.nSamplesPerSec);
}
// Interface for get frequency
template<class T>
uint32_t GetFrequencyDefault_4034_lower(T& settings)
{
return settings.p_audio_format->wfx.nSamplesPerSec;
}
template<class T>
uint32_t GetFrequencyDefault_4039_upper(T& settings)
{
return settings.nSamplesPerSec_default;
}
// test case: WWE RAW 2's rdata section will directly access pitch value then call IDirectSoundBuffer_SetPitch.
// Interface for get pitch
template<class T>
int32_t GetPitch(T& settings)
{
return settings.pitch;
}
// Interface for set pitch
template<class T>
void SetPitch(T& settings, int32_t pitch)
{
settings.pitch = pitch;
}
// Interface for get volume
template<class T>
uint32_t GetVolume(T& settings)
{
return settings.volume;
}
// Interface for set volume
template<class T>
void SetVolume(T& settings, uint32_t volume)
{
settings.volume = volume - settings.headroom;
}
// Interface for get headroom
template<class T>
uint32_t GetHeadroom(T& settings)
{
return settings.headroom;
}
// Interface for set headroom
template<class T>
void SetHeadroom(T& settings, uint32_t set_headroom)
{
settings.volume = settings.volume - set_headroom - settings.headroom;
settings.headroom = set_headroom;
}
void Init_Headroom(uint32_t& headroom, bool is3D)
{
headroom = is3D? 0 : 600;
}
template<class T>
void Init(T& settings, bool is3D)
{
Init_Headroom(settings.headroom, is3D);
settings.volume = 0 - settings.headroom;
settings.volume = 0 - settings.headroom;
}
XTL::CDirectSoundVoice::CDirectSoundVoice(bool is3D)
{
settings = { 0 };
if (g_LibVersion_DSOUND < 4039) {
settings.r4034_lower.p_audio_format = new XBOXADPCMWAVEFORMAT;
memset(&settings.r4034_lower.p_audio_format->wfx, 0, sizeof(XBOXADPCMWAVEFORMAT));
using settings_template = _settings::_r4034_lower;
Init<settings_template>(settings.r4034_lower, is3D);
funcs.GetFormat = reinterpret_cast<pGetFormat>(::GetFormat_4034_lower<settings_template>);
funcs.SetFormat = reinterpret_cast<pSetFormat>(::SetFormat_4034_lower<settings_template>);
funcs.GetFrequencyDefault = reinterpret_cast<pGetUint32>(::GetFrequencyDefault_4034_lower<settings_template>);
funcs.GetPitch = reinterpret_cast<pGetInt32>(::GetPitch<settings_template>);
funcs.SetPitch = reinterpret_cast<pSetInt32>(::SetPitch<settings_template>);
funcs.GetVolume = reinterpret_cast<pGetInt32>(::GetVolume<settings_template>);
funcs.SetVolume = reinterpret_cast<pSetInt32>(::SetVolume<settings_template>);
funcs.GetHeadroom = reinterpret_cast<pGetUint32>(::GetHeadroom<settings_template>);
funcs.SetHeadroom = reinterpret_cast<pSetUint32>(::SetHeadroom<settings_template>);
}
else if (g_LibVersion_DSOUND == 4039) {
using settings_template = _settings::_r4039_only;
Init<settings_template>(settings.r4039_only, is3D);
funcs.GetFormat = reinterpret_cast<pGetFormat>(::GetFormat_4039_upper<settings_template>);
funcs.SetFormat = reinterpret_cast<pSetFormat>(::SetFormat_4039_only<settings_template>);
funcs.GetFrequencyDefault = reinterpret_cast<pGetUint32>(::GetFrequencyDefault_4039_upper<settings_template>);
funcs.GetPitch = reinterpret_cast<pGetInt32>(::GetPitch<settings_template>);
funcs.SetPitch = reinterpret_cast<pSetInt32>(::SetPitch<settings_template>);
funcs.GetVolume = reinterpret_cast<pGetInt32>(::GetVolume<settings_template>);
funcs.SetVolume = reinterpret_cast<pSetInt32>(::SetVolume<settings_template>);
funcs.GetHeadroom = reinterpret_cast<pGetUint32>(::GetHeadroom<settings_template>);
funcs.SetHeadroom = reinterpret_cast<pSetUint32>(::SetHeadroom<settings_template>);
}
else {
using settings_template = _settings::_r4134_upper;
Init<settings_template>(settings.r4134_upper, is3D);
funcs.GetFormat = reinterpret_cast<pGetFormat>(::GetFormat_4039_upper<settings_template>);
funcs.SetFormat = reinterpret_cast<pSetFormat>(::SetFormat_4134_upper<settings_template>);
funcs.GetFrequencyDefault = reinterpret_cast<pGetUint32>(::GetFrequencyDefault_4039_upper<settings_template>);
funcs.GetPitch = reinterpret_cast<pGetInt32>(::GetPitch<settings_template>);
funcs.SetPitch = reinterpret_cast<pSetInt32>(::SetPitch<settings_template>);
funcs.GetVolume = reinterpret_cast<pGetInt32>(::GetVolume<settings_template>);
funcs.SetVolume = reinterpret_cast<pSetInt32>(::SetVolume<settings_template>);
funcs.GetHeadroom = reinterpret_cast<pGetUint32>(::GetHeadroom<settings_template>);
funcs.SetHeadroom = reinterpret_cast<pSetUint32>(::SetHeadroom<settings_template>);
}
}
XTL::CDirectSoundVoice::~CDirectSoundVoice()
{
if (g_LibVersion_DSOUND < 4039) {
if (!settings.r4034_lower.p_audio_format) {
delete settings.r4034_lower.p_audio_format;
settings.r4034_lower.p_audio_format = nullptr;
}
}
}

View File

@ -0,0 +1,34 @@
// ******************************************************************
// *
// * 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, Boston, MA 02111-1307, USA.
// *
// * (c) 2020 RadWolfie
// *
// * All rights reserved
// *
// ******************************************************************
#include "XbInternalStruct.hpp"
XTL::CUnknownTemplate::CUnknownTemplate() { ref_count = 1; }
XTL::CMcpxVoiceClient::_settings XTL::CMcpxVoiceClient::default_settings =
{
0, // 0x08
// ...
};

View File

@ -0,0 +1,246 @@
// ******************************************************************
// *
// * 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, Boston, MA 02111-1307, USA.
// *
// * (c) 2020 RadWolfie
// *
// * All rights reserved
// *
// ******************************************************************
#pragma once
#include "Cxbx.h"
#include "core\hle\DSOUND\XbDSoundTypes.h"
#include "common/audio/converter.hpp"
namespace XTL {
// TODO: Everything, only small portions had been implemented.
// Note to all maintainers, make sure structure's class-like are not misalign.
// There is always a VMT (Virtual Method Table) pointer at offset 0x00 (uint32_t size).
// Afterward are depending on what internal data are placed. So, whenever implementing a functions.
// Whenever implementing functional codes, make sure they are at the bottom of the xbox's structure. Thanks!
struct audio_format {
uint32_t audio_codec;
uint32_t nChannels;
uint32_t cbSize;
int32_t nSamplesPerSec;
uint32_t bitsPerSample;
};
struct CUnknownGenericManager {
// construct vtable (or grab ptr to existing)
CUnknownGenericManager() : ref_count(1) {}
// all VMT (Virtual Method Table) are stored in local offset 0x00's pointer
// TODO: Implement to use derived's override AddRef/Release. Also, each class has its own ref counter and is not shareable.
virtual ~CUnknownGenericManager() {}; // 0x00
virtual uint32_t WINAPI AddRef() { return ref_count++; }; // 0x04
virtual uint32_t WINAPI Release() { return ref_count--; }; // 0x08
uint32_t ref_count; // 0x04
};
// Require to verify there is no other unknown additional data by compiler itself.
static_assert(sizeof(CUnknownGenericManager) == 0x08);
struct CUnknownTemplate {
// construct vtable (or grab ptr to existing)
CUnknownTemplate();
virtual ~CUnknownTemplate() {}; // 0x00
virtual void WINAPI pUnknown_04() { throw std::exception("pUnknown_04"); }; // 0x04
virtual void WINAPI pUnknown_08() { throw std::exception("pUnknown_08"); }; // 0x08
virtual void WINAPI pUnknown_0C() { throw std::exception("pUnknown_0C"); }; // 0x0C
virtual void WINAPI pUnknown_10() { throw std::exception("pUnknown_10"); }; // 0x10
virtual void WINAPI pUnknown_14() { throw std::exception("pUnknown_14"); }; // 0x14
virtual void WINAPI pUnknown_18() { throw std::exception("pUnknown_18"); }; // 0x18
virtual void WINAPI pUnknown_1C() { throw std::exception("pUnknown_1C"); }; // 0x1C
// If need to add more VMT (Virtual Method Table), add them above here.
uint32_t ref_count; // 0x04
};
// Require to verify there is no other unknown additional data by compiler itself.
static_assert(sizeof(CUnknownTemplate) == 0x08);
struct CMcpxVoiceClient: CUnknownTemplate {
CMcpxVoiceClient() : settings(default_settings) {};
// all VMT (Virtual Method Table) are stored in local offset 0x00's pointer
virtual ~CMcpxVoiceClient() {};
// CUnknownTemplate // 0x00 - ???
struct _settings
{
uint32_t Unknown2[(0x300-8)/4]; // 0x08 - ???
}
settings;
// global _settings for this class
static _settings default_settings;
};
// Require to verify there is no other unknown additional data by compiler itself.
static_assert(sizeof(CMcpxVoiceClient) == 0x300);
struct CDirectSoundVoice : CUnknownGenericManager {
CDirectSoundVoice(bool is3D);
// all VMT (Virtual Method Table) are stored in local offset 0x00's pointer
virtual ~CDirectSoundVoice();
// CUnknownGenericManager // 0x00 - ???
union _settings {
struct _unknown
{
uint32_t unknown_08[0x300 / 4]; // 0x000 - 0x300 (unknown size, likely over 0x200 size.
} unknown;
struct _r4034_lower {
xbaddr p_unknown_08; // 0x008
uint16_t unknown_0C; // 0x00C // zero'd - unknown
XBOXADPCMWAVEFORMAT* p_audio_format; // 0x010 // Same as XBOXADPCMWAVEFORMAT / WAVEFORMATEX structure
int32_t pitch; // 0x014 // Always init and custom pitch from SetFrequency, SetPitch, SetFormat, etc calls.
int32_t volume; // 0x018 // default: (set volume - headroom)
uint32_t headroom; // 0x01C // default: (set headroom then update volume)
} r4034_lower;
struct _r4039_only {
uint32_t unknown_08; // 0x008
uint32_t audio_codec; // 0x00C // Setter is 32 bit, yet getter is 16 bit integer reader
uint32_t nChannels; // 0x010
uint32_t cbSize; // 0x014
int32_t nSamplesPerSec_default; // 0x018 // Always original frequency for check if SetFrequency is given with 0 then use original one.
uint32_t bitsPerSample; // 0x01C
int32_t pitch; // 0x020 // Always init and custom pitch from SetFrequency, SetPitch, SetFormat, etc calls.
int32_t volume; // 0x024 // (set volume - headroom)
uint32_t headroom; // 0x028 // (set headroom then update volume)
uint32_t unknown_2C[(0x300 - 0x2C) / 4]; // 0x02C - 0x300 (unknown size, likely over 0x200 size.
} r4039_only;
struct _r4134_upper {
uint32_t unknown_08; // 0x008
uint16_t audio_codec; // 0x00C
uint8_t nChannels; // 0x00E
uint8_t cbSize; // 0x00F
uint32_t nSamplesPerSec_default; // 0x010 // Always original frequency for check if SetFrequency is given with 0 then use original one.
uint32_t bitsPerSample; // 0x014
int32_t pitch; // 0x018 // Always init and custom pitch from SetFrequency, SetPitch, SetFormat, etc calls.
int32_t volume; // 0x01C // (set volume - headroom)
uint32_t headroom; // 0x020 // (set headroom then update volume)
uint32_t unknown_24[(0x300 - 0x24) / 4]; // 0x024 - 0x300 (unknown size, likely over 0x200 size.
} r4134_upper;
} settings;
static_assert(sizeof(_settings) == 0x300); // Not really require
// Generic interface without need to check xdk's build revision every time.
typedef void (*pGetFormat)(_settings& settings, audio_format& format);
typedef void (*pSetFormat)(_settings& settings, audio_format format);
typedef uint32_t (*pGetUint32)(_settings& settings);
typedef void (*pSetUint32)(_settings& settings, uint32_t value);
typedef int32_t (*pGetInt32)(_settings& settings);
typedef void (*pSetInt32)(_settings& settings, int32_t value);
struct {
pGetFormat GetFormat;
pSetFormat SetFormat;
pGetUint32 GetFrequencyDefault;
pGetInt32 GetPitch;
pSetInt32 SetPitch;
pGetInt32 GetVolume;
pSetInt32 SetVolume;
pGetUint32 GetHeadroom;
pSetUint32 SetHeadroom;
} funcs;
static_assert(sizeof(funcs) == 0x24); // Not really require
inline void GetFormat(audio_format& format) {
funcs.GetFormat(settings, format);
};
inline void SetFormat(audio_format format) {
funcs.SetFormat(settings, format);
};
inline uint32_t GetFrequencyDefault() {
return funcs.GetFrequencyDefault(settings);
};
inline int32_t GetPitch() {
return funcs.GetPitch(settings);
};
inline void SetPitch(int32_t pitch) {
funcs.SetPitch(settings, pitch);
};
inline int32_t GetVolume() {
return funcs.GetVolume(settings);
};
inline void SetVolume(int32_t volume) {
funcs.SetVolume(settings, volume);
};
inline uint32_t GetHeadroom() {
return funcs.GetHeadroom(settings);
};
inline void SetHeadroom(uint32_t headroom) {
funcs.SetHeadroom(settings, headroom);
};
};
// Require to verify there is no other unknown additional data by compiler itself.
static_assert(sizeof(CDirectSoundVoice) == sizeof(CUnknownGenericManager) + sizeof(CDirectSoundVoice::_settings) + sizeof(CDirectSoundVoice::funcs));
struct DSBUFFER_S : CUnknownTemplate {
// CUnknownTemplate unknown_00; // Offset 0x00 // -0x1C
struct DSBUFFER_C {
uint32_t unknown_08; // Offset 0x08 // -0x14
CMcpxVoiceClient* p_CMcpxVoiceClient; // Offset 0x0C // -0x10
CDirectSoundVoice* p_CDSVoice; // Offset 0x10 // -0x0C
xbaddr p_unknown_14; // Offset 0x14 // -0x08 // (points to this address)
xbaddr p_unknown_18; // Offset 0x18 // -0x04 // (points to above address)
} dsb_c;
static_assert(sizeof(DSBUFFER_C) == 0x14);
struct DSBUFFER_I {
CDirectSoundVoice* p_CDSVoice; // Offset 0x1C // 0x00 // Same as p_CDSVoice (above); pThis
CMcpxVoiceClient* p_CMcpxVoiceClient; // Offset 0x20 // 0x04 // Same as p_CMcpxVoiceClient (above)
xbaddr p_unknown_24; // Offset 0x24 // 0x08
xbaddr p_unknown_28; // Offset 0x28 // 0x0C
uint32_t unknown_2C; // Offset 0x2C // 0x10 // was integer, later shift to offset 0x30
uint32_t unknown_30; // Offset 0x30 // 0x14 // later shifted from offset 0x2C; integer
} dsb_i;
static_assert(sizeof(DSBUFFER_I) == 0x18);
DSBUFFER_S(bool is3D) {
init(is3D);
}
virtual ~DSBUFFER_S() {
delete dsb_c.p_CMcpxVoiceClient;
delete dsb_c.p_CDSVoice;
}
virtual void init_member() {
dsb_c.unknown_08 = 0;
dsb_i.p_unknown_24 = xbnull;
dsb_i.p_unknown_28 = xbnull;
dsb_i.unknown_2C = xbnull;
dsb_i.unknown_30 = xbnull;
}
virtual void init(bool is3D) {
init_member();
dsb_c.p_CMcpxVoiceClient = new CMcpxVoiceClient(); dsb_i.p_CMcpxVoiceClient = dsb_c.p_CMcpxVoiceClient;
dsb_c.p_CDSVoice = new CDirectSoundVoice(is3D); dsb_i.p_CDSVoice = dsb_c.p_CDSVoice;
dsb_c.p_unknown_18 = reinterpret_cast<xbaddr>(&dsb_c.p_unknown_14);
dsb_c.p_unknown_14 = dsb_c.p_unknown_18;
}
};
// Require to verify there is no other unknown additional data by compiler itself.
static_assert(sizeof(DSBUFFER_S) == 0x34);
}

View File

@ -251,15 +251,17 @@ static void WFXformat_SanityFix(
}
static CODEC_FORMAT WFXformat_SyncHostFormat(
void* Host_wfx_ptr,
const void* Xb_wfx_ptr,
uint32_t Xb_buffer_request_size,
uint32_t Xb_flags)
void* Host_wfx_ptr,
const void* Xb_wfx_ptr,
uint32_t Xb_buffer_request_size,
uint32_t Xb_flags,
XTL::CDirectSoundVoice* Xb_Voice)
{
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;
XTL::audio_format xb_format;
// If no format is provided, then use default.
if (Xb_wfx_ptr == xbnullptr) {
@ -332,5 +334,13 @@ static CODEC_FORMAT WFXformat_SyncHostFormat(
WFXformat_GeneratePCMFormat(2, 44100, 16, Host_wfxFormat);
}
}
// Forward xbox format to internal XTL::CDirectSoundVoice class.
xb_format.audio_codec = (codec_format_ret == CF_XADPCM ? WAVE_FORMAT_XBOX_ADPCM : WAVE_FORMAT_PCM);
xb_format.nChannels = Host_wfxFormat->Format.nChannels;
xb_format.cbSize = (codec_format_ret == CF_XADPCM ? 4 : 0);
xb_format.nSamplesPerSec = Host_wfxFormat->Format.nSamplesPerSec;
xb_format.bitsPerSample = (codec_format_ret == CF_XADPCM ? 4 : Host_wfxFormat->Format.wBitsPerSample);
Xb_Voice->SetFormat(xb_format);
return codec_format_ret;
}