mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-10-11 22:49:56 +00:00
SPU: Do DC filtering with float samples
This commit is contained in:
@@ -519,20 +519,6 @@ static __forceinline StereoOut32 MixCore(const uint coreidx, const VoiceMixSet&
|
||||
return TD + ApplyVolume(RV, thiscore.FxVol);
|
||||
}
|
||||
|
||||
static StereoOut32 DCFilter(StereoOut32 input)
|
||||
{
|
||||
// A simple DC blocking high-pass filter
|
||||
// Implementation from http://peabody.sapp.org/class/dmp2/lab/dcblock/
|
||||
// The magic number 0x7f5c is ceil(INT16_MAX * 0.995)
|
||||
StereoOut32 output;
|
||||
output.Left = (input.Left - DCFilterIn.Left + clamp_mix((0x7f5c * DCFilterOut.Left) >> 15));
|
||||
output.Right = (input.Right - DCFilterIn.Right + clamp_mix((0x7f5c * DCFilterOut.Right) >> 15));
|
||||
|
||||
DCFilterIn = input;
|
||||
DCFilterOut = output;
|
||||
return output;
|
||||
}
|
||||
|
||||
void spu2Mix()
|
||||
{
|
||||
// Note: Playmode 4 is SPDIF, which overrides other inputs.
|
||||
@@ -591,13 +577,6 @@ void spu2Mix()
|
||||
Out = ApplyVolume(clamp_mix(Out), Cores[1].MasterVol);
|
||||
}
|
||||
|
||||
// For a long time PCSX2 has had its output volume halved by
|
||||
// an incorrect function for applying the master volume above.
|
||||
//
|
||||
// Adjust volume here so it matches what people have come to expect.
|
||||
Out = ApplyVolume(Out, {0x4fff, 0x4fff});
|
||||
Out = DCFilter(Out);
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
// Log final output to wavefile.
|
||||
WaveDump::WriteCore(1, CoreSrc_External, Out);
|
||||
|
||||
@@ -569,8 +569,6 @@ extern u16 OutPos;
|
||||
extern u16 InputPos;
|
||||
// SPU Mixing Cycles ("Ticks mixed" counter)
|
||||
extern u32 Cycles;
|
||||
// DC Filter state
|
||||
extern StereoOut32 DCFilterIn, DCFilterOut;
|
||||
|
||||
extern s16 spu2regs[0x010000 / sizeof(s16)];
|
||||
extern s16 _spu2mem[0x200000 / sizeof(s16)];
|
||||
|
||||
+33
-3
@@ -36,6 +36,8 @@ static u32 s_current_chunk_pos;
|
||||
static u32 s_standard_volume = 0;
|
||||
static u32 s_fast_forward_volume = 0;
|
||||
|
||||
float DCFilterIn[2], DCFilterOut[2];
|
||||
|
||||
u32 SPU2::GetConsoleSampleRate()
|
||||
{
|
||||
return s_psxmode ? PSX_SAMPLE_RATE : SAMPLE_RATE;
|
||||
@@ -232,6 +234,9 @@ void SPU2::InternalReset(bool psxmode)
|
||||
memset(_spu2mem + 0x2800, 7, 0x10); // from BIOS reversal. Locks the voices so they don't run free.
|
||||
memset(_spu2mem + 0xe870, 7, 0x10); // Loop which gets left over by the BIOS, Megaman X7 relies on it being there.
|
||||
|
||||
memset(DCFilterIn, 0, sizeof(DCFilterIn));
|
||||
memset(DCFilterOut, 0, sizeof(DCFilterOut));
|
||||
|
||||
Spdif.Info = 0; // Reset IRQ Status if it got set in a previously run game
|
||||
|
||||
Cores[0].Init(0);
|
||||
@@ -484,11 +489,36 @@ s32 SPU2freeze(FreezeAction mode, freezeData* data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void DCFilter(float *input)
|
||||
{
|
||||
// A simple DC blocking high-pass filter
|
||||
// Implementation from http://peabody.sapp.org/class/dmp2/lab/dcblock/
|
||||
float output[2];
|
||||
output[0] = (input[0] - DCFilterIn[0] + ((0.995f * DCFilterOut[0])));
|
||||
output[1] = (input[1] - DCFilterIn[1] + ((0.995f * DCFilterOut[1])));
|
||||
|
||||
DCFilterIn[0] = input[0];
|
||||
DCFilterIn[1] = input[1];
|
||||
DCFilterOut[0] = output[0];
|
||||
DCFilterOut[1] = output[1];
|
||||
|
||||
input[0] = output[0];
|
||||
input[1] = output[1];
|
||||
}
|
||||
|
||||
__forceinline void spu2Output(StereoOut32 out)
|
||||
{
|
||||
// Final clamp, take care not to exceed 16 bits from here on
|
||||
s_current_chunk[s_current_chunk_pos++] = static_cast<float>(clamp_mix(out.Left)) / INT16_MAX;
|
||||
s_current_chunk[s_current_chunk_pos++] = static_cast<float>(clamp_mix(out.Right)) / INT16_MAX;
|
||||
float conv[2];
|
||||
|
||||
conv[0] = static_cast<float>(clamp_mix(out.Left)) / INT16_MAX;
|
||||
conv[1] = static_cast<float>(clamp_mix(out.Right)) / INT16_MAX;
|
||||
|
||||
/* Some games pause voices with the volume left on leaving us with
|
||||
* significant DC offset, so we filter it out (e.x. SSX 3)*/
|
||||
DCFilter(conv);
|
||||
|
||||
s_current_chunk[s_current_chunk_pos++] = conv[0];
|
||||
s_current_chunk[s_current_chunk_pos++] = conv[1];
|
||||
if (s_current_chunk_pos == s_current_chunk.size())
|
||||
{
|
||||
s_current_chunk_pos = 0;
|
||||
|
||||
@@ -26,7 +26,6 @@ V_CoreDebug DebugCores[2];
|
||||
V_Core Cores[2];
|
||||
V_SPDIF Spdif;
|
||||
|
||||
StereoOut32 DCFilterIn, DCFilterOut;
|
||||
u16 OutPos;
|
||||
u16 InputPos;
|
||||
u32 Cycles;
|
||||
@@ -127,8 +126,6 @@ void V_Core::Init(int index)
|
||||
DMAPtr = nullptr;
|
||||
KeyOn = 0;
|
||||
OutPos = 0;
|
||||
DCFilterIn = {};
|
||||
DCFilterOut = {};
|
||||
|
||||
psxmode = false;
|
||||
psxSoundDataTransferControl = 0;
|
||||
|
||||
Reference in New Issue
Block a user