mirror of https://github.com/PCSX2/pcsx2.git
SPU2-X: Resorted the mixer so that it's a little faster, and will be easier to apply some SSE2 opts in the future.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@680 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
1492382253
commit
7d00eb7ec6
|
@ -135,18 +135,18 @@ void DoFullDump()
|
||||||
|
|
||||||
fprintf(dump,"Interrupt Address: %x\n",Cores[c].IRQA);
|
fprintf(dump,"Interrupt Address: %x\n",Cores[c].IRQA);
|
||||||
fprintf(dump,"DMA Transfer Start Address: %x\n",Cores[c].TSA);
|
fprintf(dump,"DMA Transfer Start Address: %x\n",Cores[c].TSA);
|
||||||
fprintf(dump,"External Input to Direct Output (Left): %s\n",Cores[c].ExtDryL?"Yes":"No");
|
fprintf(dump,"External Input to Direct Output (Left): %s\n",Cores[c].DryGate.ExtL?"Yes":"No");
|
||||||
fprintf(dump,"External Input to Direct Output (Right): %s\n",Cores[c].ExtDryR?"Yes":"No");
|
fprintf(dump,"External Input to Direct Output (Right): %s\n",Cores[c].DryGate.ExtR?"Yes":"No");
|
||||||
fprintf(dump,"External Input to Effects (Left): %s\n",Cores[c].ExtWetL?"Yes":"No");
|
fprintf(dump,"External Input to Effects (Left): %s\n",Cores[c].WetGate.ExtL?"Yes":"No");
|
||||||
fprintf(dump,"External Input to Effects (Right): %s\n",Cores[c].ExtWetR?"Yes":"No");
|
fprintf(dump,"External Input to Effects (Right): %s\n",Cores[c].WetGate.ExtR?"Yes":"No");
|
||||||
fprintf(dump,"Sound Data Input to Direct Output (Left): %s\n",Cores[c].SndDryL?"Yes":"No");
|
fprintf(dump,"Sound Data Input to Direct Output (Left): %s\n",Cores[c].DryGate.SndL?"Yes":"No");
|
||||||
fprintf(dump,"Sound Data Input to Direct Output (Right): %s\n",Cores[c].SndDryR?"Yes":"No");
|
fprintf(dump,"Sound Data Input to Direct Output (Right): %s\n",Cores[c].DryGate.SndR?"Yes":"No");
|
||||||
fprintf(dump,"Sound Data Input to Effects (Left): %s\n",Cores[c].SndWetL?"Yes":"No");
|
fprintf(dump,"Sound Data Input to Effects (Left): %s\n",Cores[c].WetGate.SndL?"Yes":"No");
|
||||||
fprintf(dump,"Sound Data Input to Effects (Right): %s\n",Cores[c].SndWetR?"Yes":"No");
|
fprintf(dump,"Sound Data Input to Effects (Right): %s\n",Cores[c].WetGate.SndR?"Yes":"No");
|
||||||
fprintf(dump,"Voice Data Input to Direct Output (Left): %s\n",Cores[c].InpDryL?"Yes":"No");
|
fprintf(dump,"Voice Data Input to Direct Output (Left): %s\n",Cores[c].DryGate.InpL?"Yes":"No");
|
||||||
fprintf(dump,"Voice Data Input to Direct Output (Right): %s\n",Cores[c].InpDryR?"Yes":"No");
|
fprintf(dump,"Voice Data Input to Direct Output (Right): %s\n",Cores[c].DryGate.InpR?"Yes":"No");
|
||||||
fprintf(dump,"Voice Data Input to Effects (Left): %s\n",Cores[c].InpWetL?"Yes":"No");
|
fprintf(dump,"Voice Data Input to Effects (Left): %s\n",Cores[c].WetGate.InpL?"Yes":"No");
|
||||||
fprintf(dump,"Voice Data Input to Effects (Right): %s\n",Cores[c].InpWetR?"Yes":"No");
|
fprintf(dump,"Voice Data Input to Effects (Right): %s\n",Cores[c].WetGate.InpR?"Yes":"No");
|
||||||
fprintf(dump,"IRQ Enabled: %s\n",Cores[c].IRQEnable?"Yes":"No");
|
fprintf(dump,"IRQ Enabled: %s\n",Cores[c].IRQEnable?"Yes":"No");
|
||||||
fprintf(dump,"Effects Enabled: %s\n",Cores[c].FxEnable?"Yes":"No");
|
fprintf(dump,"Effects Enabled: %s\n",Cores[c].FxEnable?"Yes":"No");
|
||||||
fprintf(dump,"Mute Enabled: %s\n",Cores[c].Mute?"Yes":"No");
|
fprintf(dump,"Mute Enabled: %s\n",Cores[c].Mute?"Yes":"No");
|
||||||
|
@ -197,10 +197,10 @@ void DoFullDump()
|
||||||
fprintf(dump," - Pitch: %x\n",Cores[c].Voices[v].Pitch);
|
fprintf(dump," - Pitch: %x\n",Cores[c].Voices[v].Pitch);
|
||||||
fprintf(dump," - Modulated: %s\n",Cores[c].Voices[v].Modulated?"Yes":"No");
|
fprintf(dump," - Modulated: %s\n",Cores[c].Voices[v].Modulated?"Yes":"No");
|
||||||
fprintf(dump," - Source: %s\n",Cores[c].Voices[v].Noise?"Noise":"Wave");
|
fprintf(dump," - Source: %s\n",Cores[c].Voices[v].Noise?"Noise":"Wave");
|
||||||
fprintf(dump," - Direct Output for Left Channel: %s\n",Cores[c].Voices[v].DryL?"Yes":"No");
|
fprintf(dump," - Direct Output for Left Channel: %s\n",Cores[c].VoiceGates[v].DryL?"Yes":"No");
|
||||||
fprintf(dump," - Direct Output for Right Channel: %s\n",Cores[c].Voices[v].DryR?"Yes":"No");
|
fprintf(dump," - Direct Output for Right Channel: %s\n",Cores[c].VoiceGates[v].DryR?"Yes":"No");
|
||||||
fprintf(dump," - Effects Output for Left Channel: %s\n",Cores[c].Voices[v].WetL?"Yes":"No");
|
fprintf(dump," - Effects Output for Left Channel: %s\n",Cores[c].VoiceGates[v].WetL?"Yes":"No");
|
||||||
fprintf(dump," - Effects Output for Right Channel: %s\n",Cores[c].Voices[v].WetR?"Yes":"No");
|
fprintf(dump," - Effects Output for Right Channel: %s\n",Cores[c].VoiceGates[v].WetR?"Yes":"No");
|
||||||
fprintf(dump," - Loop Start Address: %x\n",Cores[c].Voices[v].LoopStartA);
|
fprintf(dump," - Loop Start Address: %x\n",Cores[c].Voices[v].LoopStartA);
|
||||||
fprintf(dump," - Sound Start Address: %x\n",Cores[c].Voices[v].StartA);
|
fprintf(dump," - Sound Start Address: %x\n",Cores[c].Voices[v].StartA);
|
||||||
fprintf(dump," - Next Data Address: %x\n",Cores[c].Voices[v].NextA);
|
fprintf(dump," - Next Data Address: %x\n",Cores[c].Voices[v].NextA);
|
||||||
|
|
|
@ -64,10 +64,12 @@ __forceinline s32 clamp_mix( s32 x, u8 bitshift )
|
||||||
return GetClamped( x, -0x8000<<bitshift, 0x7fff<<bitshift );
|
return GetClamped( x, -0x8000<<bitshift, 0x7fff<<bitshift );
|
||||||
}
|
}
|
||||||
|
|
||||||
__forceinline void clamp_mix( StereoOut32& sample, u8 bitshift )
|
__forceinline StereoOut32 clamp_mix( const StereoOut32& sample, u8 bitshift )
|
||||||
{
|
{
|
||||||
Clampify( sample.Left, -0x8000<<bitshift, 0x7fff<<bitshift );
|
return StereoOut32(
|
||||||
Clampify( sample.Right, -0x8000<<bitshift, 0x7fff<<bitshift );
|
GetClamped( sample.Left, -0x8000<<bitshift, 0x7fff<<bitshift ),
|
||||||
|
GetClamped( sample.Right, -0x8000<<bitshift, 0x7fff<<bitshift )
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __forceinline XA_decode_block(s16* buffer, const s16* block, s32& prev1, s32& prev2)
|
static void __forceinline XA_decode_block(s16* buffer, const s16* block, s32& prev1, s32& prev2)
|
||||||
|
@ -562,56 +564,71 @@ static __forceinline StereoOut32 MixVoice( uint coreidx, uint voiceidx )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct VoiceMixSet
|
||||||
|
{
|
||||||
|
static const VoiceMixSet Empty;
|
||||||
|
StereoOut32 Dry, Wet;
|
||||||
|
|
||||||
static StereoOut32 __fastcall MixCore( uint coreidx, const StereoOut32& Input, const StereoOut32& Ext )
|
VoiceMixSet() {}
|
||||||
|
VoiceMixSet( const StereoOut32& dry, const StereoOut32& wet ) :
|
||||||
|
Dry( dry ),
|
||||||
|
Wet( wet )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const VoiceMixSet VoiceMixSet::Empty( StereoOut32::Empty, StereoOut32::Empty );
|
||||||
|
|
||||||
|
static void __fastcall MixCoreVoices( VoiceMixSet& dest, const uint coreidx )
|
||||||
{
|
{
|
||||||
V_Core& thiscore( Cores[coreidx] );
|
V_Core& thiscore( Cores[coreidx] );
|
||||||
thiscore.MasterVol.Update();
|
|
||||||
|
|
||||||
StereoOut32 Dry(0,0), Wet(0,0);
|
for( uint voiceidx=0; voiceidx<V_Core::NumVoices; ++voiceidx )
|
||||||
|
|
||||||
for( uint voiceidx=0; voiceidx<24; ++voiceidx )
|
|
||||||
{
|
{
|
||||||
StereoOut32 VVal( MixVoice( coreidx, voiceidx ) );
|
StereoOut32 VVal( MixVoice( coreidx, voiceidx ) );
|
||||||
|
|
||||||
// Note: Results from MixVoice are ranged at 16 bits.
|
// Note: Results from MixVoice are ranged at 16 bits.
|
||||||
|
|
||||||
V_Voice& vc( thiscore.Voices[voiceidx] );
|
dest.Dry.Left += VVal.Left & thiscore.VoiceGates[voiceidx].DryL;
|
||||||
Dry.Left += VVal.Left & vc.DryL;
|
dest.Dry.Right += VVal.Right & thiscore.VoiceGates[voiceidx].DryR;
|
||||||
Dry.Right += VVal.Right & vc.DryR;
|
dest.Wet.Left += VVal.Left & thiscore.VoiceGates[voiceidx].WetL;
|
||||||
Wet.Left += VVal.Left & vc.WetL;
|
dest.Wet.Right += VVal.Right & thiscore.VoiceGates[voiceidx].WetR;
|
||||||
Wet.Right += VVal.Right & vc.WetR;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static StereoOut32 __fastcall MixCore( const uint coreidx, const VoiceMixSet& inVoices, const StereoOut32& Input, const StereoOut32& Ext )
|
||||||
|
{
|
||||||
|
V_Core& thiscore( Cores[coreidx] );
|
||||||
|
thiscore.MasterVol.Update();
|
||||||
|
|
||||||
// Saturate final result to standard 16 bit range.
|
// Saturate final result to standard 16 bit range.
|
||||||
clamp_mix( Dry );
|
const VoiceMixSet Voices( clamp_mix( inVoices.Dry ), clamp_mix( inVoices.Wet ) );
|
||||||
clamp_mix( Wet );
|
|
||||||
|
|
||||||
// Write Mixed results To Output Area
|
// Write Mixed results To Output Area
|
||||||
spu2M_WriteFast( 0x1000 + (coreidx<<12) + OutPos, Dry.Left );
|
spu2M_WriteFast( 0x1000 + (coreidx<<12) + OutPos, Voices.Dry.Left );
|
||||||
spu2M_WriteFast( 0x1200 + (coreidx<<12) + OutPos, Dry.Right );
|
spu2M_WriteFast( 0x1200 + (coreidx<<12) + OutPos, Voices.Dry.Right );
|
||||||
spu2M_WriteFast( 0x1400 + (coreidx<<12) + OutPos, Wet.Left );
|
spu2M_WriteFast( 0x1400 + (coreidx<<12) + OutPos, Voices.Wet.Left );
|
||||||
spu2M_WriteFast( 0x1600 + (coreidx<<12) + OutPos, Wet.Right );
|
spu2M_WriteFast( 0x1600 + (coreidx<<12) + OutPos, Voices.Wet.Right );
|
||||||
|
|
||||||
// Write mixed results to logfile (if enabled)
|
// Write mixed results to logfile (if enabled)
|
||||||
|
|
||||||
WaveDump::WriteCore( coreidx, CoreSrc_DryVoiceMix, Dry );
|
WaveDump::WriteCore( coreidx, CoreSrc_DryVoiceMix, Voices.Dry );
|
||||||
WaveDump::WriteCore( coreidx, CoreSrc_WetVoiceMix, Wet );
|
WaveDump::WriteCore( coreidx, CoreSrc_WetVoiceMix, Voices.Wet );
|
||||||
|
|
||||||
// Mix in the Input data
|
// Mix in the Input data
|
||||||
|
|
||||||
StereoOut32 TD(
|
StereoOut32 TD(
|
||||||
Input.Left & thiscore.InpDryL,
|
Input.Left & thiscore.DryGate.InpL,
|
||||||
Input.Right & thiscore.InpDryR
|
Input.Right & thiscore.DryGate.InpR
|
||||||
);
|
);
|
||||||
|
|
||||||
// Mix in the Voice data
|
// Mix in the Voice data
|
||||||
TD.Left += Dry.Left & thiscore.SndDryL;
|
TD.Left += Voices.Dry.Left & thiscore.DryGate.SndL;
|
||||||
TD.Right += Dry.Right & thiscore.SndDryR;
|
TD.Right += Voices.Dry.Right & thiscore.DryGate.SndR;
|
||||||
|
|
||||||
// Mix in the External (nothing/core0) data
|
// Mix in the External (nothing/core0) data
|
||||||
TD.Left += Ext.Left & thiscore.ExtDryL;
|
TD.Left += Ext.Left & thiscore.DryGate.ExtL;
|
||||||
TD.Right += Ext.Right & thiscore.ExtDryR;
|
TD.Right += Ext.Right & thiscore.DryGate.ExtR;
|
||||||
|
|
||||||
if( !EffectsDisabled )
|
if( !EffectsDisabled )
|
||||||
{
|
{
|
||||||
|
@ -622,14 +639,14 @@ static StereoOut32 __fastcall MixCore( uint coreidx, const StereoOut32& Input, c
|
||||||
{
|
{
|
||||||
// Mix Input, Voice, and External data:
|
// Mix Input, Voice, and External data:
|
||||||
StereoOut32 TW(
|
StereoOut32 TW(
|
||||||
Input.Left & thiscore.InpWetL,
|
Input.Left & thiscore.WetGate.InpL,
|
||||||
Input.Right & thiscore.InpWetR
|
Input.Right & thiscore.WetGate.InpR
|
||||||
);
|
);
|
||||||
|
|
||||||
TW.Left += Wet.Left & thiscore.SndWetL;
|
TW.Left += Voices.Wet.Left & thiscore.WetGate.SndL;
|
||||||
TW.Right += Wet.Right & thiscore.SndWetR;
|
TW.Right += Voices.Wet.Right & thiscore.WetGate.SndR;
|
||||||
TW.Left += Ext.Left & thiscore.ExtWetL;
|
TW.Left += Ext.Left & thiscore.WetGate.ExtL;
|
||||||
TW.Right += Ext.Right & thiscore.ExtWetR;
|
TW.Right += Ext.Right & thiscore.WetGate.ExtR;
|
||||||
|
|
||||||
WaveDump::WriteCore( coreidx, CoreSrc_PreReverb, TW );
|
WaveDump::WriteCore( coreidx, CoreSrc_PreReverb, TW );
|
||||||
|
|
||||||
|
@ -646,7 +663,7 @@ static StereoOut32 __fastcall MixCore( uint coreidx, const StereoOut32& Input, c
|
||||||
WaveDump::WriteCore( coreidx, CoreSrc_PostReverb, RV );
|
WaveDump::WriteCore( coreidx, CoreSrc_PostReverb, RV );
|
||||||
|
|
||||||
// Mix Dry+Wet
|
// Mix Dry+Wet
|
||||||
return StereoOut32( TD + ApplyVolume( RV, thiscore.FxVol ) );
|
return TD + ApplyVolume( RV, thiscore.FxVol );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -662,15 +679,25 @@ static int p_cachestat_counter=0;
|
||||||
|
|
||||||
__forceinline void Mix()
|
__forceinline void Mix()
|
||||||
{
|
{
|
||||||
// **** CORE ZERO ****
|
|
||||||
// Note: Playmode 4 is SPDIF, which overrides other inputs.
|
// Note: Playmode 4 is SPDIF, which overrides other inputs.
|
||||||
StereoOut32 Ext( (PlayMode&4) ? StereoOut32::Empty : ReadInputPV( 0 ) );
|
StereoOut32 InputData[2] =
|
||||||
WaveDump::WriteCore( 0, CoreSrc_Input, Ext );
|
{
|
||||||
|
(PlayMode&4) ? StereoOut32::Empty : ReadInputPV( 0 ),
|
||||||
|
(PlayMode&8) ? StereoOut32::Empty : ReadInputPV( 1 )
|
||||||
|
};
|
||||||
|
|
||||||
Ext = MixCore( 0, Ext, StereoOut32::Empty );
|
WaveDump::WriteCore( 0, CoreSrc_Input, InputData[0] );
|
||||||
|
WaveDump::WriteCore( 1, CoreSrc_Input, InputData[1] );
|
||||||
|
|
||||||
|
// Todo: Replace me with memzero initializer!
|
||||||
|
VoiceMixSet VoiceData[2] = { VoiceMixSet::Empty, VoiceMixSet::Empty }; // mixed voice data for each core.
|
||||||
|
MixCoreVoices( VoiceData[0], 0 );
|
||||||
|
MixCoreVoices( VoiceData[1], 1 );
|
||||||
|
|
||||||
|
StereoOut32 Ext( MixCore( 0, VoiceData[0], InputData[0], StereoOut32::Empty ) );
|
||||||
|
|
||||||
if( (PlayMode & 4) || (Cores[0].Mute!=0) )
|
if( (PlayMode & 4) || (Cores[0].Mute!=0) )
|
||||||
Ext = StereoOut32( 0, 0 );
|
Ext = StereoOut32::Empty;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Ext = ApplyVolume( Ext, Cores[0].MasterVol );
|
Ext = ApplyVolume( Ext, Cores[0].MasterVol );
|
||||||
|
@ -683,13 +710,8 @@ __forceinline void Mix()
|
||||||
spu2M_WriteFast( 0xA00 + OutPos, Ext.Right );
|
spu2M_WriteFast( 0xA00 + OutPos, Ext.Right );
|
||||||
WaveDump::WriteCore( 0, CoreSrc_External, Ext );
|
WaveDump::WriteCore( 0, CoreSrc_External, Ext );
|
||||||
|
|
||||||
// **** CORE ONE ****
|
|
||||||
|
|
||||||
StereoOut32 Out( (PlayMode&8) ? StereoOut32::Empty : ReadInputPV( 1 ) );
|
|
||||||
WaveDump::WriteCore( 1, CoreSrc_Input, Out );
|
|
||||||
|
|
||||||
ApplyVolume( Ext, Cores[1].ExtVol );
|
ApplyVolume( Ext, Cores[1].ExtVol );
|
||||||
Out = MixCore( 1, Out, Ext );
|
StereoOut32 Out( MixCore( 1, VoiceData[1], InputData[1], Ext ) );
|
||||||
|
|
||||||
if( PlayMode & 8 )
|
if( PlayMode & 8 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -47,7 +47,7 @@ static const u32 SAVE_ID = 0x1227521;
|
||||||
// versioning for saves.
|
// versioning for saves.
|
||||||
// Increment this when changes to the savestate system are made.
|
// Increment this when changes to the savestate system are made.
|
||||||
|
|
||||||
static const u32 SAVE_VERSION = 0x0003;
|
static const u32 SAVE_VERSION = 0x0004;
|
||||||
|
|
||||||
static void wipe_the_cache()
|
static void wipe_the_cache()
|
||||||
{
|
{
|
||||||
|
|
|
@ -163,18 +163,19 @@ void V_Core::Reset()
|
||||||
|
|
||||||
MasterVol = V_VolumeSlideLR::Max;
|
MasterVol = V_VolumeSlideLR::Max;
|
||||||
|
|
||||||
ExtWetR = -1;
|
DryGate.ExtL = -1;
|
||||||
ExtWetL = -1;
|
DryGate.ExtR = -1;
|
||||||
ExtDryR = -1;
|
WetGate.ExtL = -1;
|
||||||
ExtDryL = -1;
|
WetGate.ExtR = -1;
|
||||||
InpWetR = -1;
|
DryGate.InpL = -1;
|
||||||
InpWetL = -1;
|
DryGate.InpR = -1;
|
||||||
InpDryR = -1;
|
WetGate.InpR = -1;
|
||||||
InpDryL = -1;
|
WetGate.InpL = -1;
|
||||||
SndWetR = -1;
|
DryGate.SndL = -1;
|
||||||
SndWetL = -1;
|
DryGate.SndR = -1;
|
||||||
SndDryR = -1;
|
WetGate.SndL = -1;
|
||||||
SndDryL = -1;
|
WetGate.SndR = -1;
|
||||||
|
|
||||||
Regs.MMIX = 0xFFCF;
|
Regs.MMIX = 0xFFCF;
|
||||||
Regs.VMIXL = 0xFFFFFF;
|
Regs.VMIXL = 0xFFFFFF;
|
||||||
Regs.VMIXR = 0xFFFFFF;
|
Regs.VMIXR = 0xFFFFFF;
|
||||||
|
@ -186,17 +187,18 @@ void V_Core::Reset()
|
||||||
IRQA=0xFFFF0;
|
IRQA=0xFFFF0;
|
||||||
IRQEnable=1;
|
IRQEnable=1;
|
||||||
|
|
||||||
for( uint v=0; v<24; ++v )
|
for( uint v=0; v<NumVoices; ++v )
|
||||||
{
|
{
|
||||||
|
VoiceGates[v].DryL = -1;
|
||||||
|
VoiceGates[v].DryR = -1;
|
||||||
|
VoiceGates[v].WetL = -1;
|
||||||
|
VoiceGates[v].WetR = -1;
|
||||||
|
|
||||||
Voices[v].Volume = V_VolumeSlideLR::Max;
|
Voices[v].Volume = V_VolumeSlideLR::Max;
|
||||||
|
|
||||||
Voices[v].ADSR.Value = 0;
|
Voices[v].ADSR.Value = 0;
|
||||||
Voices[v].ADSR.Phase = 0;
|
Voices[v].ADSR.Phase = 0;
|
||||||
Voices[v].Pitch = 0x3FFF;
|
Voices[v].Pitch = 0x3FFF;
|
||||||
Voices[v].DryL = -1;
|
|
||||||
Voices[v].DryR = -1;
|
|
||||||
Voices[v].WetL = -1;
|
|
||||||
Voices[v].WetR = -1;
|
|
||||||
Voices[v].NextA = 2800;
|
Voices[v].NextA = 2800;
|
||||||
Voices[v].StartA = 2800;
|
Voices[v].StartA = 2800;
|
||||||
Voices[v].LoopStartA = 2800;
|
Voices[v].LoopStartA = 2800;
|
||||||
|
@ -461,10 +463,10 @@ void __fastcall TimeUpdate(u32 cClocks)
|
||||||
lClocks+=TickInterval;
|
lClocks+=TickInterval;
|
||||||
Cycles++;
|
Cycles++;
|
||||||
|
|
||||||
SaveMMXRegs();
|
// Note: IPU does not use MMX regs, so no need to save them.
|
||||||
|
//SaveMMXRegs();
|
||||||
Mix();
|
Mix();
|
||||||
RestoreMMXRegs();
|
//RestoreMMXRegs();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1016,7 +1018,7 @@ __forceinline void SPU2_FastWrite( u32 rmem, u16 value )
|
||||||
const uint start_bit = hiword ? 16 : 0; \
|
const uint start_bit = hiword ? 16 : 0; \
|
||||||
const uint end_bit = hiword ? 24 : 16; \
|
const uint end_bit = hiword ? 24 : 16; \
|
||||||
for (uint vc=start_bit, vx=1; vc<end_bit; ++vc, vx<<=1) \
|
for (uint vc=start_bit, vx=1; vc<end_bit; ++vc, vx<<=1) \
|
||||||
thiscore.Voices[vc].mask_out = (value & vx) ? -1 : 0; \
|
thiscore.VoiceGates[vc].mask_out = (value & vx) ? -1 : 0; \
|
||||||
}
|
}
|
||||||
|
|
||||||
case REG_S_VMIXL:
|
case REG_S_VMIXL:
|
||||||
|
@ -1058,18 +1060,18 @@ __forceinline void SPU2_FastWrite( u32 rmem, u16 value )
|
||||||
|
|
||||||
vx = value;
|
vx = value;
|
||||||
if (core == 0) vx&=0xFF0;
|
if (core == 0) vx&=0xFF0;
|
||||||
thiscore.ExtWetR = (vx & 0x001) ? -1 : 0;
|
thiscore.WetGate.ExtR = (vx & 0x001) ? -1 : 0;
|
||||||
thiscore.ExtWetL = (vx & 0x002) ? -1 : 0;
|
thiscore.WetGate.ExtL = (vx & 0x002) ? -1 : 0;
|
||||||
thiscore.ExtDryR = (vx & 0x004) ? -1 : 0;
|
thiscore.DryGate.ExtR = (vx & 0x004) ? -1 : 0;
|
||||||
thiscore.ExtDryL = (vx & 0x008) ? -1 : 0;
|
thiscore.DryGate.ExtL = (vx & 0x008) ? -1 : 0;
|
||||||
thiscore.InpWetR = (vx & 0x010) ? -1 : 0;
|
thiscore.WetGate.InpR = (vx & 0x010) ? -1 : 0;
|
||||||
thiscore.InpWetL = (vx & 0x020) ? -1 : 0;
|
thiscore.WetGate.InpL = (vx & 0x020) ? -1 : 0;
|
||||||
thiscore.InpDryR = (vx & 0x040) ? -1 : 0;
|
thiscore.DryGate.InpR = (vx & 0x040) ? -1 : 0;
|
||||||
thiscore.InpDryL = (vx & 0x080) ? -1 : 0;
|
thiscore.DryGate.InpL = (vx & 0x080) ? -1 : 0;
|
||||||
thiscore.SndWetR = (vx & 0x100) ? -1 : 0;
|
thiscore.WetGate.SndR = (vx & 0x100) ? -1 : 0;
|
||||||
thiscore.SndWetL = (vx & 0x200) ? -1 : 0;
|
thiscore.WetGate.SndL = (vx & 0x200) ? -1 : 0;
|
||||||
thiscore.SndDryR = (vx & 0x400) ? -1 : 0;
|
thiscore.DryGate.SndR = (vx & 0x400) ? -1 : 0;
|
||||||
thiscore.SndDryL = (vx & 0x800) ? -1 : 0;
|
thiscore.DryGate.SndL = (vx & 0x800) ? -1 : 0;
|
||||||
thiscore.Regs.MMIX = value;
|
thiscore.Regs.MMIX = value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1199,7 +1201,7 @@ void StartVoices(int core, u32 value)
|
||||||
|
|
||||||
Cores[core].Regs.ENDX &= ~value;
|
Cores[core].Regs.ENDX &= ~value;
|
||||||
|
|
||||||
for( u8 vc=0; vc<24; vc++ )
|
for( u8 vc=0; vc<V_Core::NumVoices; vc++ )
|
||||||
{
|
{
|
||||||
if ((value>>vc) & 1)
|
if ((value>>vc) & 1)
|
||||||
{
|
{
|
||||||
|
@ -1211,8 +1213,8 @@ void StartVoices(int core, u32 value)
|
||||||
|
|
||||||
if(MsgKeyOnOff()) ConLog(" * SPU2: KeyOn: C%dV%02d: SSA: %8x; M: %s%s%s%s; H: %02x%02x; P: %04x V: %04x/%04x; ADSR: %04x%04x\n",
|
if(MsgKeyOnOff()) ConLog(" * SPU2: KeyOn: C%dV%02d: SSA: %8x; M: %s%s%s%s; H: %02x%02x; P: %04x V: %04x/%04x; ADSR: %04x%04x\n",
|
||||||
core,vc,thisvc.StartA,
|
core,vc,thisvc.StartA,
|
||||||
(thisvc.DryL)?"+":"-",(thisvc.DryR)?"+":"-",
|
(Cores[core].VoiceGates[vc].DryL)?"+":"-",(Cores[core].VoiceGates[vc].DryR)?"+":"-",
|
||||||
(thisvc.WetL)?"+":"-",(thisvc.WetR)?"+":"-",
|
(Cores[core].VoiceGates[vc].WetL)?"+":"-",(Cores[core].VoiceGates[vc].WetR)?"+":"-",
|
||||||
*(u8*)GetMemPtr(thisvc.StartA),*(u8 *)GetMemPtr((thisvc.StartA)+1),
|
*(u8*)GetMemPtr(thisvc.StartA),*(u8 *)GetMemPtr((thisvc.StartA)+1),
|
||||||
thisvc.Pitch,
|
thisvc.Pitch,
|
||||||
thisvc.Volume.Left.Value>>16,thisvc.Volume.Right.Value>>16,
|
thisvc.Volume.Left.Value>>16,thisvc.Volume.Right.Value>>16,
|
||||||
|
@ -1225,7 +1227,7 @@ void StartVoices(int core, u32 value)
|
||||||
void StopVoices(int core, u32 value)
|
void StopVoices(int core, u32 value)
|
||||||
{
|
{
|
||||||
if( value == 0 ) return;
|
if( value == 0 ) return;
|
||||||
for( u8 vc=0; vc<24; vc++ )
|
for( u8 vc=0; vc<V_Core::NumVoices; vc++ )
|
||||||
{
|
{
|
||||||
if ((value>>vc) & 1)
|
if ((value>>vc) & 1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -210,7 +210,7 @@ extern void __fastcall ReadInput( uint core, StereoOut32& PData );
|
||||||
|
|
||||||
extern void Mix();
|
extern void Mix();
|
||||||
extern s32 clamp_mix( s32 x, u8 bitshift=0 );
|
extern s32 clamp_mix( s32 x, u8 bitshift=0 );
|
||||||
extern void clamp_mix( StereoOut32& sample, u8 bitshift=0 );
|
extern StereoOut32 clamp_mix( const StereoOut32& sample, u8 bitshift=0 );
|
||||||
extern void Reverb_AdvanceBuffer( V_Core& thiscore );
|
extern void Reverb_AdvanceBuffer( V_Core& thiscore );
|
||||||
extern StereoOut32 DoReverb( V_Core& thiscore, const StereoOut32& Input );
|
extern StereoOut32 DoReverb( V_Core& thiscore, const StereoOut32& Input );
|
||||||
extern s32 MulShr32( s32 srcval, s32 mulval );
|
extern s32 MulShr32( s32 srcval, s32 mulval );
|
||||||
|
|
|
@ -128,14 +128,6 @@ struct V_Voice
|
||||||
s8 Modulated;
|
s8 Modulated;
|
||||||
// Source (Wave/Noise)
|
// Source (Wave/Noise)
|
||||||
s8 Noise;
|
s8 Noise;
|
||||||
// Direct Output for Left Channel
|
|
||||||
s32 DryL;
|
|
||||||
// Direct Output for Right Channel
|
|
||||||
s32 DryR;
|
|
||||||
// Effect Output for Left Channel
|
|
||||||
s32 WetL;
|
|
||||||
// Effect Output for Right Channel
|
|
||||||
s32 WetR;
|
|
||||||
// Loop Start address (also Reg_LSAH/L)
|
// Loop Start address (also Reg_LSAH/L)
|
||||||
u32 LoopStartA;
|
u32 LoopStartA;
|
||||||
// Sound Start address (also Reg_SSAH/L)
|
// Sound Start address (also Reg_SSAH/L)
|
||||||
|
@ -309,11 +301,40 @@ struct V_CoreRegs
|
||||||
u16 _1AC;
|
u16 _1AC;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct V_VoiceGates
|
||||||
|
{
|
||||||
|
s16 DryL; // 'AND Gate' for Direct Output to Left Channel
|
||||||
|
s16 DryR; // 'AND Gate' for Direct Output for Right Channel
|
||||||
|
s16 WetL; // 'AND Gate' for Effect Output for Left Channel
|
||||||
|
s16 WetR; // 'AND Gate' for Effect Output for Right Channel
|
||||||
|
};
|
||||||
|
|
||||||
|
union V_CoreGates
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u64 lo;
|
||||||
|
u64 hi;
|
||||||
|
} v128;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
s16 InpL; // Sound Data Input to Direct Output (Left)
|
||||||
|
s16 InpR; // Sound Data Input to Direct Output (Right)
|
||||||
|
s16 SndL; // Voice Data to Direct Output (Left)
|
||||||
|
s16 SndR; // Voice Data to Direct Output (Right)
|
||||||
|
s16 ExtL; // External Input to Direct Output (Left)
|
||||||
|
s16 ExtR; // External Input to Direct Output (Right)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
struct V_Core
|
struct V_Core
|
||||||
{
|
{
|
||||||
// Core Voices
|
static const uint NumVoices = 24;
|
||||||
V_Voice Voices[24];
|
|
||||||
|
|
||||||
|
// Core Voices
|
||||||
|
V_Voice Voices[NumVoices];
|
||||||
|
V_VoiceGates VoiceGates[NumVoices];
|
||||||
|
|
||||||
V_VolumeSlideLR MasterVol;// Master Volume
|
V_VolumeSlideLR MasterVol;// Master Volume
|
||||||
|
|
||||||
|
@ -321,36 +342,16 @@ struct V_Core
|
||||||
V_VolumeLR InpVol; // Volume for Sound Data Input
|
V_VolumeLR InpVol; // Volume for Sound Data Input
|
||||||
V_VolumeLR FxVol; // Volume for Output from Effects
|
V_VolumeLR FxVol; // Volume for Output from Effects
|
||||||
|
|
||||||
|
V_CoreGates DryGate;
|
||||||
|
V_CoreGates WetGate;
|
||||||
|
|
||||||
// Interrupt Address
|
// Interrupt Address
|
||||||
u32 IRQA;
|
u32 IRQA;
|
||||||
// DMA Transfer Start Address
|
// DMA Transfer Start Address
|
||||||
u32 TSA;
|
u32 TSA;
|
||||||
// DMA Transfer Data Address (Internal...)
|
// DMA Transfer Data Address (Internal...)
|
||||||
u32 TDA;
|
u32 TDA;
|
||||||
// External Input to Direct Output (Left)
|
|
||||||
s32 ExtDryL;
|
|
||||||
// External Input to Direct Output (Right)
|
|
||||||
s32 ExtDryR;
|
|
||||||
// External Input to Effects (Left)
|
|
||||||
s32 ExtWetL;
|
|
||||||
// External Input to Effects (Right)
|
|
||||||
s32 ExtWetR;
|
|
||||||
// Sound Data Input to Direct Output (Left)
|
|
||||||
s32 InpDryL;
|
|
||||||
// Sound Data Input to Direct Output (Right)
|
|
||||||
s32 InpDryR;
|
|
||||||
// Sound Data Input to Effects (Left)
|
|
||||||
s32 InpWetL;
|
|
||||||
// Sound Data Input to Effects (Right)
|
|
||||||
s32 InpWetR;
|
|
||||||
// Voice Data to Direct Output (Left)
|
|
||||||
s32 SndDryL;
|
|
||||||
// Voice Data to Direct Output (Right)
|
|
||||||
s32 SndDryR;
|
|
||||||
// Voice Data to Effects (Left)
|
|
||||||
s32 SndWetL;
|
|
||||||
// Voice Data to Effects (Right)
|
|
||||||
s32 SndWetR;
|
|
||||||
// Interrupt Enable
|
// Interrupt Enable
|
||||||
s8 IRQEnable;
|
s8 IRQEnable;
|
||||||
// DMA related?
|
// DMA related?
|
||||||
|
|
Loading…
Reference in New Issue