From 18566548f69ac0d043354819957754ed4bbf553e Mon Sep 17 00:00:00 2001 From: "Jake.Stine" Date: Mon, 16 Feb 2009 22:14:17 +0000 Subject: [PATCH] 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 --- plugins/spu2-x/src/ADSR.cpp | 52 ++++++++++++++++++--------- plugins/spu2-x/src/Mixer.cpp | 12 +++---- plugins/spu2-x/src/Spu2.cpp | 70 ++++++++++++++++++++---------------- 3 files changed, 82 insertions(+), 52 deletions(-) diff --git a/plugins/spu2-x/src/ADSR.cpp b/plugins/spu2-x/src/ADSR.cpp index ec48228fad..a3aa1557a8 100644 --- a/plugins/spu2-x/src/ADSR.cpp +++ b/plugins/spu2-x/src/ADSR.cpp @@ -26,9 +26,36 @@ static const s32 ADSR_MAX_VOL = 0x7fffffff; static const int InvExpOffsets[] = { 0,4,6,8,9,10,11,12 }; static u32 PsxRates[160]; + +extern u32 core, voice; + 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; s64 rate=(i&3)+4; @@ -38,7 +65,7 @@ void InitADSR() // INIT ADSR rate <<= shift; PsxRates[i] = (int)min( rate, 0x3fffffffLL ); - } + }*/ } #define VOL(x) (((s32)x)) //24.8 volume @@ -77,9 +104,8 @@ bool V_ADSR::Calculate() if (AttackMode && (Value>=0x60000000)) Value += PsxRates[(AttackRate^0x7f)-0x18+32]; - else //if( AttackRate < 0x7f ) - Value+=PsxRates[(AttackRate^0x7f)-0x10+32]; - //Value += GetLinearSrAr( AttackRate ); + else + Value += PsxRates[(AttackRate^0x7f)-0x10+32]; if( Value < 0 ) { @@ -92,7 +118,7 @@ bool V_ADSR::Calculate() case 2: // decay { 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. @@ -117,13 +143,10 @@ bool V_ADSR::Calculate() if (SustainMode&4) // exponential { u32 off = InvExpOffsets[(Value>>28)&7]; - Value-=PsxRates[(SustainRate^0x7f)-0x1b+off+32]; + Value -= PsxRates[(SustainRate^0x7f)-0x1b+off+32]; } else // linear - { - Value-=PsxRates[(SustainRate^0x7f)-0xf+32]; - //Value -= GetLinearSrAr( SustainRate ); - } + Value -= PsxRates[(SustainRate^0x7f)-0xf+32]; if( Value <= 0 ) { @@ -134,13 +157,10 @@ bool V_ADSR::Calculate() else // increasing { if( (SustainMode&4) && (Value>=0x60000000) ) - Value+=PsxRates[(SustainRate^0x7f)-0x18+32]; + Value += PsxRates[(SustainRate^0x7f)-0x18+32]; else - { // linear / Pseudo below 75% (they're the same) - Value+=PsxRates[(SustainRate^0x7f)-0x10+32]; - //Value += GetLinearSrAr( SustainRate ); - } + Value += PsxRates[(SustainRate^0x7f)-0x10+32]; if( Value < 0 ) { diff --git a/plugins/spu2-x/src/Mixer.cpp b/plugins/spu2-x/src/Mixer.cpp index b301d8c65d..6dadeb4cd8 100644 --- a/plugins/spu2-x/src/Mixer.cpp +++ b/plugins/spu2-x/src/Mixer.cpp @@ -132,8 +132,8 @@ static void __forceinline XA_decode_block_unsaturated(s16* buffer, const s16* bl *(buffer++) = pcm2; } - prev2=pcm; - prev1=pcm2; + prev2 = pcm; + prev1 = pcm2; } } @@ -240,7 +240,7 @@ static void __forceinline __fastcall GetNextDataBuffered( V_Core& thiscore, V_Vo s16* sbuffer = cacheLine.Sampledata; // 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) // 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 // 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; @@ -358,7 +358,7 @@ static void __forceinline GetVoiceValues_Linear(V_Core& thiscore, V_Voice& vc, s 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 { @@ -693,7 +693,7 @@ static void __fastcall MixCore(s32& OutL, s32& OutR, s32 ExtL, s32 ExtR) V_Core& thiscore( Cores[core] ); - for (voice=0;voice<24;voice++) + for( voice=0; voice<24; ++voice ) { s32 VValL,VValR; diff --git a/plugins/spu2-x/src/Spu2.cpp b/plugins/spu2-x/src/Spu2.cpp index d5763ea730..c957445be5 100644 --- a/plugins/spu2-x/src/Spu2.cpp +++ b/plugins/spu2-x/src/Spu2.cpp @@ -214,20 +214,20 @@ void V_Voice::Start() StartA=(StartA+0xFFFF8)+0x8; } - ADSR.Releasing=false; - ADSR.Value=1; - ADSR.Phase=1; - PlayCycle=Cycles; - SCurrent=28; - LoopMode=0; - LoopFlags=0; - LoopStartA=StartA; - NextA=StartA; - Prev1=0; - Prev2=0; + ADSR.Releasing = false; + ADSR.Value = 1; + ADSR.Phase = 1; + PlayCycle = Cycles; + SCurrent = 28; + LoopMode = 0; + LoopFlags = 0; + LoopStartA = StartA; + NextA = StartA; + Prev1 = 0; + Prev2 = 0; - PV1=PV2=0; - PV3=PV4=0; + PV1 = PV2 = 0; + PV3 = PV4 = 0; } else { @@ -244,8 +244,8 @@ void V_Voice::Stop() static const int TickInterval = 768; static const int SanityInterval = 4800; -u32 TicksCore=0; -u32 TicksThread=0; +u32 TicksCore = 0; +u32 TicksThread = 0; void __fastcall TimeUpdate(u32 cClocks) { @@ -395,30 +395,40 @@ void SPU_ps1_write(u32 mem, u16 value) case 0: //VOLL (Volume L) Cores[0].Voices[voice].VolumeL.Mode = 0; 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) Cores[0].Voices[voice].VolumeR.Mode = 0; Cores[0].Voices[voice].VolumeR.Value = GetVol32( value<<1 ); - Cores[0].Voices[voice].VolumeR.Reg_VOL = value; break; - case 2: Cores[0].Voices[voice].Pitch=value; break; - case 3: Cores[0].Voices[voice].StartA=(u32)value<<8; break; + Cores[0].Voices[voice].VolumeR.Reg_VOL = value; + 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) - Cores[0].Voices[voice].ADSR.AttackMode=(value & 0x8000)>>15; - Cores[0].Voices[voice].ADSR.AttackRate=(value & 0x7F00)>>8; - Cores[0].Voices[voice].ADSR.DecayRate=(value & 0xF0)>>4; - Cores[0].Voices[voice].ADSR.SustainLevel=(value & 0xF); - Cores[0].Voices[voice].ADSR.Reg_ADSR1 = value; break; + Cores[0].Voices[voice].ADSR.AttackMode = (value & 0x8000)>>15; + Cores[0].Voices[voice].ADSR.AttackRate = (value & 0x7F00)>>8; + Cores[0].Voices[voice].ADSR.DecayRate = (value & 0xF0)>>4; + Cores[0].Voices[voice].ADSR.SustainLevel = (value & 0xF); + Cores[0].Voices[voice].ADSR.Reg_ADSR1 = value; + break; + case 5: // ADSR2 (Envelope) - Cores[0].Voices[voice].ADSR.SustainMode=(value & 0xE000)>>13; - Cores[0].Voices[voice].ADSR.SustainRate=(value & 0x1FC0)>>6; - Cores[0].Voices[voice].ADSR.ReleaseMode=(value & 0x20)>>5; - Cores[0].Voices[voice].ADSR.ReleaseRate=(value & 0x1F); - Cores[0].Voices[voice].ADSR.Reg_ADSR2 = value; break; + Cores[0].Voices[voice].ADSR.SustainMode = (value & 0xE000)>>13; + Cores[0].Voices[voice].ADSR.SustainRate = (value & 0x1FC0)>>6; + Cores[0].Voices[voice].ADSR.ReleaseMode = (value & 0x20)>>5; + Cores[0].Voices[voice].ADSR.ReleaseRate = (value & 0x1F); + Cores[0].Voices[voice].ADSR.Reg_ADSR2 = value; + break; + case 6: Cores[0].Voices[voice].ADSR.Value = ((s32)value<<16) | value; ConLog( "* SPU2: Mysterious ADSR Volume Set to 0x%x", value ); 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; }