mirror of https://github.com/PCSX2/pcsx2.git
SPU2-X:
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:
parent
c1811e6903
commit
57dd103e0d
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ int Interpolation = 1;
|
|||
|
||||
bool EffectsDisabled = false;
|
||||
int ReverbBoost = 0;
|
||||
bool postprocess_filter_enabled = 1;
|
||||
|
||||
// OUTPUT
|
||||
u32 OutputModule = 0;
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ int Interpolation = 1;
|
|||
*/
|
||||
int ReverbBoost = 0;
|
||||
bool EffectsDisabled = false;
|
||||
bool postprocess_filter_enabled = 1;
|
||||
|
||||
// OUTPUT
|
||||
int SndOutLatencyMS = 150;
|
||||
|
|
Loading…
Reference in New Issue