mirror of https://github.com/PCSX2/pcsx2.git
SPU2: Switch to a more accurate noise algorithm
This algorithm comes from pcsxr and is an implementation of Dr. Hell's research. It's supposed to be very accurate. Bumps savestate because of new SPU core struct members.
This commit is contained in:
parent
f5d89062e0
commit
6c81bb54f7
|
@ -267,18 +267,6 @@ static __forceinline void GetNextDataDummy(V_Core& thiscore, uint voiceidx)
|
|||
vc.SCurrent += 4 - (vc.SCurrent & 3);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static s32 __forceinline GetNoiseValues()
|
||||
{
|
||||
static u16 lfsr = 0xC0FEu;
|
||||
|
||||
u16 bit = lfsr ^ (lfsr << 3) ^ (lfsr << 4) ^ (lfsr << 5);
|
||||
lfsr = (lfsr << 1) | (bit >> 15);
|
||||
|
||||
return (s16)lfsr;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
|
@ -460,26 +448,48 @@ static __forceinline s32 GetVoiceValues(V_Core& thiscore, uint voiceidx)
|
|||
return 0; // technically unreachable!
|
||||
}
|
||||
|
||||
// Noise values need to be mixed without going through interpolation, since it
|
||||
// can wreak havoc on the noise (causing muffling or popping). Not that this noise
|
||||
// generator is accurate in its own right.. but eh, ah well :)
|
||||
static __forceinline s32 GetNoiseValues(V_Core& thiscore, uint voiceidx)
|
||||
// This is Dr. Hell's noise algorithm as implemented in pcsxr
|
||||
// Supposedly this is 100% accurate
|
||||
static __forceinline void UpdateNoise(V_Core& thiscore)
|
||||
{
|
||||
// V_Voice &vc(thiscore.Voices[voiceidx]);
|
||||
static const uint8_t noise_add[64] = {
|
||||
1, 0, 0, 1, 0, 1, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0,
|
||||
0, 1, 1, 0, 1, 0, 0, 1,
|
||||
0, 1, 1, 0, 1, 0, 0, 1,
|
||||
0, 1, 1, 0, 1, 0, 0, 1,
|
||||
0, 1, 1, 0, 1, 0, 0, 1};
|
||||
|
||||
s32 retval = GetNoiseValues();
|
||||
static const uint16_t noise_freq_add[5] = {
|
||||
0, 84, 140, 180, 210};
|
||||
|
||||
/*while(vc.SP>=4096)
|
||||
|
||||
u32 level = 0x8000 >> (thiscore.NoiseClk >> 2);
|
||||
level <<= 16;
|
||||
|
||||
thiscore.NoiseCnt += 0x10000;
|
||||
|
||||
thiscore.NoiseCnt += noise_freq_add[thiscore.NoiseClk & 3];
|
||||
if ((thiscore.NoiseCnt & 0xffff) >= noise_freq_add[4])
|
||||
{
|
||||
retval = GetNoiseValues();
|
||||
vc.SP-=4096;
|
||||
}*/
|
||||
thiscore.NoiseCnt += 0x10000;
|
||||
thiscore.NoiseCnt -= noise_freq_add[thiscore.NoiseClk & 3];
|
||||
}
|
||||
|
||||
// GetNoiseValues can't set the phase zero on us unexpectedly
|
||||
// like GetVoiceValues can. Better assert just in case though..
|
||||
// pxAssume(vc.ADSR.Phase != 0);
|
||||
if (thiscore.NoiseCnt >= level)
|
||||
{
|
||||
while (thiscore.NoiseCnt >= level)
|
||||
thiscore.NoiseCnt -= level;
|
||||
|
||||
return retval;
|
||||
thiscore.NoiseOut = (thiscore.NoiseOut << 1) | noise_add[(thiscore.NoiseOut >> 10) & 63];
|
||||
}
|
||||
}
|
||||
|
||||
static __forceinline s32 GetNoiseValues(V_Core& thiscore)
|
||||
{
|
||||
return (s16)thiscore.NoiseOut;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -534,7 +544,7 @@ static __forceinline StereoOut32 MixVoice(uint coreidx, uint voiceidx)
|
|||
s32 Value = 0;
|
||||
|
||||
if (vc.Noise)
|
||||
Value = GetNoiseValues(thiscore, voiceidx);
|
||||
Value = GetNoiseValues(thiscore);
|
||||
else
|
||||
{
|
||||
// Optimization : Forceinline'd Templated Dispatch Table. Any halfwit compiler will
|
||||
|
@ -641,6 +651,8 @@ static __forceinline void MixCoreVoices(VoiceMixSet& dest, const uint coreidx)
|
|||
StereoOut32 V_Core::Mix(const VoiceMixSet& inVoices, const StereoOut32& Input, const StereoOut32& Ext)
|
||||
{
|
||||
MasterVol.Update();
|
||||
UpdateNoise(*this);
|
||||
|
||||
|
||||
// Saturate final result to standard 16 bit range.
|
||||
const VoiceMixSet Voices(clamp_mix(inVoices.Dry), clamp_mix(inVoices.Wet));
|
||||
|
|
|
@ -399,7 +399,9 @@ struct V_Core
|
|||
bool AdmaInProgress;
|
||||
|
||||
s8 DMABits; // DMA related?
|
||||
s8 NoiseClk; // Noise Clock
|
||||
u8 NoiseClk; // Noise Clock
|
||||
u32 NoiseCnt; // Noise Counter
|
||||
u32 NoiseOut; // Noise Output
|
||||
u16 AutoDMACtrl; // AutoDMA Status
|
||||
s32 DMAICounter; // DMA Interrupt Counter
|
||||
u32 LastClock; // DMA Interrupt Clock Cycle Counter
|
||||
|
|
|
@ -130,6 +130,8 @@ void V_Core::Init(int index)
|
|||
Mute = false;
|
||||
DMABits = 0;
|
||||
NoiseClk = 0;
|
||||
NoiseCnt = 0;
|
||||
NoiseOut = 0;
|
||||
AutoDMACtrl = 0;
|
||||
InputDataLeft = 0;
|
||||
InputPosRead = 0;
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
// the lower 16 bit value. IF the change is breaking of all compatibility with old
|
||||
// states, increment the upper 16 bit value, and clear the lower 16 bits to 0.
|
||||
|
||||
static const u32 g_SaveVersion = (0x9A17 << 16) | 0x0000;
|
||||
static const u32 g_SaveVersion = (0x9A18 << 16) | 0x0000;
|
||||
|
||||
// this function is meant to be used in the place of GSfreeze, and provides a safe layer
|
||||
// between the GS saving function and the MTGS's needs. :)
|
||||
|
|
Loading…
Reference in New Issue