Adapted the de-alias and frequency response filters from nenolod's "UPSE", a high quality PSF player.
(http://nenolod.net/projects/upse/)
These 2 filters are present on the real SPU(2) as well and are meant to increase the audio quality
by fixing aliasing and then equalizing the final result.
It currently mostly seems to accentuate the presence and highs.

Thanks a ton for hinting at this and for letting us adapt your code for SPU2-X, nenolod! :)

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4118 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
ramapcsx2 2010-12-22 05:37:38 +00:00
parent c1811e6903
commit 57dd103e0d
8 changed files with 142 additions and 8 deletions

View File

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

View File

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

View File

@ -43,6 +43,7 @@ int Interpolation = 1;
bool EffectsDisabled = false;
int ReverbBoost = 0;
bool postprocess_filter_enabled = 1;
// OUTPUT
u32 OutputModule = 0;

View File

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

View File

@ -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 );
}

View File

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

View File

@ -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];
}

View File

@ -37,6 +37,7 @@ int Interpolation = 1;
*/
int ReverbBoost = 0;
bool EffectsDisabled = false;
bool postprocess_filter_enabled = 1;
// OUTPUT
int SndOutLatencyMS = 150;