Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SPU: Rewrite ADSR/Volume slides #10084

Merged
merged 7 commits into from
Oct 15, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
SPU2: Get rid of 32bit volumes [SAVEVERSION+]
  • Loading branch information
Ziemas committed Oct 13, 2023
commit cc17113c9d88032944da102b2a1b8e1cebd011cd
37 changes: 5 additions & 32 deletions pcsx2/SPU2/Mixer.cpp
Original file line number Diff line number Diff line change
@@ -28,24 +28,6 @@ static const s32 tbl_XA_Factor[16][2] =
{98, -55},
{122, -60}};

// Performs a 64-bit multiplication between two values and returns the
// high 32 bits as a result (discarding the fractional 32 bits).
// The combined fractional bits of both inputs must be 32 bits for this
// to work properly.
//
// This is meant to be a drop-in replacement for times when the 'div' part
// of a MulDiv is a constant. (example: 1<<8, or 4096, etc)
//
// [Air] Performance breakdown: This is over 10 times faster than MulDiv in
// a *worst case* scenario. It's also more accurate since it forces the
// caller to extend the inputs so that they make use of all 32 bits of
// precision.
//
static __forceinline s32 MulShr32(s32 srcval, s32 mulval)
{
return static_cast<s64>(srcval) * mulval >> 32;
}

__forceinline s32 clamp_mix(s32 x)
{
return std::clamp(x, -0x8000, 0x7fff);
@@ -278,16 +260,7 @@ static __forceinline void GetNextDataDummy(V_Core& thiscore, uint voiceidx)
/////////////////////////////////////////////////////////////////////////////////////////
// //

// Data is expected to be 16 bit signed (typical stuff!).
// volume is expected to be 32 bit signed (31 bits with reverse phase)
// Data is shifted up by 1 bit to give the output an effective 16 bit range.
static __forceinline s32 ApplyVolume(s32 data, s32 volume)
{
//return (volume * data) >> 15;
return MulShr32(data << 1, volume);
}

static __forceinline s32 ApplyVolume16(s32 data, s32 volume)
{
return (volume * data) >> 15;
}
@@ -302,8 +275,8 @@ static __forceinline StereoOut32 ApplyVolume(const StereoOut32& data, const V_Vo
static __forceinline StereoOut32 ApplyVolume(const StereoOut32& data, const V_VolumeSlideLR& volume)
{
return StereoOut32(
ApplyVolume16(data.Left, volume.Left.Value),
ApplyVolume16(data.Right, volume.Right.Value));
ApplyVolume(data.Left, volume.Left.Value),
ApplyVolume(data.Right, volume.Right.Value));
}

static void __forceinline UpdatePitch(uint coreidx, uint voiceidx)
@@ -485,7 +458,7 @@ static __forceinline StereoOut32 MixVoice(uint coreidx, uint voiceidx)
// use a full 64-bit multiply/result here.

CalculateADSR(thiscore, voiceidx);
Value = ApplyVolume16(Value, vc.ADSR.Value);
Value = ApplyVolume(Value, vc.ADSR.Value);
vc.OutX = Value;

if (IsDevBuild)
@@ -684,8 +657,8 @@ __forceinline
}
else
{
Out.Left = ApplyVolume16(Out.Left, Cores[1].MasterVol.Left.Value);
Out.Right = ApplyVolume16(Out.Right, Cores[1].MasterVol.Right.Value);
Out.Left = ApplyVolume(Out.Left, Cores[1].MasterVol.Left.Value);
Out.Right = ApplyVolume(Out.Right, Cores[1].MasterVol.Right.Value);
}

// Final Clamp!
32 changes: 16 additions & 16 deletions pcsx2/SPU2/RegTable.cpp
Original file line number Diff line number Diff line change
@@ -243,14 +243,14 @@ static std::array<u16*, 0x401> ComputeRegTable()
//0x760: weird area
PCORE(0, MasterVol.Left.Reg_VOL),
PCORE(0, MasterVol.Right.Reg_VOL),
PCORE(0, FxVol.Left) + 1,
PCORE(0, FxVol.Right) + 1,
PCORE(0, ExtVol.Left) + 1,
PCORE(0, ExtVol.Right) + 1,
PCORE(0, InpVol.Left) + 1,
PCORE(0, InpVol.Right) + 1,
PCORE(0, MasterVol.Left.Value) + 1,
PCORE(0, MasterVol.Right.Value) + 1,
PCORE(0, FxVol.Left),
PCORE(0, FxVol.Right),
PCORE(0, ExtVol.Left),
PCORE(0, ExtVol.Right),
PCORE(0, InpVol.Left),
PCORE(0, InpVol.Right),
PCORE(0, MasterVol.Left.Value),
PCORE(0, MasterVol.Right.Value),
PCORE(0, Revb.IIR_VOL),
PCORE(0, Revb.COMB1_VOL),
PCORE(0, Revb.COMB2_VOL),
@@ -264,14 +264,14 @@ static std::array<u16*, 0x401> ComputeRegTable()

PCORE(1, MasterVol.Left.Reg_VOL),
PCORE(1, MasterVol.Right.Reg_VOL),
PCORE(1, FxVol.Left) + 1,
PCORE(1, FxVol.Right) + 1,
PCORE(1, ExtVol.Left) + 1,
PCORE(1, ExtVol.Right) + 1,
PCORE(1, InpVol.Left) + 1,
PCORE(1, InpVol.Right) + 1,
PCORE(1, MasterVol.Left.Value) + 1,
PCORE(1, MasterVol.Right.Value) + 1,
PCORE(1, FxVol.Left),
PCORE(1, FxVol.Right),
PCORE(1, ExtVol.Left),
PCORE(1, ExtVol.Right),
PCORE(1, InpVol.Left),
PCORE(1, InpVol.Right),
PCORE(1, MasterVol.Left.Value),
PCORE(1, MasterVol.Right.Value),
PCORE(1, Revb.IIR_VOL),
PCORE(1, Revb.COMB1_VOL),
PCORE(1, Revb.COMB2_VOL),
29 changes: 11 additions & 18 deletions pcsx2/SPU2/spu2sys.cpp
Original file line number Diff line number Diff line change
@@ -103,7 +103,7 @@ __forceinline void spu2M_Write(u32 addr, u16 value)
spu2M_Write(addr, (s16)value);
}

V_VolumeLR V_VolumeLR::Max(0x7FFFFFFF);
V_VolumeLR V_VolumeLR::Max(0x7FFF);
V_VolumeSlideLR V_VolumeSlideLR::Max(0x3FFF, 0x7FFF);

V_Core::V_Core(int coreidx)
@@ -478,13 +478,6 @@ __forceinline void UpdateSpdifMode()
}
}

// Converts an SPU2 register volume write into a 32 bit SPU2 volume. The value is extended
// properly into the lower 16 bits of the value to provide a full spectrum of volumes.
static s32 GetVol32(u16 src)
{
return ((static_cast<s32>(src)) << 16) | ((src << 1) & 0xffff);
}

static u32 map_spu1to2(u32 addr)
{
return addr * 4 + (addr >= 0x200 ? 0xc0000 : 0);
@@ -565,11 +558,11 @@ void V_Core::WriteRegPS1(u32 mem, u16 value)
break;

case 0x1d84: // Reverberation depth left
FxVol.Left = GetVol32(value);
FxVol.Left = SignExtend16(value);
break;

case 0x1d86: // Reverberation depth right
FxVol.Right = GetVol32(value);
FxVol.Right = SignExtend16(value);
break;

case 0x1d88: // Voice ON (0-15)
@@ -875,10 +868,10 @@ u16 V_Core::ReadRegPS1(u32 mem)
value = MasterVol.Right.Value;
break;
case 0x1d84:
value = FxVol.Left >> 16;
value = FxVol.Left;
break;
case 0x1d86:
value = FxVol.Right >> 16;
value = FxVol.Right;
break;

case 0x1d88:
@@ -1389,27 +1382,27 @@ static void RegWrite_CoreExt(u16 value)
break;

case REG_P_EVOLL:
thiscore.FxVol.Left = GetVol32(value);
thiscore.FxVol.Left = SignExtend16(value);
break;

case REG_P_EVOLR:
thiscore.FxVol.Right = GetVol32(value);
thiscore.FxVol.Right = SignExtend16(value);
break;

case REG_P_AVOLL:
thiscore.ExtVol.Left = GetVol32(value);
thiscore.ExtVol.Left = SignExtend16(value);
break;

case REG_P_AVOLR:
thiscore.ExtVol.Right = GetVol32(value);
thiscore.ExtVol.Right = SignExtend16(value);
break;

case REG_P_BVOLL:
thiscore.InpVol.Left = GetVol32(value);
thiscore.InpVol.Left = SignExtend16(value);
break;

case REG_P_BVOLR:
thiscore.InpVol.Right = GetVol32(value);
thiscore.InpVol.Right = SignExtend16(value);
break;

// MVOLX has been confirmed to not be allowed to be written to, so cases have been added as a no-op.
2 changes: 1 addition & 1 deletion pcsx2/SaveState.h
Original file line number Diff line number Diff line change
@@ -37,7 +37,7 @@ enum class FreezeAction
// [SAVEVERSION+]
// This informs the auto updater that the users savestates will be invalidated.

static const u32 g_SaveVersion = (0x9A45 << 16) | 0x0000;
static const u32 g_SaveVersion = (0x9A46 << 16) | 0x0000;


// the freezing data between submodules and core