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
This commit is contained in:
Jake.Stine 2009-02-20 13:29:39 +00:00
parent 2c27126e92
commit 0a24870600
13 changed files with 378 additions and 367 deletions

View File

@ -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;

View File

@ -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<data_rate;i++)
{
// Right side data should be zero / ignored
ReadInput( thiscore, Data );
ReadInput( 0, Data ); // read from core 0
if(fSpdifDump)
{

View File

@ -359,6 +359,8 @@ EXPORT_C_(u16) SPU2read(u32 rmem)
// if(!replay_mode)
// s2r_readreg(Cycles,rmem);
//TimeUpdate( *cPtr );
u16 ret=0xDEAD; u32 core=0, mem=rmem&0xFFFF, omem=mem;
if (mem & 0x400) { omem^=0x400; core=1; }
@ -374,13 +376,12 @@ EXPORT_C_(u16) SPU2read(u32 rmem)
{
ret=spu2Ru16(mem);
ConLog(" * SPU2: Read from reg>=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,12 +418,16 @@ 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 );
}
}
}
// if start is 1, starts recording spu2 data, else stops
// returns a non zero value if successful

View File

@ -26,8 +26,6 @@ extern void spdif_update();
void ADMAOutLogWrite(void *lpData, u32 ulSize);
u32 core, voice;
static const s32 tbl_XA_Factor[5][2] =
{
{ 0, 0 },
@ -75,9 +73,9 @@ __forceinline void clamp_mix( StereoOut32& sample, u8 bitshift )
static void __forceinline XA_decode_block(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 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,19 +173,15 @@ 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 )
{
@ -200,8 +192,7 @@ static s32 __forceinline __fastcall GetNextDataBuffered( V_Core& thiscore, V_Voi
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;
}
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,178 +456,9 @@ static s32 __forceinline __fastcall GetNoiseValues( V_Core& thiscore, V_Voice& v
/////////////////////////////////////////////////////////////////////////////////////////
// //
void __fastcall ReadInput( V_Core& thiscore, StereoOut32& PData )
{
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 )
static __forceinline StereoOut32 ReadInputPV( uint core )
{
V_Core& thiscore( Cores[core] );
u32 pitch = AutoDMAPlayRate[core];
if(pitch==0) pitch=48000;
@ -628,7 +466,7 @@ static __forceinline StereoOut32 ReadInputPV( V_Core& thiscore )
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

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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 );
//////////////////////////////

View File

@ -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);

View File

@ -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 )
{

View File

@ -495,6 +495,10 @@
RelativePath=".\RealtimeDebugger.cpp"
>
</File>
<File
RelativePath="..\RegLog.cpp"
>
</File>
<File
RelativePath="..\spu2replay.cpp"
>
@ -679,8 +683,12 @@
</Filter>
</Filter>
<Filter
Name="dma"
Name="SPU2"
>
<File
RelativePath="..\defs.h"
>
</File>
<File
RelativePath="..\dma.cpp"
>
@ -728,65 +736,6 @@
RelativePath="dma.h"
>
</File>
</Filter>
<Filter
Name="SPU2"
>
<File
RelativePath="..\ADSR.cpp"
>
</File>
<File
RelativePath="..\defs.h"
>
</File>
<File
RelativePath="..\Mixer.cpp"
>
<FileConfiguration
Name="Devel|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
BrowseInformation="1"
CompileAs="0"
/>
</FileConfiguration>
<FileConfiguration
Name="DebugStrict|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
AssemblerOutput="4"
BrowseInformation="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
BrowseInformation="1"
CompileAs="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
BrowseInformation="1"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\RegLog.cpp"
>
</File>
<File
RelativePath="..\regs.h"
>
@ -799,10 +748,6 @@
RelativePath="..\RegTable.h"
>
</File>
<File
RelativePath="..\Reverb.cpp"
>
</File>
<File
RelativePath="..\Spu2.cpp"
>
@ -849,6 +794,65 @@
RelativePath="..\Spu2.h"
>
</File>
<Filter
Name="Mixer"
>
<File
RelativePath="..\ADSR.cpp"
>
</File>
<File
RelativePath="..\Mixer.cpp"
>
<FileConfiguration
Name="Devel|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
BrowseInformation="1"
CompileAs="0"
/>
</FileConfiguration>
<FileConfiguration
Name="DebugStrict|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
AssemblerOutput="4"
BrowseInformation="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
BrowseInformation="1"
CompileAs="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
BrowseInformation="1"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\ReadInput.cpp"
>
</File>
<File
RelativePath="..\Reverb.cpp"
>
</File>
</Filter>
</Filter>
<Filter
Name="Winamp DSP"

View File

@ -195,7 +195,6 @@ struct V_VoiceDebug
s32 PeakX;
s32 displayPeak;
s32 lastSetStartA;
s32 lastStopReason;
};
struct V_CoreDebug