SPU2-X: Switched over to what appears to be a much better ADSR table (we'll be testing it to see what impact it has across all games).

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@512 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-02-16 22:14:17 +00:00
parent 54baa99158
commit 18566548f6
3 changed files with 82 additions and 52 deletions

View File

@ -26,9 +26,36 @@ static const s32 ADSR_MAX_VOL = 0x7fffffff;
static const int InvExpOffsets[] = { 0,4,6,8,9,10,11,12 }; static const int InvExpOffsets[] = { 0,4,6,8,9,10,11,12 };
static u32 PsxRates[160]; static u32 PsxRates[160];
extern u32 core, voice;
void InitADSR() // INIT ADSR void InitADSR() // INIT ADSR
{ {
for (int i=0; i<(32+128); i++)
int r=3;
int rs=1;
int rd=0;
memset( PsxRates, 0, sizeof( PsxRates ) );
for( int i=32; i<160; ++i )
{
if( r < 0x3FFFFFFF )
{
r += rs;
rd++;
if( rd == 5 )
{
rd = 1;
rs <<= 1;
}
}
if( r > 0x3FFFFFFF ) r = 0x3FFFFFFF;
PsxRates[i] = r;
}
/*for (int i=0; i<(32+128); i++)
{ {
int shift=(i-32)>>2; int shift=(i-32)>>2;
s64 rate=(i&3)+4; s64 rate=(i&3)+4;
@ -38,7 +65,7 @@ void InitADSR() // INIT ADSR
rate <<= shift; rate <<= shift;
PsxRates[i] = (int)min( rate, 0x3fffffffLL ); PsxRates[i] = (int)min( rate, 0x3fffffffLL );
} }*/
} }
#define VOL(x) (((s32)x)) //24.8 volume #define VOL(x) (((s32)x)) //24.8 volume
@ -77,9 +104,8 @@ bool V_ADSR::Calculate()
if (AttackMode && (Value>=0x60000000)) if (AttackMode && (Value>=0x60000000))
Value += PsxRates[(AttackRate^0x7f)-0x18+32]; Value += PsxRates[(AttackRate^0x7f)-0x18+32];
else //if( AttackRate < 0x7f ) else
Value+=PsxRates[(AttackRate^0x7f)-0x10+32]; Value += PsxRates[(AttackRate^0x7f)-0x10+32];
//Value += GetLinearSrAr( AttackRate );
if( Value < 0 ) if( Value < 0 )
{ {
@ -92,7 +118,7 @@ bool V_ADSR::Calculate()
case 2: // decay case 2: // decay
{ {
u32 off = InvExpOffsets[(Value>>28)&7]; u32 off = InvExpOffsets[(Value>>28)&7];
Value-=PsxRates[((DecayRate^0x1f)*4)-0x18+off+32]; Value -= PsxRates[((DecayRate^0x1f)*4)-0x18+off+32];
// calculate sustain level as a factor of the ADSR maximum volume. // calculate sustain level as a factor of the ADSR maximum volume.
@ -117,13 +143,10 @@ bool V_ADSR::Calculate()
if (SustainMode&4) // exponential if (SustainMode&4) // exponential
{ {
u32 off = InvExpOffsets[(Value>>28)&7]; u32 off = InvExpOffsets[(Value>>28)&7];
Value-=PsxRates[(SustainRate^0x7f)-0x1b+off+32]; Value -= PsxRates[(SustainRate^0x7f)-0x1b+off+32];
} }
else // linear else // linear
{ Value -= PsxRates[(SustainRate^0x7f)-0xf+32];
Value-=PsxRates[(SustainRate^0x7f)-0xf+32];
//Value -= GetLinearSrAr( SustainRate );
}
if( Value <= 0 ) if( Value <= 0 )
{ {
@ -134,13 +157,10 @@ bool V_ADSR::Calculate()
else // increasing else // increasing
{ {
if( (SustainMode&4) && (Value>=0x60000000) ) if( (SustainMode&4) && (Value>=0x60000000) )
Value+=PsxRates[(SustainRate^0x7f)-0x18+32]; Value += PsxRates[(SustainRate^0x7f)-0x18+32];
else else
{
// linear / Pseudo below 75% (they're the same) // linear / Pseudo below 75% (they're the same)
Value+=PsxRates[(SustainRate^0x7f)-0x10+32]; Value += PsxRates[(SustainRate^0x7f)-0x10+32];
//Value += GetLinearSrAr( SustainRate );
}
if( Value < 0 ) if( Value < 0 )
{ {

View File

@ -132,8 +132,8 @@ static void __forceinline XA_decode_block_unsaturated(s16* buffer, const s16* bl
*(buffer++) = pcm2; *(buffer++) = pcm2;
} }
prev2=pcm; prev2 = pcm;
prev1=pcm2; prev1 = pcm2;
} }
} }
@ -240,7 +240,7 @@ static void __forceinline __fastcall GetNextDataBuffered( V_Core& thiscore, V_Vo
s16* sbuffer = cacheLine.Sampledata; s16* sbuffer = cacheLine.Sampledata;
// saturated decoder // saturated decoder
XA_decode_block( sbuffer, memptr, vc.Prev1, vc.Prev2 ); //XA_decode_block( sbuffer, memptr, vc.Prev1, vc.Prev2 );
// [Air]: Testing use of a new unsaturated decoder. (benchmark needed) // [Air]: Testing use of a new unsaturated decoder. (benchmark needed)
// Chances are the saturation isn't needed, but for a very few exception games. // Chances are the saturation isn't needed, but for a very few exception games.
@ -248,7 +248,7 @@ static void __forceinline __fastcall GetNextDataBuffered( V_Core& thiscore, V_Vo
// merit possible lower compatibility? Especially now that games that make // merit possible lower compatibility? Especially now that games that make
// heavy use of the SPU2 via music or sfx will mostly use the cache anyway. // heavy use of the SPU2 via music or sfx will mostly use the cache anyway.
//XA_decode_block_unsaturated( vc.SBuffer, memptr, vc.Prev1, vc.Prev2 ); XA_decode_block_unsaturated( vc.SBuffer, memptr, vc.Prev1, vc.Prev2 );
} }
vc.SCurrent = 0; vc.SCurrent = 0;
@ -358,7 +358,7 @@ static void __forceinline GetVoiceValues_Linear(V_Core& thiscore, V_Voice& vc, s
if(Interpolation==0) if(Interpolation==0)
{ {
Value = MulShr32( vc.PV1<<1, vc.ADSR.Value ); Value = ApplyVolume( vc.PV1, vc.ADSR.Value );
} }
else //if(Interpolation==1) //must be linear else //if(Interpolation==1) //must be linear
{ {
@ -693,7 +693,7 @@ static void __fastcall MixCore(s32& OutL, s32& OutR, s32 ExtL, s32 ExtR)
V_Core& thiscore( Cores[core] ); V_Core& thiscore( Cores[core] );
for (voice=0;voice<24;voice++) for( voice=0; voice<24; ++voice )
{ {
s32 VValL,VValR; s32 VValL,VValR;

View File

@ -214,20 +214,20 @@ void V_Voice::Start()
StartA=(StartA+0xFFFF8)+0x8; StartA=(StartA+0xFFFF8)+0x8;
} }
ADSR.Releasing=false; ADSR.Releasing = false;
ADSR.Value=1; ADSR.Value = 1;
ADSR.Phase=1; ADSR.Phase = 1;
PlayCycle=Cycles; PlayCycle = Cycles;
SCurrent=28; SCurrent = 28;
LoopMode=0; LoopMode = 0;
LoopFlags=0; LoopFlags = 0;
LoopStartA=StartA; LoopStartA = StartA;
NextA=StartA; NextA = StartA;
Prev1=0; Prev1 = 0;
Prev2=0; Prev2 = 0;
PV1=PV2=0; PV1 = PV2 = 0;
PV3=PV4=0; PV3 = PV4 = 0;
} }
else else
{ {
@ -244,8 +244,8 @@ void V_Voice::Stop()
static const int TickInterval = 768; static const int TickInterval = 768;
static const int SanityInterval = 4800; static const int SanityInterval = 4800;
u32 TicksCore=0; u32 TicksCore = 0;
u32 TicksThread=0; u32 TicksThread = 0;
void __fastcall TimeUpdate(u32 cClocks) void __fastcall TimeUpdate(u32 cClocks)
{ {
@ -395,30 +395,40 @@ void SPU_ps1_write(u32 mem, u16 value)
case 0: //VOLL (Volume L) case 0: //VOLL (Volume L)
Cores[0].Voices[voice].VolumeL.Mode = 0; Cores[0].Voices[voice].VolumeL.Mode = 0;
Cores[0].Voices[voice].VolumeL.Value = GetVol32( value<<1 ); Cores[0].Voices[voice].VolumeL.Value = GetVol32( value<<1 );
Cores[0].Voices[voice].VolumeL.Reg_VOL = value; break; Cores[0].Voices[voice].VolumeL.Reg_VOL = value;
break;
case 1: //VOLR (Volume R) case 1: //VOLR (Volume R)
Cores[0].Voices[voice].VolumeR.Mode = 0; Cores[0].Voices[voice].VolumeR.Mode = 0;
Cores[0].Voices[voice].VolumeR.Value = GetVol32( value<<1 ); Cores[0].Voices[voice].VolumeR.Value = GetVol32( value<<1 );
Cores[0].Voices[voice].VolumeR.Reg_VOL = value; break; Cores[0].Voices[voice].VolumeR.Reg_VOL = value;
case 2: Cores[0].Voices[voice].Pitch=value; break; break;
case 3: Cores[0].Voices[voice].StartA=(u32)value<<8; break;
case 2: Cores[0].Voices[voice].Pitch = value; break;
case 3: Cores[0].Voices[voice].StartA = (u32)value<<8; break;
case 4: // ADSR1 (Envelope) case 4: // ADSR1 (Envelope)
Cores[0].Voices[voice].ADSR.AttackMode=(value & 0x8000)>>15; Cores[0].Voices[voice].ADSR.AttackMode = (value & 0x8000)>>15;
Cores[0].Voices[voice].ADSR.AttackRate=(value & 0x7F00)>>8; Cores[0].Voices[voice].ADSR.AttackRate = (value & 0x7F00)>>8;
Cores[0].Voices[voice].ADSR.DecayRate=(value & 0xF0)>>4; Cores[0].Voices[voice].ADSR.DecayRate = (value & 0xF0)>>4;
Cores[0].Voices[voice].ADSR.SustainLevel=(value & 0xF); Cores[0].Voices[voice].ADSR.SustainLevel = (value & 0xF);
Cores[0].Voices[voice].ADSR.Reg_ADSR1 = value; break; Cores[0].Voices[voice].ADSR.Reg_ADSR1 = value;
break;
case 5: // ADSR2 (Envelope) case 5: // ADSR2 (Envelope)
Cores[0].Voices[voice].ADSR.SustainMode=(value & 0xE000)>>13; Cores[0].Voices[voice].ADSR.SustainMode = (value & 0xE000)>>13;
Cores[0].Voices[voice].ADSR.SustainRate=(value & 0x1FC0)>>6; Cores[0].Voices[voice].ADSR.SustainRate = (value & 0x1FC0)>>6;
Cores[0].Voices[voice].ADSR.ReleaseMode=(value & 0x20)>>5; Cores[0].Voices[voice].ADSR.ReleaseMode = (value & 0x20)>>5;
Cores[0].Voices[voice].ADSR.ReleaseRate=(value & 0x1F); Cores[0].Voices[voice].ADSR.ReleaseRate = (value & 0x1F);
Cores[0].Voices[voice].ADSR.Reg_ADSR2 = value; break; Cores[0].Voices[voice].ADSR.Reg_ADSR2 = value;
break;
case 6: case 6:
Cores[0].Voices[voice].ADSR.Value = ((s32)value<<16) | value; Cores[0].Voices[voice].ADSR.Value = ((s32)value<<16) | value;
ConLog( "* SPU2: Mysterious ADSR Volume Set to 0x%x", value ); ConLog( "* SPU2: Mysterious ADSR Volume Set to 0x%x", value );
break; break;
case 7: Cores[0].Voices[voice].LoopStartA=(u32)value <<8; break;
case 7: Cores[0].Voices[voice].LoopStartA = (u32)value <<8; break;
jNO_DEFAULT; jNO_DEFAULT;
} }