diff --git a/plugins/spu2-x/src/Config.h b/plugins/spu2-x/src/Config.h index 30956b11dc..04b8843fd4 100644 --- a/plugins/spu2-x/src/Config.h +++ b/plugins/spu2-x/src/Config.h @@ -63,6 +63,7 @@ extern int Interpolation; extern int ReverbBoost; extern int numSpeakers; extern bool EffectsDisabled; +extern bool postprocess_filter_enabled; extern u32 OutputModule; extern int SndOutLatencyMS; diff --git a/plugins/spu2-x/src/Global.h b/plugins/spu2-x/src/Global.h index 83400c6f6f..5e10d5498c 100644 --- a/plugins/spu2-x/src/Global.h +++ b/plugins/spu2-x/src/Global.h @@ -88,6 +88,9 @@ extern void SysMessage(const wchar_t *fmt, ...); # define SPU2_LOG #endif +// Uncomment to enable debug keys on numpad (0 to 5) +//#define DEBUG_KEYS + #include "Utilities/Exceptions.h" #include "Utilities/SafeArray.h" diff --git a/plugins/spu2-x/src/Linux/Config.cpp b/plugins/spu2-x/src/Linux/Config.cpp index 08d64505f0..a899f0c6c8 100644 --- a/plugins/spu2-x/src/Linux/Config.cpp +++ b/plugins/spu2-x/src/Linux/Config.cpp @@ -43,6 +43,7 @@ int Interpolation = 1; bool EffectsDisabled = false; int ReverbBoost = 0; +bool postprocess_filter_enabled = 1; // OUTPUT u32 OutputModule = 0; diff --git a/plugins/spu2-x/src/Linux/Config.h b/plugins/spu2-x/src/Linux/Config.h index ae5f42ded5..4c3c38c77d 100644 --- a/plugins/spu2-x/src/Linux/Config.h +++ b/plugins/spu2-x/src/Linux/Config.h @@ -69,6 +69,7 @@ static __forceinline bool RegDump() { return _RegDump & DebugEnabled; }*/ extern int Interpolation; extern int ReverbBoost; extern bool EffectsDisabled; +extern bool postprocess_filter_enabled = 1; extern int AutoDMAPlayRate[2]; diff --git a/plugins/spu2-x/src/Mixer.cpp b/plugins/spu2-x/src/Mixer.cpp index a39b1d70d1..a9db8593f3 100644 --- a/plugins/spu2-x/src/Mixer.cpp +++ b/plugins/spu2-x/src/Mixer.cpp @@ -723,6 +723,80 @@ StereoOut32 V_Core::Mix( const VoiceMixSet& inVoices, const StereoOut32& Input, return TD + ApplyVolume( RV*temp, FxVol ); } +// Filters that work on the final output to de-alias and equlize it. +// Taken from http://nenolod.net/projects/upse/ +#define OVERALL_SCALE (0.87f) + +StereoOut32 Apply_Frequency_Response_Filter(StereoOut32 &SoundStream) +{ + static FrequencyResponseFilter FRF = FrequencyResponseFilter(); + + s32 in, out; + s32 l, r; + s32 mid, side; + + l = SoundStream.Left; + r = SoundStream.Right; + + mid = l + r; + side = l - r; + + in = mid; + out = FRF.la0 * in + FRF.la1 * FRF.lx1 + FRF.la2 * FRF.lx2 - FRF.lb1 * FRF.ly1 - FRF.lb2 * FRF.ly2; + + FRF.lx2 = FRF.lx1; + FRF.lx1 = in; + + FRF.ly2 = FRF.ly1; + FRF.ly1 = out; + + mid = out; + + l = ((0.5) * (OVERALL_SCALE)) * (mid + side); + r = ((0.5) * (OVERALL_SCALE)) * (mid - side); + + in = l; + out = FRF.ha0 * in + FRF.ha1 * FRF.History_One_In.Left + FRF.ha2 * FRF.History_Two_In.Left - FRF.hb1 * FRF.History_One_Out.Left - FRF.hb2 * FRF.History_Two_Out.Left; + FRF.History_Two_In.Left = FRF.History_One_In.Left; FRF.History_One_In.Left = in; + FRF.History_Two_Out.Left = FRF.History_One_Out.Left; FRF.History_One_Out.Left = out; + l = out; + + in = r; + out = FRF.ha0 * in + FRF.ha1 * FRF.History_One_In.Right + FRF.ha2 * FRF.History_Two_In.Right - FRF.hb1 * FRF.History_One_Out.Right - FRF.hb2 * FRF.History_Two_Out.Right; + FRF.History_Two_In.Right = FRF.History_One_In.Right; FRF.History_One_In.Right = in; + FRF.History_Two_Out.Right = FRF.History_One_Out.Right; FRF.History_One_Out.Right = out; + r = out; + + //clamp_mix(l); + //clamp_mix(r); + + SoundStream.Left = l; + SoundStream.Right = r; + + return SoundStream; +} + +StereoOut32 Apply_Dealias_Filter(StereoOut32 &SoundStream) +{ + static StereoOut32 Old = StereoOut32::Empty; + + s32 l, r; + + l = SoundStream.Left; + r = SoundStream.Right; + + l += (l - Old.Left); + r += (r - Old.Right); + + Old.Left = SoundStream.Left; + Old.Right = SoundStream.Right; + + SoundStream.Left = l; + SoundStream.Right = r; + + return SoundStream; +} + // used to throttle the output rate of cache stat reports static int p_cachestat_counter=0; @@ -780,11 +854,18 @@ __forceinline void Mix() Out.Left = MulShr32( Out.Left<<(SndOutVolumeShift+1), Cores[1].MasterVol.Left.Value ); Out.Right = MulShr32( Out.Right<<(SndOutVolumeShift+1), Cores[1].MasterVol.Right.Value ); + #ifdef DEBUG_KEYS + if(postprocess_filter_enabled) + #endif + { + Out = Apply_Dealias_Filter ( Out ); + Out = Apply_Frequency_Response_Filter ( Out ); + } + // Final Clamp! // Like any good audio system, the PS2 pumps the volume and incurs some distortion in its // output, giving us a nice thumpy sound at times. So we add 1 above (2x volume pump) and // then clamp it all here. - Out = clamp_mix( Out, SndOutVolumeShift ); } diff --git a/plugins/spu2-x/src/Mixer.h b/plugins/spu2-x/src/Mixer.h index a643de2adb..4f790166c3 100644 --- a/plugins/spu2-x/src/Mixer.h +++ b/plugins/spu2-x/src/Mixer.h @@ -78,6 +78,48 @@ struct StereoOut32 }; +struct FrequencyResponseFilter +{ + static FrequencyResponseFilter Empty; + + StereoOut32 History_One_In; + StereoOut32 History_One_Out; + StereoOut32 History_Two_In; + StereoOut32 History_Two_Out; + + s32 lx1; + s32 lx2; + s32 ly1; + s32 ly2; + + float la0, la1, la2, lb1, lb2; + float ha0, ha1, ha2, hb1, hb2; + + FrequencyResponseFilter() : + History_One_In( 0, 0 ), + History_One_Out( 0, 0 ), + History_Two_In( 0, 0 ), + History_Two_Out( 0, 0 ), + lx1 ( 0 ), + lx2 ( 0 ), + ly1 ( 0 ), + ly2 ( 0 ), + + la0 ( 1.00320890889339290000 ), + la1 ( -1.97516434134506300000 ), + la2 ( 0.97243484967313087000 ), + lb1 ( -1.97525280404731810000 ), + lb2 ( 0.97555529586426892000 ), + + ha0 ( 1.52690772687271160000 ), + ha1 ( -1.62653918974914990000 ), + ha2 ( 0.57997976029249387000 ), + hb1 ( -0.80955590379048203000 ), + hb2 ( 0.28990420120653748000 ) + { + } + +}; extern void Mix(); extern s32 clamp_mix( s32 x, u8 bitshift=0 ); diff --git a/plugins/spu2-x/src/PS2E-spu2.cpp b/plugins/spu2-x/src/PS2E-spu2.cpp index 6449bf72ab..2f88f52d92 100644 --- a/plugins/spu2-x/src/PS2E-spu2.cpp +++ b/plugins/spu2-x/src/PS2E-spu2.cpp @@ -26,8 +26,6 @@ # include "svnrev.h" #endif -// Uncomment to enable debug keys -//#define DEBUG_KEYS // PCSX2 expects ASNI, not unicode, so this MUST always be char... static char libraryName[256]; @@ -511,7 +509,7 @@ static bool numpad_plus = false, numpad_plus_old = false; #ifdef DEBUG_KEYS static u32 lastTicks; -static bool lState[5]; +static bool lState[6]; #endif EXPORT_C_(void) SPU2async(u32 cycles) @@ -530,17 +528,23 @@ EXPORT_C_(void) SPU2async(u32 cycles) #ifdef DEBUG_KEYS u32 curTicks = GetTickCount(); - if((curTicks - lastTicks) >= 100) + if((curTicks - lastTicks) >= 50) { int oldI = Interpolation; - bool cState[5]; - for(int i=0;i<5;i++) + bool cState[6]; + for(int i=0;i<6;i++) { cState[i] = !!(GetAsyncKeyState(VK_NUMPAD0+i)&0x8000); - if(cState[i] && !lState[i]) + if((cState[i] && !lState[i]) && i != 5) Interpolation = i; + if((cState[i] && !lState[i]) && i == 5) + { + postprocess_filter_enabled = !postprocess_filter_enabled; + printf("Post process filters %s \n", postprocess_filter_enabled? "enabled" : "disabled"); + } + lState[i] = cState[i]; } diff --git a/plugins/spu2-x/src/Windows/Config.cpp b/plugins/spu2-x/src/Windows/Config.cpp index 7717666b17..f169d03c0f 100644 --- a/plugins/spu2-x/src/Windows/Config.cpp +++ b/plugins/spu2-x/src/Windows/Config.cpp @@ -37,6 +37,7 @@ int Interpolation = 1; */ int ReverbBoost = 0; bool EffectsDisabled = false; +bool postprocess_filter_enabled = 1; // OUTPUT int SndOutLatencyMS = 150;