mirror of https://github.com/PCSX2/pcsx2.git
SPU2: Get rid of the need for delay cycles
Properly handle KeyOn/KeyOff happening in quick succession.
This commit is contained in:
parent
f929d79473
commit
465aa00fc7
|
@ -57,7 +57,6 @@ float VolumeAdjustBR;
|
|||
float VolumeAdjustSL;
|
||||
float VolumeAdjustSR;
|
||||
float VolumeAdjustLFE;
|
||||
unsigned int delayCycles;
|
||||
|
||||
bool postprocess_filter_enabled = true;
|
||||
bool postprocess_filter_dealias = false;
|
||||
|
@ -109,7 +108,6 @@ void ReadSettings()
|
|||
VolumeAdjustSL = powf(10, VolumeAdjustSLdb / 10);
|
||||
VolumeAdjustSR = powf(10, VolumeAdjustSRdb / 10);
|
||||
VolumeAdjustLFE = powf(10, VolumeAdjustLFEdb / 10);
|
||||
delayCycles = CfgReadInt(L"DEBUG", L"DelayCycles", 4);
|
||||
|
||||
wxString temp;
|
||||
|
||||
|
@ -207,7 +205,6 @@ void WriteSettings()
|
|||
CfgWriteInt(L"OUTPUT", L"Latency", SndOutLatencyMS);
|
||||
CfgWriteInt(L"OUTPUT", L"Synch_Mode", SynchMode);
|
||||
CfgWriteInt(L"OUTPUT", L"SpeakerConfiguration", numSpeakers);
|
||||
CfgWriteInt(L"DEBUG", L"DelayCycles", delayCycles);
|
||||
|
||||
#ifdef SPU2X_PORTAUDIO
|
||||
PortaudioOut->WriteSettings();
|
||||
|
|
|
@ -43,7 +43,6 @@ extern float VolumeAdjustBR;
|
|||
extern float VolumeAdjustSL;
|
||||
extern float VolumeAdjustSR;
|
||||
extern float VolumeAdjustLFE;
|
||||
extern unsigned int delayCycles;
|
||||
|
||||
struct Stereo51Out16DplII;
|
||||
struct Stereo51Out32DplII;
|
||||
|
|
|
@ -58,7 +58,6 @@ float VolumeAdjustBR;
|
|||
float VolumeAdjustSL;
|
||||
float VolumeAdjustSR;
|
||||
float VolumeAdjustLFE;
|
||||
unsigned int delayCycles;
|
||||
|
||||
bool postprocess_filter_enabled = 1;
|
||||
bool postprocess_filter_dealias = false;
|
||||
|
@ -102,7 +101,6 @@ void ReadSettings()
|
|||
VolumeAdjustSLdb = CfgReadFloat(L"MIXING", L"VolumeAdjustSL(dB)", 0);
|
||||
VolumeAdjustSRdb = CfgReadFloat(L"MIXING", L"VolumeAdjustSR(dB)", 0);
|
||||
VolumeAdjustLFEdb = CfgReadFloat(L"MIXING", L"VolumeAdjustLFE(dB)", 0);
|
||||
delayCycles = CfgReadInt(L"DEBUG", L"DelayCycles", 4);
|
||||
VolumeAdjustC = powf(10, VolumeAdjustCdb / 10);
|
||||
VolumeAdjustFL = powf(10, VolumeAdjustFLdb / 10);
|
||||
VolumeAdjustFR = powf(10, VolumeAdjustFRdb / 10);
|
||||
|
@ -185,7 +183,6 @@ void WriteSettings()
|
|||
CfgWriteInt(L"OUTPUT", L"Synch_Mode", SynchMode);
|
||||
CfgWriteInt(L"OUTPUT", L"SpeakerConfiguration", numSpeakers);
|
||||
CfgWriteInt(L"OUTPUT", L"DplDecodingLevel", dplLevel);
|
||||
CfgWriteInt(L"DEBUG", L"DelayCycles", delayCycles);
|
||||
|
||||
if (Config_WaveOut.Device.empty())
|
||||
Config_WaveOut.Device = L"default";
|
||||
|
|
|
@ -189,7 +189,6 @@ struct V_Voice
|
|||
s32 SCurrent;
|
||||
|
||||
// it takes a few ticks for voices to start on the real SPU2?
|
||||
void QueueStart();
|
||||
bool Start();
|
||||
void Stop();
|
||||
};
|
||||
|
|
|
@ -327,44 +327,29 @@ void V_Core::UpdateEffectsBufferSize()
|
|||
RevBuffers.APF2_R_SRC = EffectsBufferIndexer(Revb.APF2_R_DST - Revb.APF2_SIZE);
|
||||
}
|
||||
|
||||
void V_Voice::QueueStart()
|
||||
{
|
||||
if (Cycles - PlayCycle < delayCycles)
|
||||
{
|
||||
// Required by The Legend of Spyro: The Eternal Night (probably the other two legend games too)
|
||||
ConLog(" *** KeyOn after less than %d T disregarded.\n", delayCycles);
|
||||
return;
|
||||
}
|
||||
PlayCycle = Cycles;
|
||||
}
|
||||
|
||||
bool V_Voice::Start()
|
||||
{
|
||||
if ((Cycles - PlayCycle) >= delayCycles)
|
||||
if (StartA & 7)
|
||||
{
|
||||
if (StartA & 7)
|
||||
{
|
||||
fprintf(stderr, " *** Misaligned StartA %05x!\n", StartA);
|
||||
StartA = (StartA + 0xFFFF8) + 0x8;
|
||||
}
|
||||
|
||||
ADSR.Releasing = false;
|
||||
ADSR.Value = 1;
|
||||
ADSR.Phase = 1;
|
||||
SCurrent = 28;
|
||||
LoopMode = 0;
|
||||
LoopFlags = 0;
|
||||
NextA = StartA | 1;
|
||||
Prev1 = 0;
|
||||
Prev2 = 0;
|
||||
|
||||
PV1 = PV2 = 0;
|
||||
PV3 = PV4 = 0;
|
||||
NextCrest = -0x8000;
|
||||
return true;
|
||||
fprintf(stderr, " *** Misaligned StartA %05x!\n", StartA);
|
||||
StartA = (StartA + 0xFFFF8) + 0x8;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
ADSR.Releasing = false;
|
||||
ADSR.Value = 1;
|
||||
ADSR.Phase = 1;
|
||||
SCurrent = 28;
|
||||
LoopMode = 0;
|
||||
LoopFlags = 0;
|
||||
NextA = StartA | 1;
|
||||
Prev1 = 0;
|
||||
Prev2 = 0;
|
||||
|
||||
PV1 = PV2 = 0;
|
||||
PV3 = PV4 = 0;
|
||||
NextCrest = -0x8000;
|
||||
PlayCycle = Cycles;
|
||||
return true;
|
||||
}
|
||||
|
||||
void V_Voice::Stop()
|
||||
|
@ -471,13 +456,6 @@ __forceinline void TimeUpdate(u32 cClocks)
|
|||
lClocks += TickInterval;
|
||||
Cycles++;
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
if (Cores[i].KeyOn)
|
||||
for (int j = 0; j < 24; j++)
|
||||
if (Cores[i].KeyOn >> j & 1)
|
||||
if (Cores[i].Voices[j].Start())
|
||||
Cores[i].KeyOn &= ~(1 << j);
|
||||
|
||||
// Note: IOP does not use MMX regs, so no need to save them.
|
||||
//SaveMMXRegs();
|
||||
Mix();
|
||||
|
@ -1857,22 +1835,23 @@ void SPU2_FastWrite(u32 rmem, u16 value)
|
|||
|
||||
void StartVoices(int core, u32 value)
|
||||
{
|
||||
ConLog("KeyOn Write %x\n", value);
|
||||
|
||||
// Optimization: Games like to write zero to the KeyOn reg a lot, so shortcut
|
||||
// this loop if value is zero.
|
||||
|
||||
if (value == 0)
|
||||
return;
|
||||
|
||||
Cores[core].Regs.ENDX &= ~value;
|
||||
|
||||
Cores[core].KeyOn |= value;
|
||||
Cores[core].Regs.ENDX &= ~value;
|
||||
|
||||
for (u8 vc = 0; vc < V_Core::NumVoices; vc++)
|
||||
{
|
||||
if (!((value >> vc) & 1))
|
||||
continue;
|
||||
|
||||
Cores[core].Voices[vc].QueueStart();
|
||||
if (Cores[core].Voices[vc].Start())
|
||||
Cores[core].KeyOn &= ~(1 << vc);
|
||||
|
||||
if (IsDevBuild)
|
||||
{
|
||||
|
@ -1893,13 +1872,22 @@ void StartVoices(int core, u32 value)
|
|||
|
||||
void StopVoices(int core, u32 value)
|
||||
{
|
||||
ConLog("KeyOff Write %x\n", value);
|
||||
|
||||
if (value == 0)
|
||||
return;
|
||||
|
||||
for (u8 vc = 0; vc < V_Core::NumVoices; vc++)
|
||||
{
|
||||
if (!((value >> vc) & 1))
|
||||
continue;
|
||||
|
||||
if (Cycles - Cores[core].Voices[vc].PlayCycle < 2)
|
||||
{
|
||||
ConLog("Attempt to stop voice %d on core %d in less than 2T since KeyOn\n", vc, core);
|
||||
continue;
|
||||
}
|
||||
|
||||
Cores[core].Voices[vc].ADSR.Releasing = true;
|
||||
if (MsgKeyOnOff())
|
||||
ConLog("* SPU2: KeyOff: Core %d; Voice %d.\n", core, vc);
|
||||
|
|
Loading…
Reference in New Issue