From 0a24870600738c7309d0bd64fbaf04c0f2518805 Mon Sep 17 00:00:00 2001 From: "Jake.Stine" Date: Fri, 20 Feb 2009 13:29:39 +0000 Subject: [PATCH] SPU2-X: Squashed a bug that caused lots of crackle-pops on certain audio tracks (most obvious during the KH2 intro); LoopStartA apparently should *not* be set to NextA when KeyOn is issued. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@552 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/spu2-x/src/ADSR.cpp | 25 -- plugins/spu2-x/src/Decoder.cpp | 6 +- plugins/spu2-x/src/DllInterface.cpp | 11 +- plugins/spu2-x/src/Dma.cpp | 4 +- plugins/spu2-x/src/Mixer.cpp | 330 +++++------------- plugins/spu2-x/src/ReadInput.cpp | 190 ++++++++++ plugins/spu2-x/src/RegLog.cpp | 11 +- plugins/spu2-x/src/Spu2.cpp | 7 +- plugins/spu2-x/src/Spu2.h | 5 +- plugins/spu2-x/src/Win32/RealtimeDebugger.cpp | 3 +- plugins/spu2-x/src/Win32/SndOut_XAudio2.cpp | 20 +- plugins/spu2-x/src/Win32/Spu2-X_vs2008.vcproj | 132 +++---- plugins/spu2-x/src/defs.h | 1 - 13 files changed, 378 insertions(+), 367 deletions(-) create mode 100644 plugins/spu2-x/src/ReadInput.cpp diff --git a/plugins/spu2-x/src/ADSR.cpp b/plugins/spu2-x/src/ADSR.cpp index fe4f3ae53..e9d4abaef 100644 --- a/plugins/spu2-x/src/ADSR.cpp +++ b/plugins/spu2-x/src/ADSR.cpp @@ -27,33 +27,8 @@ static const int InvExpOffsets[] = { 0,4,6,8,9,10,11,12 }; static u32 PsxRates[160]; -extern u32 core, voice; - void InitADSR() // INIT ADSR { - - /*u64 r=3; - u64 rs=1; - u64 rd=0; - - memset( PsxRates, 0, sizeof( PsxRates ) ); - - for( uint i=32; i<160; ++i ) - { - if( r < 0x3FFFFFFF ) - { - r += rs; - rd++; - if( rd == 5 ) - { - rd = 1; - rs <<= 1; - } - } - - PsxRates[i] = (u32)min( r, 0x3FFFFFFFULL ); - }*/ - for (int i=0; i<(32+128); i++) { int shift=(i-32)>>2; diff --git a/plugins/spu2-x/src/Decoder.cpp b/plugins/spu2-x/src/Decoder.cpp index b1d0142cb..a97b56119 100644 --- a/plugins/spu2-x/src/Decoder.cpp +++ b/plugins/spu2-x/src/Decoder.cpp @@ -57,8 +57,6 @@ int state=0; FILE *fSpdifDump; -extern u32 core; - union spdif_frame { // total size: 32bits struct { u32 preamble:4; //4 @@ -133,12 +131,10 @@ void spdif_update() { StereoOut32 Data; - core=0; - V_Core& thiscore( Cores[core] ); for(int i=0;i=0x800: %x value %x\n",mem,ret); - FileLog(" * SPU2: Read from reg>=0x800: %x value %x\n",mem,ret); } else { ret = *(regtable[(mem>>1)]); - - FileLog("[%10d] SPU2 read mem %x (core %d, register %x): %x\n",Cycles, mem, core, (omem & 0x7ff), ret); + //FileLog("[%10d] SPU2 read mem %x (core %d, register %x): %x\n",Cycles, mem, core, (omem & 0x7ff), ret); + SPU2writeLog( "read", rmem, ret ); } return ret; @@ -417,10 +418,14 @@ EXPORT_C_(void) SPU2write(u32 rmem, u16 value) } else { + //TimeUpdate( *cPtr ); if (rmem>>16 == 0x1f80) SPU_ps1_write(rmem,value); else + { + SPU2writeLog( "write", rmem, value ); SPU2_FastWrite( rmem, value ); + } } } diff --git a/plugins/spu2-x/src/Dma.cpp b/plugins/spu2-x/src/Dma.cpp index 0b8fedc6a..d86fde889 100644 --- a/plugins/spu2-x/src/Dma.cpp +++ b/plugins/spu2-x/src/Dma.cpp @@ -315,7 +315,7 @@ void DoDMAWrite(int core,u16 *pMem,u32 size) if( ( Cores[core].IRQA >= Cores[core].TSA ) || ( Cores[core].IRQA <= Cores[core].TDA ) ) { - Spdif.Info=4<= Cores[core].TSA ) && ( Cores[core].IRQA <= Cores[core].TDA ) ) { - Spdif.Info=4<> 0)&0xF)+16; - s32 pred1 = tbl_XA_Factor[(header>> 4)&0xF][0]; - s32 pred2 = tbl_XA_Factor[(header>> 4)&0xF][1]; + const s32 shift = ((header>> 0)&0xF)+16; + const s32 pred1 = tbl_XA_Factor[(header>> 4)&0xF][0]; + const s32 pred2 = tbl_XA_Factor[(header>> 4)&0xF][1]; const s8* blockbytes = (s8*)&block[1]; @@ -112,10 +110,10 @@ static void __forceinline XA_decode_block(s16* buffer, const s16* block, s32& pr static void __forceinline XA_decode_block_unsaturated(s16* buffer, const s16* block, s32& prev1, s32& prev2) { - const s32 header = *block; - s32 shift = ((header>> 0)&0xF)+16; - s32 pred1 = tbl_XA_Factor[(header>> 4)&0xF][0]; - s32 pred2 = tbl_XA_Factor[(header>> 4)&0xF][1]; + const u8 header = *(u8*)block; + s32 shift = (header&0xF) + 16; + s32 pred1 = tbl_XA_Factor[header>>4][0]; + s32 pred2 = tbl_XA_Factor[header>>4][1]; const s8* blockbytes = (s8*)&block[1]; @@ -126,7 +124,6 @@ static void __forceinline XA_decode_block_unsaturated(s16* buffer, const s16* bl s32 data = ((*blockbytes)<<28) & 0xF0000000; pcm = data>>shift; pcm+=((pred1*prev1)+(pred2*prev2))>>6; - // [Air] : Fast method, no saturation is performed. *(buffer++) = pcm; } @@ -134,7 +131,6 @@ static void __forceinline XA_decode_block_unsaturated(s16* buffer, const s16* bl s32 data = ((*blockbytes)<<24) & 0xF0000000; pcm2 = data>>shift; pcm2+=((pred1*pcm)+(pred2*prev1))>>6; - // [Air] : Fast method, no saturation is performed. *(buffer++) = pcm2; } @@ -177,31 +173,26 @@ int g_counter_cache_ignores = 0; #define XAFLAG_LOOP (1ul<<1) #define XAFLAG_LOOP_START (1ul<<2) -static s32 __forceinline __fastcall GetNextDataBuffered( V_Core& thiscore, V_Voice& vc ) +static __forceinline s32 __fastcall GetNextDataBuffered( V_Core& thiscore, uint voiceidx ) { - if (vc.SCurrent<28) - { - // [Air] : skip the increment? - // (witness one of the rare ideal uses of a goto statement!) - if( (vc.SCurrent&3) != 3 ) goto _skipIncrement; - } - else + V_Voice& vc( thiscore.Voices[voiceidx] ); + + if( vc.SCurrent == 28 ) { if(vc.LoopFlags & XAFLAG_LOOP_END) { - thiscore.Regs.ENDX |= (1 << voice); + thiscore.Regs.ENDX |= (1 << voiceidx); if( vc.LoopFlags & XAFLAG_LOOP ) { - vc.NextA=vc.LoopStartA; + vc.NextA = vc.LoopStartA; } else { vc.Stop(); if( IsDevBuild ) { - if(MsgVoiceOff()) ConLog(" * SPU2: Voice Off by EndPoint: %d \n", voice); - DebugCores[core].Voices[voice].lastStopReason = 1; + if(MsgVoiceOff()) ConLog(" * SPU2: Voice Off by EndPoint: %d \n", voiceidx); } } } @@ -245,6 +236,9 @@ static s32 __forceinline __fastcall GetNextDataBuffered( V_Core& thiscore, V_Voi s16* sbuffer = cacheLine.Sampledata; + //if( vc.LoopFlags & XAFLAG_LOOP ) + // vc.Prev1 = vc.Prev2 = 0; + // saturated decoder //XA_decode_block( sbuffer, memptr, vc.Prev1, vc.Prev2 ); @@ -260,11 +254,16 @@ static s32 __forceinline __fastcall GetNextDataBuffered( V_Core& thiscore, V_Voi vc.SCurrent = 0; if( (vc.LoopFlags & XAFLAG_LOOP_START) && !vc.LoopMode ) vc.LoopStartA = vc.NextA; + + goto _Increment; } - IncrementNextA( thiscore, vc ); + if( (vc.SCurrent&3) == 3 ) + { +_Increment: + IncrementNextA( thiscore, vc ); + } -_skipIncrement: return vc.SBuffer[vc.SCurrent++]; } @@ -322,25 +321,28 @@ static __forceinline StereoOut32 ApplyVolume( const StereoOut32& data, const V_V ); } -static void __forceinline UpdatePitch( V_Voice& vc ) +static void __forceinline UpdatePitch( uint coreidx, uint voiceidx ) { + V_Voice& vc( Cores[coreidx].Voices[voiceidx] ); s32 pitch; // [Air] : re-ordered comparisons: Modulated is much more likely to be zero than voice, // and so the way it was before it's have to check both voice and modulated values // most of the time. Now it'll just check Modulated and short-circuit past the voice // check (not that it amounts to much, but eh every little bit helps). - if( (vc.Modulated==0) || (voice==0) ) + if( (vc.Modulated==0) || (voiceidx==0) ) pitch = vc.Pitch; else - pitch = (vc.Pitch*(32768 + abs(Cores[core].Voices[voice-1].OutX)))>>15; + pitch = (vc.Pitch*(32768 + abs(Cores[coreidx].Voices[voiceidx-1].OutX)))>>15; vc.SP+=pitch; } -static __forceinline void CalculateADSR( V_Core& thiscore, V_Voice& vc ) +static __forceinline void CalculateADSR( V_Core& thiscore, uint voiceidx ) { + V_Voice& vc( thiscore.Voices[voiceidx] ); + if( vc.ADSR.Phase==0 ) { vc.ADSR.Value = 0; @@ -351,27 +353,28 @@ static __forceinline void CalculateADSR( V_Core& thiscore, V_Voice& vc ) { if( IsDevBuild ) { - if(MsgVoiceOff()) ConLog(" * SPU2: Voice Off by ADSR: %d \n", voice); - DebugCores[core].Voices[voice].lastStopReason = 2; + if(MsgVoiceOff()) ConLog(" * SPU2: Voice Off by ADSR: %d \n", voiceidx); } vc.Stop(); - thiscore.Regs.ENDX |= (1 << voice); + thiscore.Regs.ENDX |= (1 << voiceidx); } jASSUME( vc.ADSR.Value >= 0 ); // ADSR should never be negative... } // Returns a 16 bit result in Value. -static s32 __forceinline GetVoiceValues_Linear( V_Core& thiscore, V_Voice& vc ) +static s32 __forceinline GetVoiceValues_Linear( V_Core& thiscore, uint voiceidx ) { + V_Voice& vc( thiscore.Voices[voiceidx] ); + while( vc.SP > 0 ) { vc.PV2 = vc.PV1; - vc.PV1 = GetNextDataBuffered( thiscore, vc ); + vc.PV1 = GetNextDataBuffered( thiscore, voiceidx ); vc.SP -= 4096; } - CalculateADSR( thiscore, vc ); + CalculateADSR( thiscore, voiceidx ); // Note! It's very important that ADSR stay as accurate as possible. By the way // it is used, various sound effects can end prematurely if we truncate more than @@ -389,21 +392,23 @@ static s32 __forceinline GetVoiceValues_Linear( V_Core& thiscore, V_Voice& vc ) } // Returns a 16 bit result in Value. -static s32 __forceinline GetVoiceValues_Cubic( V_Core& thiscore, V_Voice& vc ) +static s32 __forceinline GetVoiceValues_Cubic( V_Core& thiscore, uint voiceidx ) { + V_Voice& vc( thiscore.Voices[voiceidx] ); + while( vc.SP > 0 ) { vc.PV4 = vc.PV3; vc.PV3 = vc.PV2; vc.PV2 = vc.PV1; - vc.PV1 = GetNextDataBuffered( thiscore, vc ); + vc.PV1 = GetNextDataBuffered( thiscore, voiceidx ); vc.PV1 <<= 2; vc.SPc = vc.SP&4095; // just the fractional part, please! vc.SP -= 4096; } - CalculateADSR( thiscore, vc ); + CalculateADSR( thiscore, voiceidx ); s32 z0 = vc.PV3 - vc.PV4 + vc.PV1 - vc.PV2; s32 z1 = (vc.PV4 - vc.PV3 - z0); @@ -425,8 +430,10 @@ static s32 __forceinline GetVoiceValues_Cubic( V_Core& thiscore, V_Voice& vc ) // 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 s32 __forceinline __fastcall GetNoiseValues( V_Core& thiscore, V_Voice& vc ) +static s32 __forceinline __fastcall GetNoiseValues( V_Core& thiscore, uint voiceidx ) { + V_Voice& vc( thiscore.Voices[voiceidx] ); + s32 retval = GetNoiseValues(); /*while(vc.SP>=4096) @@ -439,7 +446,7 @@ static s32 __forceinline __fastcall GetNoiseValues( V_Core& thiscore, V_Voice& v // like GetVoiceValues can. Better assert just in case though.. jASSUME( vc.ADSR.Phase != 0 ); - CalculateADSR( thiscore, vc ); + CalculateADSR( thiscore, voiceidx ); // Yup, ADSR applies even to noise sources... return ApplyVolume( retval, vc.ADSR.Value ); @@ -449,186 +456,17 @@ static s32 __forceinline __fastcall GetNoiseValues( V_Core& thiscore, V_Voice& v ///////////////////////////////////////////////////////////////////////////////////////// // // -void __fastcall ReadInput( V_Core& thiscore, StereoOut32& PData ) +static __forceinline StereoOut32 ReadInputPV( uint core ) { - if((thiscore.AutoDMACtrl&(core+1))==(core+1)) - { - s32 tl,tr; - - if((core==1)&&((PlayMode&8)==8)) - { - thiscore.InputPos&=~1; - - // CDDA mode - // Source audio data is 32 bits. - // We don't yet have the capability to handle this high res input data - // so we just downgrade it to 16 bits for now. - -#ifdef PCM24_S1_INTERLEAVE - *PData.Left=*(((s32*)(thiscore.ADMATempBuffer+(thiscore.InputPos<<1)))); - *PData.Right=*(((s32*)(thiscore.ADMATempBuffer+(thiscore.InputPos<<1)+2))); -#else - s32 *pl=(s32*)&(thiscore.ADMATempBuffer[thiscore.InputPos]); - s32 *pr=(s32*)&(thiscore.ADMATempBuffer[thiscore.InputPos+0x200]); - PData.Left = *pl; - PData.Right = *pr; -#endif - - PData.Left >>= 2; //give 30 bit data (SndOut downsamples the rest of the way) - PData.Right >>= 2; - - thiscore.InputPos+=2; - if((thiscore.InputPos==0x100)||(thiscore.InputPos>=0x200)) { - thiscore.AdmaInProgress=0; - if(thiscore.InputDataLeft>=0x200) - { - u8 k=thiscore.InputDataLeft>=thiscore.InputDataProgress; - -#ifdef PCM24_S1_INTERLEAVE - AutoDMAReadBuffer(core,1); -#else - AutoDMAReadBuffer(core,0); -#endif - thiscore.AdmaInProgress=1; - - thiscore.TSA=(core<<10)+thiscore.InputPos; - - if (thiscore.InputDataLeft<0x200) - { - FileLog("[%10d] AutoDMA%c block end.\n",Cycles, (core==0)?'4':'7'); - - if( IsDevBuild ) - { - if(thiscore.InputDataLeft>0) - { - if(MsgAutoDMA()) ConLog("WARNING: adma buffer didn't finish with a whole block!!\n"); - } - } - thiscore.InputDataLeft=0; - thiscore.DMAICounter=1; - } - } - thiscore.InputPos&=0x1ff; - } - - } - else if((core==0)&&((PlayMode&4)==4)) - { - thiscore.InputPos&=~1; - - s32 *pl=(s32*)&(thiscore.ADMATempBuffer[thiscore.InputPos]); - s32 *pr=(s32*)&(thiscore.ADMATempBuffer[thiscore.InputPos+0x200]); - PData.Left = *pl; - PData.Right = *pr; - - thiscore.InputPos+=2; - if(thiscore.InputPos>=0x200) { - thiscore.AdmaInProgress=0; - if(thiscore.InputDataLeft>=0x200) - { - u8 k=thiscore.InputDataLeft>=thiscore.InputDataProgress; - - AutoDMAReadBuffer(core,0); - - thiscore.AdmaInProgress=1; - - thiscore.TSA=(core<<10)+thiscore.InputPos; - - if (thiscore.InputDataLeft<0x200) - { - FileLog("[%10d] Spdif AutoDMA%c block end.\n",Cycles, (core==0)?'4':'7'); - - if( IsDevBuild ) - { - if(thiscore.InputDataLeft>0) - { - if(MsgAutoDMA()) ConLog("WARNING: adma buffer didn't finish with a whole block!!\n"); - } - } - thiscore.InputDataLeft=0; - thiscore.DMAICounter=1; - } - } - thiscore.InputPos&=0x1ff; - } - - } - else - { - if((core==1)&&((PlayMode&2)!=0)) - { - tl=0; - tr=0; - } - else - { - // Using the temporary buffer because this area gets overwritten by some other code. - //*PData.Left = (s32)*(s16*)(spu2mem+0x2000+(core<<10)+thiscore.InputPos); - //*PData.Right = (s32)*(s16*)(spu2mem+0x2200+(core<<10)+thiscore.InputPos); - - tl = (s32)thiscore.ADMATempBuffer[thiscore.InputPos]; - tr = (s32)thiscore.ADMATempBuffer[thiscore.InputPos+0x200]; - - } - - PData.Left = tl; - PData.Right = tr; - - thiscore.InputPos++; - if((thiscore.InputPos==0x100)||(thiscore.InputPos>=0x200)) { - thiscore.AdmaInProgress=0; - if(thiscore.InputDataLeft>=0x200) - { - u8 k=thiscore.InputDataLeft>=thiscore.InputDataProgress; - - AutoDMAReadBuffer(core,0); - - thiscore.AdmaInProgress=1; - - thiscore.TSA=(core<<10)+thiscore.InputPos; - - if (thiscore.InputDataLeft<0x200) - { - thiscore.AutoDMACtrl |= ~3; - - if( IsDevBuild ) - { - FileLog("[%10d] AutoDMA%c block end.\n",Cycles, (core==0)?'4':'7'); - if(thiscore.InputDataLeft>0) - { - if(MsgAutoDMA()) ConLog("WARNING: adma buffer didn't finish with a whole block!!\n"); - } - } - - thiscore.InputDataLeft = 0; - thiscore.DMAICounter = 1; - } - } - thiscore.InputPos&=0x1ff; - } - } - } - else - { - PData.Left = 0; - PData.Right = 0; - } -} - -///////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////// -// // - -static __forceinline StereoOut32 ReadInputPV( V_Core& thiscore ) -{ - u32 pitch=AutoDMAPlayRate[core]; + V_Core& thiscore( Cores[core] ); + u32 pitch = AutoDMAPlayRate[core]; if(pitch==0) pitch=48000; thiscore.ADMAPV += pitch; while(thiscore.ADMAPV>=48000) { - ReadInput( thiscore, thiscore.ADMAP ); + ReadInput( core, thiscore.ADMAP ); thiscore.ADMAPV -= 48000; } @@ -653,8 +491,11 @@ static __forceinline void spu2M_WriteFast( u32 addr, s16 value ) } -static __forceinline StereoOut32 MixVoice( V_Core& thiscore, V_Voice& vc ) +static __forceinline StereoOut32 MixVoice( uint coreidx, uint voiceidx ) { + V_Core& thiscore( Cores[coreidx] ); + V_Voice& vc( thiscore.Voices[voiceidx] ); + // Most games don't use much volume slide effects. So only call the UpdateVolume // methods when needed by checking the flag outside the method here... @@ -666,30 +507,30 @@ static __forceinline StereoOut32 MixVoice( V_Core& thiscore, V_Voice& vc ) if( vc.ADSR.Phase > 0 ) { - UpdatePitch( vc ); + UpdatePitch( coreidx, voiceidx ); s32 Value; if( vc.Noise ) - Value = GetNoiseValues( thiscore, vc ); + Value = GetNoiseValues( thiscore, voiceidx ); else { if( Interpolation == 2 ) - Value = GetVoiceValues_Cubic( thiscore, vc ); + Value = GetVoiceValues_Cubic( thiscore, voiceidx ); else - Value = GetVoiceValues_Linear( thiscore, vc ); + Value = GetVoiceValues_Linear( thiscore, voiceidx ); } // Note: All values recorded into OutX (may be used for modulation later) vc.OutX = Value; if( IsDevBuild ) - DebugCores[core].Voices[voice].displayPeak = max(DebugCores[core].Voices[voice].displayPeak,abs(vc.OutX)); + DebugCores[coreidx].Voices[voiceidx].displayPeak = max(DebugCores[coreidx].Voices[voiceidx].displayPeak,abs(vc.OutX)); // Write-back of raw voice data (post ADSR applied) - if (voice==1) spu2M_WriteFast( 0x400 + (core<<12) + OutPos, Value ); - else if (voice==3) spu2M_WriteFast( 0x600 + (core<<12) + OutPos, Value ); + if (voiceidx==1) spu2M_WriteFast( 0x400 + (coreidx<<12) + OutPos, Value ); + else if (voiceidx==3) spu2M_WriteFast( 0x600 + (coreidx<<12) + OutPos, Value ); return ApplyVolume( StereoOut32( Value, Value ), vc.Volume ); } @@ -697,28 +538,28 @@ static __forceinline StereoOut32 MixVoice( V_Core& thiscore, V_Voice& vc ) { // Write-back of raw voice data (some zeros since the voice is "dead") - if (voice==1) spu2M_WriteFast( 0x400 + (core<<12) + OutPos, 0 ); - else if (voice==3) spu2M_WriteFast( 0x600 + (core<<12) + OutPos, 0 ); + if (voiceidx==1) spu2M_WriteFast( 0x400 + (coreidx<<12) + OutPos, 0 ); + else if (voiceidx==3) spu2M_WriteFast( 0x600 + (coreidx<<12) + OutPos, 0 ); return StereoOut32( 0, 0 ); } } -static StereoOut32 __fastcall MixCore( const StereoOut32& Input, const StereoOut32& Ext ) +static StereoOut32 __fastcall MixCore( uint coreidx, const StereoOut32& Input, const StereoOut32& Ext ) { - V_Core& thiscore( Cores[core] ); + V_Core& thiscore( Cores[coreidx] ); thiscore.MasterVol.Update(); StereoOut32 Dry(0,0), Wet(0,0); - for( voice=0; voice<24; ++voice ) + for( uint voiceidx=0; voiceidx<24; ++voiceidx ) { - V_Voice& vc( thiscore.Voices[voice] ); - StereoOut32 VVal( MixVoice( thiscore, vc ) ); + StereoOut32 VVal( MixVoice( coreidx, voiceidx ) ); // Note: Results from MixVoice are ranged at 16 bits. + V_Voice& vc( thiscore.Voices[voiceidx] ); Dry.Left += VVal.Left & vc.DryL; Dry.Right += VVal.Right & vc.DryR; Wet.Left += VVal.Left & vc.WetL; @@ -730,15 +571,15 @@ static StereoOut32 __fastcall MixCore( const StereoOut32& Input, const StereoOut clamp_mix( Wet ); // Write Mixed results To Output Area - spu2M_WriteFast( 0x1000 + (core<<12) + OutPos, Dry.Left ); - spu2M_WriteFast( 0x1200 + (core<<12) + OutPos, Dry.Right ); - spu2M_WriteFast( 0x1400 + (core<<12) + OutPos, Wet.Left ); - spu2M_WriteFast( 0x1600 + (core<<12) + OutPos, Wet.Right ); + spu2M_WriteFast( 0x1000 + (coreidx<<12) + OutPos, Dry.Left ); + spu2M_WriteFast( 0x1200 + (coreidx<<12) + OutPos, Dry.Right ); + spu2M_WriteFast( 0x1400 + (coreidx<<12) + OutPos, Wet.Left ); + spu2M_WriteFast( 0x1600 + (coreidx<<12) + OutPos, Wet.Right ); // Write mixed results to logfile (if enabled) - WaveDump::WriteCore( core, CoreSrc_DryVoiceMix, Dry ); - WaveDump::WriteCore( core, CoreSrc_WetVoiceMix, Wet ); + WaveDump::WriteCore( coreidx, CoreSrc_DryVoiceMix, Dry ); + WaveDump::WriteCore( coreidx, CoreSrc_WetVoiceMix, Wet ); // Mix in the Input data @@ -773,7 +614,7 @@ static StereoOut32 __fastcall MixCore( const StereoOut32& Input, const StereoOut TW.Left += Ext.Left & thiscore.ExtWetL; TW.Right += Ext.Right & thiscore.ExtWetR; - WaveDump::WriteCore( core, CoreSrc_PreReverb, TW ); + WaveDump::WriteCore( coreidx, CoreSrc_PreReverb, TW ); StereoOut32 RV( DoReverb( thiscore, TW ) ); @@ -785,15 +626,15 @@ static StereoOut32 __fastcall MixCore( const StereoOut32& Input, const StereoOut RV.Left *= 2; RV.Right *= 2; - WaveDump::WriteCore( core, CoreSrc_PostReverb, RV ); + WaveDump::WriteCore( coreidx, CoreSrc_PostReverb, RV ); // Mix Dry+Wet return StereoOut32( TD + ApplyVolume( RV, thiscore.FxVol ) ); } else { - WaveDump::WriteCore( core, CoreSrc_PreReverb, 0, 0 ); - WaveDump::WriteCore( core, CoreSrc_PostReverb, 0, 0 ); + WaveDump::WriteCore( coreidx, CoreSrc_PreReverb, 0, 0 ); + WaveDump::WriteCore( coreidx, CoreSrc_PostReverb, 0, 0 ); } } return TD; @@ -805,13 +646,11 @@ static int p_cachestat_counter=0; __forceinline void Mix() { // **** CORE ZERO **** - core = 0; - // Note: Playmode 4 is SPDIF, which overrides other inputs. - StereoOut32 Ext( (PlayMode&4) ? StereoOut32::Empty : ReadInputPV( Cores[0] ) ); + StereoOut32 Ext( (PlayMode&4) ? StereoOut32::Empty : ReadInputPV( 0 ) ); WaveDump::WriteCore( 0, CoreSrc_Input, Ext ); - Ext = MixCore( Ext, StereoOut32::Empty ); + Ext = MixCore( 0, Ext, StereoOut32::Empty ); if( (PlayMode & 4) || (Cores[0].Mute!=0) ) Ext = StereoOut32( 0, 0 ); @@ -829,19 +668,18 @@ __forceinline void Mix() // **** CORE ONE **** - core = 1; - StereoOut32 Out( (PlayMode&8) ? StereoOut32::Empty : ReadInputPV( Cores[1] ) ); + StereoOut32 Out( (PlayMode&8) ? StereoOut32::Empty : ReadInputPV( 1 ) ); WaveDump::WriteCore( 1, CoreSrc_Input, Out ); ApplyVolume( Ext, Cores[1].ExtVol ); - Out = MixCore( Out, Ext ); + Out = MixCore( 1, Out, Ext ); if( PlayMode & 8 ) { // Experimental CDDA support // The CDDA overrides all other mixer output. It's a direct feed! - ReadInput( Cores[1], Out ); + ReadInput( 1, Out ); //WaveLog::WriteCore( 1, "CDDA-32", OutL, OutR ); } else diff --git a/plugins/spu2-x/src/ReadInput.cpp b/plugins/spu2-x/src/ReadInput.cpp new file mode 100644 index 000000000..2a5eb2a18 --- /dev/null +++ b/plugins/spu2-x/src/ReadInput.cpp @@ -0,0 +1,190 @@ +/* SPU2-X, A plugin for Emulating the Sound Processing Unit of the Playstation 2 +* Developed and maintained by the Pcsx2 Development Team. +* +* Original portions from SPU2ghz are (c) 2008 by David Quintana [gigaherz] +* +* This library is free software; you can redistribute it and/or modify it under +* the terms of the GNU Lesser General Public License as published by the Free +* Software Foundation; either version 2.1 of the the License, or (at your +* option) any later version. +* +* This library is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License +* for more details. +* +* You should have received a copy of the GNU Lesser General Public License along +* with this library; if not, write to the Free Software Foundation, Inc., 59 +* Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + +#include "spu2.h" + +void __fastcall ReadInput( uint core, StereoOut32& PData ) +{ + V_Core& thiscore( Cores[core] ); + + if((thiscore.AutoDMACtrl&(core+1))==(core+1)) + { + s32 tl,tr; + + if((core==1)&&((PlayMode&8)==8)) + { + thiscore.InputPos&=~1; + + // CDDA mode + // Source audio data is 32 bits. + // We don't yet have the capability to handle this high res input data + // so we just downgrade it to 16 bits for now. + +#ifdef PCM24_S1_INTERLEAVE + *PData.Left=*(((s32*)(thiscore.ADMATempBuffer+(thiscore.InputPos<<1)))); + *PData.Right=*(((s32*)(thiscore.ADMATempBuffer+(thiscore.InputPos<<1)+2))); +#else + s32 *pl=(s32*)&(thiscore.ADMATempBuffer[thiscore.InputPos]); + s32 *pr=(s32*)&(thiscore.ADMATempBuffer[thiscore.InputPos+0x200]); + PData.Left = *pl; + PData.Right = *pr; +#endif + + PData.Left >>= 2; //give 30 bit data (SndOut downsamples the rest of the way) + PData.Right >>= 2; + + thiscore.InputPos+=2; + if((thiscore.InputPos==0x100)||(thiscore.InputPos>=0x200)) { + thiscore.AdmaInProgress=0; + if(thiscore.InputDataLeft>=0x200) + { + u8 k=thiscore.InputDataLeft>=thiscore.InputDataProgress; + +#ifdef PCM24_S1_INTERLEAVE + AutoDMAReadBuffer(core,1); +#else + AutoDMAReadBuffer(core,0); +#endif + thiscore.AdmaInProgress=1; + + thiscore.TSA=(core<<10)+thiscore.InputPos; + + if (thiscore.InputDataLeft<0x200) + { + FileLog("[%10d] AutoDMA%c block end.\n",Cycles, (core==0)?'4':'7'); + + if( IsDevBuild ) + { + if(thiscore.InputDataLeft>0) + { + if(MsgAutoDMA()) ConLog("WARNING: adma buffer didn't finish with a whole block!!\n"); + } + } + thiscore.InputDataLeft=0; + thiscore.DMAICounter=1; + } + } + thiscore.InputPos&=0x1ff; + } + + } + else if((core==0)&&((PlayMode&4)==4)) + { + thiscore.InputPos&=~1; + + s32 *pl=(s32*)&(thiscore.ADMATempBuffer[thiscore.InputPos]); + s32 *pr=(s32*)&(thiscore.ADMATempBuffer[thiscore.InputPos+0x200]); + PData.Left = *pl; + PData.Right = *pr; + + thiscore.InputPos+=2; + if(thiscore.InputPos>=0x200) { + thiscore.AdmaInProgress=0; + if(thiscore.InputDataLeft>=0x200) + { + u8 k=thiscore.InputDataLeft>=thiscore.InputDataProgress; + + AutoDMAReadBuffer(core,0); + + thiscore.AdmaInProgress=1; + + thiscore.TSA=(core<<10)+thiscore.InputPos; + + if (thiscore.InputDataLeft<0x200) + { + FileLog("[%10d] Spdif AutoDMA%c block end.\n",Cycles, (core==0)?'4':'7'); + + if( IsDevBuild ) + { + if(thiscore.InputDataLeft>0) + { + if(MsgAutoDMA()) ConLog("WARNING: adma buffer didn't finish with a whole block!!\n"); + } + } + thiscore.InputDataLeft=0; + thiscore.DMAICounter=1; + } + } + thiscore.InputPos&=0x1ff; + } + + } + else + { + if((core==1)&&((PlayMode&2)!=0)) + { + tl=0; + tr=0; + } + else + { + // Using the temporary buffer because this area gets overwritten by some other code. + //*PData.Left = (s32)*(s16*)(spu2mem+0x2000+(core<<10)+thiscore.InputPos); + //*PData.Right = (s32)*(s16*)(spu2mem+0x2200+(core<<10)+thiscore.InputPos); + + tl = (s32)thiscore.ADMATempBuffer[thiscore.InputPos]; + tr = (s32)thiscore.ADMATempBuffer[thiscore.InputPos+0x200]; + + } + + PData.Left = tl; + PData.Right = tr; + + thiscore.InputPos++; + if((thiscore.InputPos==0x100)||(thiscore.InputPos>=0x200)) { + thiscore.AdmaInProgress=0; + if(thiscore.InputDataLeft>=0x200) + { + u8 k=thiscore.InputDataLeft>=thiscore.InputDataProgress; + + AutoDMAReadBuffer(core,0); + + thiscore.AdmaInProgress=1; + + thiscore.TSA=(core<<10)+thiscore.InputPos; + + if (thiscore.InputDataLeft<0x200) + { + thiscore.AutoDMACtrl |= ~3; + + if( IsDevBuild ) + { + FileLog("[%10d] AutoDMA%c block end.\n",Cycles, (core==0)?'4':'7'); + if(thiscore.InputDataLeft>0) + { + if(MsgAutoDMA()) ConLog("WARNING: adma buffer didn't finish with a whole block!!\n"); + } + } + + thiscore.InputDataLeft = 0; + thiscore.DMAICounter = 1; + } + } + thiscore.InputPos&=0x1ff; + } + } + } + else + { + PData.Left = 0; + PData.Right = 0; + } +} diff --git a/plugins/spu2-x/src/RegLog.cpp b/plugins/spu2-x/src/RegLog.cpp index 2e1b450d8..e300d935b 100644 --- a/plugins/spu2-x/src/RegLog.cpp +++ b/plugins/spu2-x/src/RegLog.cpp @@ -22,13 +22,16 @@ const char *ParamNames[8]={"VOLL","VOLR","PITCH","ADSR1","ADSR2","ENVX","VOLXL","VOLXR"}; const char *AddressNames[6]={"SSAH","SSAL","LSAH","LSAL","NAXH","NAXL"}; -__forceinline void RegLog(int level, char *RName,u32 mem,u32 core,u16 value) +__forceinline void _RegLog_( const char* action, int level, char *RName, u32 mem, u32 core, u16 value ) { if( level > 1 ) - FileLog("[%10d] SPU2 write mem %08x (core %d, register %s) value %04x\n",Cycles,mem,core,RName,value); + FileLog("[%10d] SPU2 %s mem %08x (core %d, register %s) value %04x\n", + Cycles, action, mem, core, RName, value); } -void SPU2writeLog(u32 rmem, u16 value) +#define RegLog( lev, rname, mem, core, val ) _RegLog_( action, lev, rname, mem, core, val ) + +void SPU2writeLog( const char* action, u32 rmem, u16 value ) { if( !IsDevBuild ) return; @@ -198,7 +201,7 @@ void SPU2writeLog(u32 rmem, u16 value) break; case REG_S_ADMAS: RegLog(3,"ADMAS",rmem,core,value); - ConLog(" * SPU2: Core %d AutoDMAControl set to %d\n",core,value); + //ConLog(" * SPU2: Core %d AutoDMAControl set to %d\n",core,value); break; case REG_P_STATX: RegLog(3,"STATX",rmem,core,value); diff --git a/plugins/spu2-x/src/Spu2.cpp b/plugins/spu2-x/src/Spu2.cpp index 77a066cb8..2c716c73d 100644 --- a/plugins/spu2-x/src/Spu2.cpp +++ b/plugins/spu2-x/src/Spu2.cpp @@ -285,7 +285,8 @@ void V_Voice::Start() SCurrent = 28; LoopMode = 0; LoopFlags = 0; - LoopStartA = StartA; + // Setting the loopstart to NextA breaks Squaresoft games (KH2 intro gets crackly) + //LoopStartA = StartA; NextA = StartA; Prev1 = 0; Prev2 = 0; @@ -743,8 +744,6 @@ __forceinline void SPU2_FastWrite( u32 rmem, u16 value ) omem=mem=rmem & 0x7FF; //FFFF; if (mem & 0x400) { omem^=0x400; core=1; } - SPU2writeLog(mem,value); - if (omem < 0x0180) // Voice Params { const u32 voice = (omem & 0x1F0) >> 4; @@ -881,7 +880,7 @@ __forceinline void SPU2_FastWrite( u32 rmem, u16 value ) } thiscore.AttrBit0 =(value>> 0) & 0x01; //1 bit - thiscore.DMABits =(value>> 1) & 0x07; //3 bits + thiscore.DMABits =(value>> 1) & 0x07; //3 bits thiscore.AttrBit4 =(value>> 4) & 0x01; //1 bit thiscore.AttrBit5 =(value>> 5) & 0x01; //1 bit thiscore.IRQEnable =(value>> 6) & 0x01; //1 bit diff --git a/plugins/spu2-x/src/Spu2.h b/plugins/spu2-x/src/Spu2.h index 8b21f6a9e..7834fd4a8 100644 --- a/plugins/spu2-x/src/Spu2.h +++ b/plugins/spu2-x/src/Spu2.h @@ -164,8 +164,7 @@ extern u32* cPtr; extern bool hasPtr; extern bool resetClock; -extern void RegLog(int level, char *RName,u32 mem,u32 core,u16 value); -extern void SPU2writeLog(u32 rmem, u16 value); +extern void SPU2writeLog( const char* action, u32 rmem, u16 value ); extern void __fastcall TimeUpdate(u32 cClocks); extern u16 SPU_ps1_read(u32 mem); @@ -189,7 +188,7 @@ extern void LowPassFilterInit(); extern void InitADSR(); extern void CalculateADSR( V_Voice& vc ); -extern void __fastcall ReadInput( V_Core& thiscore, StereoOut32& PData ); +extern void __fastcall ReadInput( uint core, StereoOut32& PData ); ////////////////////////////// diff --git a/plugins/spu2-x/src/Win32/RealtimeDebugger.cpp b/plugins/spu2-x/src/Win32/RealtimeDebugger.cpp index d3243bd71..e00897fae 100644 --- a/plugins/spu2-x/src/Win32/RealtimeDebugger.cpp +++ b/plugins/spu2-x/src/Win32/RealtimeDebugger.cpp @@ -124,6 +124,7 @@ void UpdateDebugDialog() { SetDCBrushColor(hdc,RGB( 0, 0,128)); } + /* else { if(vcd.lastStopReason==1) @@ -134,7 +135,7 @@ void UpdateDebugDialog() { SetDCBrushColor(hdc,RGB( 0,128, 0)); } - } + }*/ FillRectangle(hdc,IX,IY,252,30); diff --git a/plugins/spu2-x/src/Win32/SndOut_XAudio2.cpp b/plugins/spu2-x/src/Win32/SndOut_XAudio2.cpp index bb3759be3..f23b3a2b8 100644 --- a/plugins/spu2-x/src/Win32/SndOut_XAudio2.cpp +++ b/plugins/spu2-x/src/Win32/SndOut_XAudio2.cpp @@ -58,14 +58,6 @@ private: virtual ~BaseStreamingVoice() { - IXAudio2SourceVoice* killMe = pSourceVoice; - pSourceVoice = NULL; - killMe->FlushSourceBuffers(); - EnterCriticalSection( &cs ); - killMe->DestroyVoice(); - SAFE_DELETE_ARRAY( qbuffer ); - LeaveCriticalSection( &cs ); - DeleteCriticalSection( &cs ); } BaseStreamingVoice( uint numChannels ) : @@ -149,7 +141,17 @@ private: { } - virtual ~StreamingVoice() {} + virtual ~StreamingVoice() + { + IXAudio2SourceVoice* killMe = pSourceVoice; + pSourceVoice = NULL; + killMe->FlushSourceBuffers(); + EnterCriticalSection( &cs ); + killMe->DestroyVoice(); + SAFE_DELETE_ARRAY( qbuffer ); + LeaveCriticalSection( &cs ); + DeleteCriticalSection( &cs ); + } void Init( IXAudio2* pXAudio2 ) { diff --git a/plugins/spu2-x/src/Win32/Spu2-X_vs2008.vcproj b/plugins/spu2-x/src/Win32/Spu2-X_vs2008.vcproj index 6cbd31dbf..e214e9c59 100644 --- a/plugins/spu2-x/src/Win32/Spu2-X_vs2008.vcproj +++ b/plugins/spu2-x/src/Win32/Spu2-X_vs2008.vcproj @@ -495,6 +495,10 @@ RelativePath=".\RealtimeDebugger.cpp" > + + @@ -679,8 +683,12 @@ + + @@ -728,65 +736,6 @@ RelativePath="dma.h" > - - - - - - - - - - - - - - - - - - - - - - @@ -799,10 +748,6 @@ RelativePath="..\RegTable.h" > - - @@ -849,6 +794,65 @@ RelativePath="..\Spu2.h" > + + + + + + + + + + + + + + + + + + + + + +