SPU2: Get rid of 32bit volumes [SAVEVERSION+]

This commit is contained in:
Ziemas 2023-10-10 01:26:50 +02:00 committed by refractionpcsx2
parent 07d4a65a45
commit 16a11b75a8
4 changed files with 33 additions and 67 deletions

View File

@ -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!

View File

@ -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),

View File

@ -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.

View File

@ -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