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);
|
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!
|
return 0; // technically unreachable!
|
||||||
}
|
}
|
||||||
|
|
||||||
// Noise values need to be mixed without going through interpolation, since it
|
// This is Dr. Hell's noise algorithm as implemented in pcsxr
|
||||||
// can wreak havoc on the noise (causing muffling or popping). Not that this noise
|
// Supposedly this is 100% accurate
|
||||||
// generator is accurate in its own right.. but eh, ah well :)
|
static __forceinline void UpdateNoise(V_Core& thiscore)
|
||||||
static __forceinline s32 GetNoiseValues(V_Core& thiscore, uint voiceidx)
|
|
||||||
{
|
{
|
||||||
// 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();
|
thiscore.NoiseCnt += 0x10000;
|
||||||
vc.SP-=4096;
|
thiscore.NoiseCnt -= noise_freq_add[thiscore.NoiseClk & 3];
|
||||||
}*/
|
}
|
||||||
|
|
||||||
// GetNoiseValues can't set the phase zero on us unexpectedly
|
if (thiscore.NoiseCnt >= level)
|
||||||
// like GetVoiceValues can. Better assert just in case though..
|
{
|
||||||
// pxAssume(vc.ADSR.Phase != 0);
|
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;
|
s32 Value = 0;
|
||||||
|
|
||||||
if (vc.Noise)
|
if (vc.Noise)
|
||||||
Value = GetNoiseValues(thiscore, voiceidx);
|
Value = GetNoiseValues(thiscore);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Optimization : Forceinline'd Templated Dispatch Table. Any halfwit compiler will
|
// 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)
|
StereoOut32 V_Core::Mix(const VoiceMixSet& inVoices, const StereoOut32& Input, const StereoOut32& Ext)
|
||||||
{
|
{
|
||||||
MasterVol.Update();
|
MasterVol.Update();
|
||||||
|
UpdateNoise(*this);
|
||||||
|
|
||||||
|
|
||||||
// Saturate final result to standard 16 bit range.
|
// Saturate final result to standard 16 bit range.
|
||||||
const VoiceMixSet Voices(clamp_mix(inVoices.Dry), clamp_mix(inVoices.Wet));
|
const VoiceMixSet Voices(clamp_mix(inVoices.Dry), clamp_mix(inVoices.Wet));
|
||||||
|
|
|
@ -399,7 +399,9 @@ struct V_Core
|
||||||
bool AdmaInProgress;
|
bool AdmaInProgress;
|
||||||
|
|
||||||
s8 DMABits; // DMA related?
|
s8 DMABits; // DMA related?
|
||||||
s8 NoiseClk; // Noise Clock
|
u8 NoiseClk; // Noise Clock
|
||||||
|
u32 NoiseCnt; // Noise Counter
|
||||||
|
u32 NoiseOut; // Noise Output
|
||||||
u16 AutoDMACtrl; // AutoDMA Status
|
u16 AutoDMACtrl; // AutoDMA Status
|
||||||
s32 DMAICounter; // DMA Interrupt Counter
|
s32 DMAICounter; // DMA Interrupt Counter
|
||||||
u32 LastClock; // DMA Interrupt Clock Cycle Counter
|
u32 LastClock; // DMA Interrupt Clock Cycle Counter
|
||||||
|
|
|
@ -130,6 +130,8 @@ void V_Core::Init(int index)
|
||||||
Mute = false;
|
Mute = false;
|
||||||
DMABits = 0;
|
DMABits = 0;
|
||||||
NoiseClk = 0;
|
NoiseClk = 0;
|
||||||
|
NoiseCnt = 0;
|
||||||
|
NoiseOut = 0;
|
||||||
AutoDMACtrl = 0;
|
AutoDMACtrl = 0;
|
||||||
InputDataLeft = 0;
|
InputDataLeft = 0;
|
||||||
InputPosRead = 0;
|
InputPosRead = 0;
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
// the lower 16 bit value. IF the change is breaking of all compatibility with old
|
// 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.
|
// 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
|
// 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. :)
|
// between the GS saving function and the MTGS's needs. :)
|
||||||
|
|
Loading…
Reference in New Issue