diff --git a/plugins/spu2-x/src/Mixer.cpp b/plugins/spu2-x/src/Mixer.cpp index f826027609..8442c36a79 100644 --- a/plugins/spu2-x/src/Mixer.cpp +++ b/plugins/spu2-x/src/Mixer.cpp @@ -331,7 +331,7 @@ static void __forceinline UpdatePitch( uint coreidx, uint voiceidx ) if( (vc.Modulated==0) || (voiceidx==0) ) pitch = vc.Pitch; else - pitch = (vc.Pitch*(32768 + abs(Cores[coreidx].Voices[voiceidx-1].OutX)))>>15; + pitch = (vc.Pitch*(32768 + Cores[coreidx].Voices[voiceidx-1].OutX))>>15; vc.SP+=pitch; } @@ -573,18 +573,28 @@ static __forceinline StereoOut32 MixVoice( uint coreidx, uint voiceidx ) CalculateADSR( thiscore, voiceidx ); Value = MulShr32( Value, vc.ADSR.Value ); - vc.OutX = Value; // Note: All values recorded into OutX (may be used for modulation later) - - if(voiceidx<23 && Cores[coreidx].Voices[voiceidx+1].Modulated) - Value=0; + + // Store Value for eventual modulation later + // Pseudonym's Crest calculation idea. Actually calculates a crest, unlike the old code which was just peak. + u32 Amplitude = std::abs(Value); + if(Amplitude < vc.NextCrest) + { + vc.OutX = vc.NextCrest; + vc.NextCrest = 0; + } + if(Amplitude > vc.PrevAmp) + { + vc.NextCrest = Amplitude; + } + vc.PrevAmp = Amplitude; if( IsDevBuild ) - DebugCores[coreidx].Voices[voiceidx].displayPeak = std::max(DebugCores[coreidx].Voices[voiceidx].displayPeak,abs(vc.OutX)); + DebugCores[coreidx].Voices[voiceidx].displayPeak = std::max(DebugCores[coreidx].Voices[voiceidx].displayPeak,(s32)vc.OutX); // Write-back of raw voice data (post ADSR applied) - if (voiceidx==1) spu2M_WriteFast( ( (0==coreidx) ? 0x400 : 0xc00 ) + OutPos, Value ); - else if (voiceidx==3) spu2M_WriteFast( ( (0==coreidx) ? 0x600 : 0xe00 ) + OutPos, Value ); + if (voiceidx==1) spu2M_WriteFast( ( (0==coreidx) ? 0x400 : 0xc00 ) + OutPos, vc.OutX ); + else if (voiceidx==3) spu2M_WriteFast( ( (0==coreidx) ? 0x600 : 0xe00 ) + OutPos, vc.OutX ); return ApplyVolume( StereoOut32( Value, Value ), vc.Volume ); } diff --git a/plugins/spu2-x/src/defs.h b/plugins/spu2-x/src/defs.h index d5ea70eda1..5705c4e96c 100644 --- a/plugins/spu2-x/src/defs.h +++ b/plugins/spu2-x/src/defs.h @@ -143,7 +143,7 @@ struct V_Voice // Envelope V_ADSR ADSR; // Pitch (also Reg_PITCH) - s16 Pitch; + u16 Pitch; // Loop Start address (also Reg_LSAH/L) u32 LoopStartA; // Sound Start address (also Reg_SSAH/L) @@ -180,7 +180,9 @@ struct V_Voice s32 PV1; // Last outputted audio value, used for voice modulation. - s32 OutX; + u32 OutX; + u32 NextCrest; // temp value for Crest calculation + u32 PrevAmp; // temp value for Crest calculation (abs of last value) // SBuffer now points directly to an ADPCM cache entry. s16 *SBuffer; diff --git a/plugins/spu2-x/src/spu2sys.cpp b/plugins/spu2-x/src/spu2sys.cpp index be1f97c30d..70af5fadc7 100644 --- a/plugins/spu2-x/src/spu2sys.cpp +++ b/plugins/spu2-x/src/spu2sys.cpp @@ -144,7 +144,7 @@ void V_Core::Reset( int index ) VoiceGates[v].WetL = -1; VoiceGates[v].WetR = -1; - Voices[v].Volume = V_VolumeSlideLR::Max; + Voices[v].Volume = V_VolumeSlideLR(0,0); // V_VolumeSlideLR::Max; Voices[v].SCurrent = 28; Voices[v].ADSR.Value = 0; @@ -263,6 +263,8 @@ void V_Voice::Start() PV1 = PV2 = 0; PV3 = PV4 = 0; + PrevAmp = 0; + NextCrest = 0; } else { @@ -754,7 +756,7 @@ static void __fastcall RegWrite_VoiceParams( u16 value ) break; case 2: - thisvoice.Pitch = value; + thisvoice.Pitch = value & 0x3fff; break; case 3: // ADSR1 (Envelope)