mirror of https://github.com/PCSX2/pcsx2.git
SPU2-X: Added a lowpass filter to the reverb output, which should produce more correct audio (still experimental). Plus many code cleanups.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@509 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
d5b0ff7fa3
commit
340db13caa
|
@ -51,7 +51,37 @@ static __forceinline T GetClamped( T src, T min, T max )
|
||||||
return std::min( std::max( src, min ), max );
|
return std::min( std::max( src, min ), max );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern void SysMessage(const char *fmt, ...);
|
extern void SysMessage(const char *fmt, ...);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
// Dev / Debug conditionals --
|
||||||
|
// Consts for using if() statements instead of uglier #ifdef macros.
|
||||||
|
// Abbreviated macros for dev/debug only consoles and msgboxes.
|
||||||
|
|
||||||
|
#ifdef SPU2X_DEVBUILD
|
||||||
|
|
||||||
|
# define DevCon Console
|
||||||
|
# define DevMsg MsgBox
|
||||||
|
static const bool IsDevBuild = true;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
# define DevCon 0&&Console
|
||||||
|
# define DevMsg
|
||||||
|
static const bool IsDevBuild = false;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
|
||||||
|
# define DbgCon Console
|
||||||
|
static const bool IsDebugBuild = true;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
# define DbgCon 0&&Console
|
||||||
|
static const bool IsDebugBuild = false;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -187,14 +187,14 @@ void DoFullDump()
|
||||||
" - Value: %x\n",
|
" - Value: %x\n",
|
||||||
Cores[c].Voices[v].ADSR.Reg_ADSR1,
|
Cores[c].Voices[v].ADSR.Reg_ADSR1,
|
||||||
Cores[c].Voices[v].ADSR.Reg_ADSR2,
|
Cores[c].Voices[v].ADSR.Reg_ADSR2,
|
||||||
Cores[c].Voices[v].ADSR.Ar,
|
Cores[c].Voices[v].ADSR.AttackRate,
|
||||||
Cores[c].Voices[v].ADSR.Am,
|
Cores[c].Voices[v].ADSR.AttackMode,
|
||||||
Cores[c].Voices[v].ADSR.Dr,
|
Cores[c].Voices[v].ADSR.DecayRate,
|
||||||
Cores[c].Voices[v].ADSR.Sl,
|
Cores[c].Voices[v].ADSR.SustainLevel,
|
||||||
Cores[c].Voices[v].ADSR.Sr,
|
Cores[c].Voices[v].ADSR.SustainRate,
|
||||||
Cores[c].Voices[v].ADSR.Sm,
|
Cores[c].Voices[v].ADSR.SustainMode,
|
||||||
Cores[c].Voices[v].ADSR.Rr,
|
Cores[c].Voices[v].ADSR.ReleaseRate,
|
||||||
Cores[c].Voices[v].ADSR.Rm,
|
Cores[c].Voices[v].ADSR.ReleaseMode,
|
||||||
Cores[c].Voices[v].ADSR.Phase,
|
Cores[c].Voices[v].ADSR.Phase,
|
||||||
Cores[c].Voices[v].ADSR.Value);
|
Cores[c].Voices[v].ADSR.Value);
|
||||||
fprintf(dump," - Pitch: %x\n",Cores[c].Voices[v].Pitch);
|
fprintf(dump," - Pitch: %x\n",Cores[c].Voices[v].Pitch);
|
||||||
|
|
|
@ -45,46 +45,49 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD dwReason,LPVOID lpvReserved)
|
||||||
|
|
||||||
static void InitLibraryName()
|
static void InitLibraryName()
|
||||||
{
|
{
|
||||||
#ifdef PUBLIC
|
if( !IsDevBuild )
|
||||||
|
{
|
||||||
|
// Public Release!
|
||||||
|
// Output a simplified string that's just our name:
|
||||||
|
|
||||||
// Public Release!
|
strcpy( libraryName, "SPU2-X" );
|
||||||
// Output a simplified string that's just our name:
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef SVN_REV_UNKNOWN
|
||||||
|
|
||||||
strcpy( libraryName, "SPU2-X" );
|
// Unknown revision.
|
||||||
|
// Output a name that includes devbuild status but not
|
||||||
|
// subversion revision tags:
|
||||||
|
|
||||||
#elif defined( SVN_REV_UNKNOWN )
|
strcpy( libraryName, "SPU2-X"
|
||||||
|
#ifdef _DEBUG_FAST
|
||||||
// Unknown revision.
|
"-Debug"
|
||||||
// Output a name that includes devbuild status but not
|
#elif defined( DEBUG )
|
||||||
// subversion revision tags:
|
"-Debug/Strict" // strict debugging is slow!
|
||||||
|
#else
|
||||||
strcpy( libraryName, "SPU2-X"
|
"-Dev"
|
||||||
# ifdef _DEBUG_FAST
|
#endif
|
||||||
"-Debug"
|
|
||||||
# elif defined( DEBUG )
|
|
||||||
"-Debug/Strict" // strict debugging is slow!
|
|
||||||
# else
|
|
||||||
"-Dev"
|
|
||||||
# endif
|
|
||||||
);
|
);
|
||||||
#else
|
|
||||||
|
|
||||||
// Use TortoiseSVN's SubWCRev utility's output
|
#else
|
||||||
// to label the specific revision:
|
|
||||||
|
|
||||||
sprintf_s( libraryName, "SPU2-X r%d%s"
|
// Use TortoiseSVN's SubWCRev utility's output
|
||||||
# ifdef _DEBUG_FAST
|
// to label the specific revision:
|
||||||
"-Debug"
|
|
||||||
# elif defined( _DEBUG )
|
sprintf_s( libraryName, "SPU2-X r%d%s"
|
||||||
"-Debug/Strict" // strict debugging is slow!
|
#ifdef _DEBUG_FAST
|
||||||
# else
|
"-Debug"
|
||||||
"-Dev"
|
#elif defined( _DEBUG )
|
||||||
# endif
|
"-Debug/Strict" // strict debugging is slow!
|
||||||
,SVN_REV,
|
#else
|
||||||
SVN_MODS ? "m" : ""
|
"-Dev"
|
||||||
|
#endif
|
||||||
|
,SVN_REV,
|
||||||
|
SVN_MODS ? "m" : ""
|
||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_C_(u32) PS2EgetLibType()
|
EXPORT_C_(u32) PS2EgetLibType()
|
||||||
|
@ -309,29 +312,31 @@ bool numpad_plus = false, numpad_plus_old = false;
|
||||||
|
|
||||||
EXPORT_C_(void) SPU2async(u32 cycles)
|
EXPORT_C_(void) SPU2async(u32 cycles)
|
||||||
{
|
{
|
||||||
#ifndef PUBLIC
|
if( IsDevBuild )
|
||||||
u32 oldClocks = lClocks;
|
{
|
||||||
static u32 timer=0,time1=0,time2=0;
|
u32 oldClocks = lClocks;
|
||||||
timer++;
|
static u32 timer=0,time1=0,time2=0;
|
||||||
if (timer == 1){
|
timer++;
|
||||||
time1=timeGetTime();
|
if (timer == 1){
|
||||||
|
time1=timeGetTime();
|
||||||
|
}
|
||||||
|
if (timer == 3000){
|
||||||
|
time2 = timeGetTime()-time1 ;
|
||||||
|
timer=0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (timer == 3000){
|
|
||||||
time2 = timeGetTime()-time1 ;
|
|
||||||
timer=0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DspUpdate();
|
DspUpdate();
|
||||||
|
|
||||||
#ifndef PUBLIC
|
if( IsDevBuild )
|
||||||
/*numpad_plus = (GetAsyncKeyState(VK_ADD)&0x8000)!=0;
|
|
||||||
if(numpad_plus && !numpad_plus_old)
|
|
||||||
{
|
{
|
||||||
DoFullDump();
|
/*numpad_plus = (GetAsyncKeyState(VK_ADD)&0x8000)!=0;
|
||||||
|
if(numpad_plus && !numpad_plus_old)
|
||||||
|
{
|
||||||
|
DoFullDump();
|
||||||
|
}
|
||||||
|
numpad_plus_old = numpad_plus;*/
|
||||||
}
|
}
|
||||||
numpad_plus_old = numpad_plus;*/
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(hasPtr)
|
if(hasPtr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -438,9 +438,9 @@ void SPU2writeDMA(int core, u16* pMem, u32 size)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PUBLIC
|
if( IsDevBuild )
|
||||||
DebugCores[core].lastsize=size;
|
DebugCores[core].lastsize = size;
|
||||||
#endif
|
|
||||||
Cores[core].TSA&=~7;
|
Cores[core].TSA&=~7;
|
||||||
|
|
||||||
bool adma_enable = ((Cores[core].AutoDMACtrl&(core+1))==(core+1));
|
bool adma_enable = ((Cores[core].AutoDMACtrl&(core+1))==(core+1));
|
||||||
|
|
|
@ -28,8 +28,7 @@ void ADMAOutLogWrite(void *lpData, u32 ulSize);
|
||||||
|
|
||||||
u32 core, voice;
|
u32 core, voice;
|
||||||
|
|
||||||
static const s32 ADSR_MAX_VOL = 0x7fffffff;
|
static const s32 tbl_XA_Factor[5][2] =
|
||||||
static const s32 f[5][2] =
|
|
||||||
{
|
{
|
||||||
{ 0, 0 },
|
{ 0, 0 },
|
||||||
{ 60, 0 },
|
{ 60, 0 },
|
||||||
|
@ -38,13 +37,10 @@ static const s32 f[5][2] =
|
||||||
{ 122, -60 }
|
{ 122, -60 }
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int InvExpOffsets[] = { 0,4,6,8,9,10,11,12 };
|
|
||||||
static u32 PsxRates[160];
|
|
||||||
|
|
||||||
|
|
||||||
// Performs a 64-bit multiplication between two values and returns the
|
// Performs a 64-bit multiplication between two values and returns the
|
||||||
// high 32 bits as a result (discarding the fractional 32 bits).
|
// high 32 bits as a result (discarding the fractional 32 bits).
|
||||||
// The combined fracional bits of both inputs must be 32 bits for this
|
// The combined fractional bits of both inputs must be 32 bits for this
|
||||||
// to work properly.
|
// to work properly.
|
||||||
//
|
//
|
||||||
// This is meant to be a drop-in replacement for times when the 'div' part
|
// This is meant to be a drop-in replacement for times when the 'div' part
|
||||||
|
@ -70,29 +66,12 @@ __forceinline s32 clamp_mix(s32 x, u8 bitshift)
|
||||||
return GetClamped( x, -0x8000<<bitshift, 0x7fff<<bitshift );
|
return GetClamped( x, -0x8000<<bitshift, 0x7fff<<bitshift );
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitADSR() // INIT ADSR
|
|
||||||
{
|
|
||||||
for (int i=0; i<(32+128); i++)
|
|
||||||
{
|
|
||||||
int shift=(i-32)>>2;
|
|
||||||
s64 rate=(i&3)+4;
|
|
||||||
if (shift<0)
|
|
||||||
rate >>= -shift;
|
|
||||||
else
|
|
||||||
rate <<= shift;
|
|
||||||
|
|
||||||
PsxRates[i] = (int)min( rate, 0x3fffffffLL );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define VOL(x) (((s32)x)) //24.8 volume
|
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
const s32 header = *block;
|
const s32 header = *block;
|
||||||
s32 shift = ((header>> 0)&0xF)+16;
|
s32 shift = ((header>> 0)&0xF)+16;
|
||||||
s32 pred1 = f[(header>> 4)&0xF][0];
|
s32 pred1 = tbl_XA_Factor[(header>> 4)&0xF][0];
|
||||||
s32 pred2 = f[(header>> 4)&0xF][1];
|
s32 pred2 = tbl_XA_Factor[(header>> 4)&0xF][1];
|
||||||
|
|
||||||
const s8* blockbytes = (s8*)&block[1];
|
const s8* blockbytes = (s8*)&block[1];
|
||||||
|
|
||||||
|
@ -129,8 +108,8 @@ static void __forceinline XA_decode_block_unsaturated(s16* buffer, const s16* bl
|
||||||
{
|
{
|
||||||
const s32 header = *block;
|
const s32 header = *block;
|
||||||
s32 shift = ((header>> 0)&0xF)+16;
|
s32 shift = ((header>> 0)&0xF)+16;
|
||||||
s32 pred1 = f[(header>> 4)&0xF][0];
|
s32 pred1 = tbl_XA_Factor[(header>> 4)&0xF][0];
|
||||||
s32 pred2 = f[(header>> 4)&0xF][1];
|
s32 pred2 = tbl_XA_Factor[(header>> 4)&0xF][1];
|
||||||
|
|
||||||
const s8* blockbytes = (s8*)&block[1];
|
const s8* blockbytes = (s8*)&block[1];
|
||||||
|
|
||||||
|
@ -167,10 +146,10 @@ static void __forceinline IncrementNextA( const V_Core& thiscore, V_Voice& vc )
|
||||||
{
|
{
|
||||||
if( Cores[i].IRQEnable && (vc.NextA==Cores[i].IRQA ) )
|
if( Cores[i].IRQEnable && (vc.NextA==Cores[i].IRQA ) )
|
||||||
{
|
{
|
||||||
#ifndef PUBLIC
|
if( IsDevBuild )
|
||||||
ConLog(" * SPU2 Core %d: IRQ Called (IRQ passed).\n", i);
|
ConLog(" * SPU2 Core %d: IRQ Called (IRQ passed).\n", i);
|
||||||
#endif
|
|
||||||
Spdif.Info=4<<i;
|
Spdif.Info = 4 << i;
|
||||||
SetIrqCall();
|
SetIrqCall();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -184,11 +163,9 @@ static void __forceinline IncrementNextA( const V_Core& thiscore, V_Voice& vc )
|
||||||
// invalided when DMA transfers and memory writes are performed.
|
// invalided when DMA transfers and memory writes are performed.
|
||||||
PcmCacheEntry *pcm_cache_data = NULL;
|
PcmCacheEntry *pcm_cache_data = NULL;
|
||||||
|
|
||||||
#ifndef PUBLIC
|
int g_counter_cache_hits = 0;
|
||||||
int g_counter_cache_hits=0;
|
int g_counter_cache_misses = 0;
|
||||||
int g_counter_cache_misses=0;
|
int g_counter_cache_ignores = 0;
|
||||||
int g_counter_cache_ignores=0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define XAFLAG_LOOP_END (1ul<<0)
|
#define XAFLAG_LOOP_END (1ul<<0)
|
||||||
#define XAFLAG_LOOP (1ul<<1)
|
#define XAFLAG_LOOP (1ul<<1)
|
||||||
|
@ -213,12 +190,12 @@ static void __forceinline __fastcall GetNextDataBuffered( V_Core& thiscore, V_Vo
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VoiceStop(core,voice);
|
vc.Stop();
|
||||||
thiscore.Regs.ENDX|=1<<voice;
|
if( IsDevBuild )
|
||||||
#ifndef PUBLIC
|
{
|
||||||
if(MsgVoiceOff()) ConLog(" * SPU2: Voice Off by EndPoint: %d \n", voice);
|
if(MsgVoiceOff()) ConLog(" * SPU2: Voice Off by EndPoint: %d \n", voice);
|
||||||
DebugCores[core].Voices[voice].lastStopReason = 1;
|
DebugCores[core].Voices[voice].lastStopReason = 1;
|
||||||
#endif
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,9 +219,8 @@ static void __forceinline __fastcall GetNextDataBuffered( V_Core& thiscore, V_Vo
|
||||||
|
|
||||||
//ConLog( " * SPU2 : Cache Hit! NextA=0x%x, cacheIdx=0x%x\n", vc.NextA, cacheIdx );
|
//ConLog( " * SPU2 : Cache Hit! NextA=0x%x, cacheIdx=0x%x\n", vc.NextA, cacheIdx );
|
||||||
|
|
||||||
#ifndef PUBLIC
|
if( IsDevBuild )
|
||||||
g_counter_cache_hits++;
|
g_counter_cache_hits++;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -252,12 +228,13 @@ static void __forceinline __fastcall GetNextDataBuffered( V_Core& thiscore, V_Vo
|
||||||
if( vc.NextA >= SPU2_DYN_MEMLINE )
|
if( vc.NextA >= SPU2_DYN_MEMLINE )
|
||||||
cacheLine.Validated = true;
|
cacheLine.Validated = true;
|
||||||
|
|
||||||
#ifndef PUBLIC
|
if( IsDevBuild )
|
||||||
if( vc.NextA < SPU2_DYN_MEMLINE )
|
{
|
||||||
g_counter_cache_ignores++;
|
if( vc.NextA < SPU2_DYN_MEMLINE )
|
||||||
else
|
g_counter_cache_ignores++;
|
||||||
g_counter_cache_misses++;
|
else
|
||||||
#endif
|
g_counter_cache_misses++;
|
||||||
|
}
|
||||||
|
|
||||||
s16* sbuffer = cacheLine.Sampledata;
|
s16* sbuffer = cacheLine.Sampledata;
|
||||||
|
|
||||||
|
@ -284,166 +261,6 @@ _skipIncrement:
|
||||||
Data = vc.SBuffer[vc.SCurrent++];
|
Data = vc.SBuffer[vc.SCurrent++];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the linear slide value for AR and SR inputs.
|
|
||||||
static int GetLinearSrAr( uint SrAr )
|
|
||||||
{
|
|
||||||
// The Sr/Ar settings work in quarter steps, which means
|
|
||||||
// the bottom 2 bits go on the left side of the shift, and
|
|
||||||
// the right side of the shift gets divided by 4:
|
|
||||||
|
|
||||||
const uint newSr = 0x7f - SrAr;
|
|
||||||
return ((1|(newSr&3)) << (newSr>>2));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __forceinline CalculateADSR( V_Voice& vc )
|
|
||||||
{
|
|
||||||
V_ADSR& env(vc.ADSR);
|
|
||||||
|
|
||||||
jASSUME( env.Phase != 0 );
|
|
||||||
|
|
||||||
if(env.Releasing && (env.Phase < 5))
|
|
||||||
env.Phase = 5;
|
|
||||||
|
|
||||||
switch (env.Phase)
|
|
||||||
{
|
|
||||||
case 1: // attack
|
|
||||||
if( env.Value == ADSR_MAX_VOL )
|
|
||||||
{
|
|
||||||
// Already maxed out. Progress phase and nothing more:
|
|
||||||
env.Phase++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Case 1 below is for pseudo exponential below 75%.
|
|
||||||
// Pseudo Exp > 75% and Linear are the same.
|
|
||||||
|
|
||||||
if (env.Am && (env.Value>=0x60000000))
|
|
||||||
env.Value += PsxRates[(env.Ar^0x7f)-0x18+32];
|
|
||||||
else //if( env.Ar < 0x7f )
|
|
||||||
env.Value+=PsxRates[(env.Ar^0x7f)-0x10+32];
|
|
||||||
//env.Value += GetLinearSrAr( env.Ar );
|
|
||||||
|
|
||||||
if( env.Value < 0 )
|
|
||||||
{
|
|
||||||
// We hit the ceiling.
|
|
||||||
env.Phase++;
|
|
||||||
env.Value = ADSR_MAX_VOL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2: // decay
|
|
||||||
{
|
|
||||||
u32 off = InvExpOffsets[(env.Value>>28)&7];
|
|
||||||
env.Value-=PsxRates[((env.Dr^0x1f)*4)-0x18+off+32];
|
|
||||||
|
|
||||||
// calculate sustain level by mirroring the bits
|
|
||||||
// of the sustain var into the lower bits as we shift up
|
|
||||||
// (total shift, 27 bits)
|
|
||||||
|
|
||||||
//s32 suslev8 = (env.Sl << 4) | env.Sl;
|
|
||||||
//s32 suslev = (suslev8 << 8) | suslev8; // brings us to 16 bits!
|
|
||||||
//suslev = (suslev << 8) | suslev8; // 24 bits!
|
|
||||||
|
|
||||||
s32 suslev = 0x7fffffff / (0x10 - env.Sl);
|
|
||||||
|
|
||||||
if( env.Value <= suslev )
|
|
||||||
{
|
|
||||||
if (env.Value < 0)
|
|
||||||
env.Value = 0;
|
|
||||||
env.Phase++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3: // sustain
|
|
||||||
{
|
|
||||||
// 0x7f disables sustain (infinite sustain)
|
|
||||||
if( env.Sr == 0x7f ) return;
|
|
||||||
|
|
||||||
if (env.Sm&2) // decreasing
|
|
||||||
{
|
|
||||||
if (env.Sm&4) // exponential
|
|
||||||
{
|
|
||||||
u32 off = InvExpOffsets[(env.Value>>28)&7];
|
|
||||||
env.Value-=PsxRates[(env.Sr^0x7f)-0x1b+off+32];
|
|
||||||
}
|
|
||||||
else // linear
|
|
||||||
{
|
|
||||||
env.Value-=PsxRates[(env.Sr^0x7f)-0xf+32];
|
|
||||||
//env.Value -= GetLinearSrAr( env.Sr );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( env.Value <= 0 )
|
|
||||||
{
|
|
||||||
env.Value = 0;
|
|
||||||
env.Phase++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // increasing
|
|
||||||
{
|
|
||||||
if( (env.Sm&4) && (env.Value>=0x60000000) )
|
|
||||||
env.Value+=PsxRates[(env.Sr^0x7f)-0x18+32];
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// linear / Pseudo below 75% (they're the same)
|
|
||||||
env.Value+=PsxRates[(env.Sr^0x7f)-0x10+32];
|
|
||||||
//env.Value += GetLinearSrAr( env.Sr );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( env.Value < 0 )
|
|
||||||
{
|
|
||||||
env.Value = ADSR_MAX_VOL;
|
|
||||||
env.Phase++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4: // sustain end
|
|
||||||
env.Value = (env.Sm&2) ? 0 : ADSR_MAX_VOL;
|
|
||||||
if(env.Value==0)
|
|
||||||
env.Phase=6;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 5: // release
|
|
||||||
|
|
||||||
if (env.Rm) // exponential
|
|
||||||
{
|
|
||||||
u32 off=InvExpOffsets[(env.Value>>28)&7];
|
|
||||||
env.Value-=PsxRates[((env.Rr^0x1f)*4)-0x18+off+32];
|
|
||||||
}
|
|
||||||
else // linear
|
|
||||||
{
|
|
||||||
//env.Value-=PsxRates[((env.Rr^0x1f)*4)-0xc+32];
|
|
||||||
if( env.Rr != 0x1f )
|
|
||||||
env.Value -= (1 << (0x1f-env.Rr));
|
|
||||||
}
|
|
||||||
|
|
||||||
if( env.Value <= 0 )
|
|
||||||
{
|
|
||||||
env.Value=0;
|
|
||||||
env.Phase++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 6: // release end
|
|
||||||
env.Value=0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
jNO_DEFAULT
|
|
||||||
}
|
|
||||||
|
|
||||||
if (env.Phase==6) {
|
|
||||||
#ifndef PUBLIC
|
|
||||||
if(MsgVoiceOff()) ConLog(" * SPU2: Voice Off by ADSR: %d \n", voice);
|
|
||||||
DebugCores[core].Voices[voice].lastStopReason = 2;
|
|
||||||
#endif
|
|
||||||
VoiceStop(core,voice);
|
|
||||||
Cores[core].Regs.ENDX|=(1<<voice);
|
|
||||||
env.Phase=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// //
|
// //
|
||||||
|
@ -497,27 +314,41 @@ static void __forceinline UpdatePitch( V_Voice& vc )
|
||||||
vc.SP+=pitch;
|
vc.SP+=pitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static __forceinline void CalculateADSR( V_Core& thiscore, V_Voice& vc )
|
||||||
|
{
|
||||||
|
if( vc.ADSR.Phase==0 )
|
||||||
|
{
|
||||||
|
vc.ADSR.Value = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !vc.ADSR.Calculate() )
|
||||||
|
{
|
||||||
|
if( IsDevBuild )
|
||||||
|
{
|
||||||
|
if(MsgVoiceOff()) ConLog(" * SPU2: Voice Off by ADSR: %d \n", voice);
|
||||||
|
DebugCores[core].Voices[voice].lastStopReason = 2;
|
||||||
|
}
|
||||||
|
vc.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
jASSUME( vc.ADSR.Value >= 0 ); // ADSR should never be negative...
|
||||||
|
}
|
||||||
|
|
||||||
// Returns a 16 bit result in Value.
|
// Returns a 16 bit result in Value.
|
||||||
static void __forceinline GetVoiceValues_Linear(V_Core& thiscore, V_Voice& vc, s32& Value)
|
static void __forceinline GetVoiceValues_Linear(V_Core& thiscore, V_Voice& vc, s32& Value)
|
||||||
{
|
{
|
||||||
while( vc.SP > 0 )
|
while( vc.SP > 0 )
|
||||||
{
|
{
|
||||||
vc.PV2=vc.PV1;
|
vc.PV2 = vc.PV1;
|
||||||
|
|
||||||
GetNextDataBuffered( thiscore, vc, vc.PV1 );
|
GetNextDataBuffered( thiscore, vc, vc.PV1 );
|
||||||
|
|
||||||
vc.SP-=4096;
|
vc.SP -= 4096;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( vc.ADSR.Phase==0 )
|
CalculateADSR( thiscore, vc );
|
||||||
{
|
|
||||||
Value = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CalculateADSR( vc );
|
|
||||||
|
|
||||||
jASSUME( vc.ADSR.Value >= 0 ); // ADSR should never be negative...
|
|
||||||
|
|
||||||
// Note! It's very important that ADSR stay as accurate as possible. By the way
|
// 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
|
// it is used, various sound effects can end prematurely if we truncate more than
|
||||||
|
@ -549,15 +380,7 @@ static void __forceinline GetVoiceValues_Cubic(V_Core& thiscore, V_Voice& vc, s3
|
||||||
vc.SP-=4096;
|
vc.SP-=4096;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( vc.ADSR.Phase==0 )
|
CalculateADSR( thiscore, vc );
|
||||||
{
|
|
||||||
Value = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CalculateADSR( vc );
|
|
||||||
|
|
||||||
jASSUME( vc.ADSR.Value >= 0 ); // ADSR should never be negative...
|
|
||||||
|
|
||||||
s32 z0 = vc.PV3 - vc.PV4 + vc.PV1 - vc.PV2;
|
s32 z0 = vc.PV3 - vc.PV4 + vc.PV1 - vc.PV2;
|
||||||
s32 z1 = (vc.PV4 - vc.PV3 - z0);
|
s32 z1 = (vc.PV4 - vc.PV3 - z0);
|
||||||
|
@ -591,7 +414,7 @@ static void __forceinline __fastcall GetNoiseValues(V_Core& thiscore, V_Voice& v
|
||||||
// like GetVoiceValues can. Better assert just in case though..
|
// like GetVoiceValues can. Better assert just in case though..
|
||||||
jASSUME( vc.ADSR.Phase != 0 );
|
jASSUME( vc.ADSR.Phase != 0 );
|
||||||
|
|
||||||
CalculateADSR( vc );
|
CalculateADSR( thiscore, vc );
|
||||||
|
|
||||||
// Yup, ADSR applies even to noise sources...
|
// Yup, ADSR applies even to noise sources...
|
||||||
Data = MulShr32( Data, vc.ADSR.Value );
|
Data = MulShr32( Data, vc.ADSR.Value );
|
||||||
|
@ -649,12 +472,13 @@ void __fastcall ReadInput(V_Core& thiscore, s32& PDataL,s32& PDataR)
|
||||||
{
|
{
|
||||||
FileLog("[%10d] AutoDMA%c block end.\n",Cycles, (core==0)?'4':'7');
|
FileLog("[%10d] AutoDMA%c block end.\n",Cycles, (core==0)?'4':'7');
|
||||||
|
|
||||||
#ifndef PUBLIC
|
if( IsDevBuild )
|
||||||
if(thiscore.InputDataLeft>0)
|
|
||||||
{
|
{
|
||||||
if(MsgAutoDMA()) ConLog("WARNING: adma buffer didn't finish with a whole block!!\n");
|
if(thiscore.InputDataLeft>0)
|
||||||
|
{
|
||||||
|
if(MsgAutoDMA()) ConLog("WARNING: adma buffer didn't finish with a whole block!!\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
thiscore.InputDataLeft=0;
|
thiscore.InputDataLeft=0;
|
||||||
thiscore.DMAICounter=1;
|
thiscore.DMAICounter=1;
|
||||||
}
|
}
|
||||||
|
@ -689,12 +513,13 @@ void __fastcall ReadInput(V_Core& thiscore, s32& PDataL,s32& PDataR)
|
||||||
{
|
{
|
||||||
FileLog("[%10d] Spdif AutoDMA%c block end.\n",Cycles, (core==0)?'4':'7');
|
FileLog("[%10d] Spdif AutoDMA%c block end.\n",Cycles, (core==0)?'4':'7');
|
||||||
|
|
||||||
#ifndef PUBLIC
|
if( IsDevBuild )
|
||||||
if(thiscore.InputDataLeft>0)
|
|
||||||
{
|
{
|
||||||
if(MsgAutoDMA()) ConLog("WARNING: adma buffer didn't finish with a whole block!!\n");
|
if(thiscore.InputDataLeft>0)
|
||||||
|
{
|
||||||
|
if(MsgAutoDMA()) ConLog("WARNING: adma buffer didn't finish with a whole block!!\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
thiscore.InputDataLeft=0;
|
thiscore.InputDataLeft=0;
|
||||||
thiscore.DMAICounter=1;
|
thiscore.DMAICounter=1;
|
||||||
}
|
}
|
||||||
|
@ -741,15 +566,17 @@ void __fastcall ReadInput(V_Core& thiscore, s32& PDataL,s32& PDataR)
|
||||||
{
|
{
|
||||||
thiscore.AutoDMACtrl |= ~3;
|
thiscore.AutoDMACtrl |= ~3;
|
||||||
|
|
||||||
#ifndef PUBLIC
|
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");
|
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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
thiscore.InputDataLeft=0;
|
thiscore.InputDataLeft = 0;
|
||||||
thiscore.DMAICounter=1;
|
thiscore.DMAICounter = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
thiscore.InputPos&=0x1ff;
|
thiscore.InputPos&=0x1ff;
|
||||||
|
@ -795,57 +622,6 @@ static void __forceinline __fastcall ReadInputPV(V_Core& thiscore, s32& ValL,s32
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// //
|
// //
|
||||||
|
|
||||||
#define VOLFLAG_REVERSE_PHASE (1ul<<0)
|
|
||||||
#define VOLFLAG_DECREMENT (1ul<<1)
|
|
||||||
#define VOLFLAG_EXPONENTIAL (1ul<<2)
|
|
||||||
#define VOLFLAG_SLIDE_ENABLE (1ul<<3)
|
|
||||||
|
|
||||||
static void __fastcall UpdateVolume(V_Volume& Vol)
|
|
||||||
{
|
|
||||||
// Volume slides use the same basic logic as ADSR, but simplified (single-stage
|
|
||||||
// instead of multi-stage)
|
|
||||||
|
|
||||||
if (Vol.Mode & VOLFLAG_DECREMENT)
|
|
||||||
{
|
|
||||||
// Decrement
|
|
||||||
|
|
||||||
if(Vol.Mode & VOLFLAG_EXPONENTIAL)
|
|
||||||
{
|
|
||||||
u32 off = InvExpOffsets[(Vol.Value>>28)&7];
|
|
||||||
Vol.Value -= PsxRates[(Vol.Increment^0x7f)-0x1b+off+32];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
Vol.Value -= Vol.Increment;
|
|
||||||
|
|
||||||
if (Vol.Value < 0)
|
|
||||||
{
|
|
||||||
Vol.Value = 0;
|
|
||||||
Vol.Mode = 0; // disable slide
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Increment
|
|
||||||
// Pseudo-exponential increments, as done by the SPU2 (really!)
|
|
||||||
// Above 75% slides slow, below 75% slides fast. It's exponential, pseudo'ly speaking.
|
|
||||||
|
|
||||||
if( (Vol.Mode & VOLFLAG_EXPONENTIAL) && (Vol.Value>=0x60000000))
|
|
||||||
Vol.Value += PsxRates[(Vol.Increment^0x7f)-0x18+32];
|
|
||||||
else
|
|
||||||
Vol.Value += Vol.Increment;
|
|
||||||
|
|
||||||
if( Vol.Value < 0 ) // wrapped around the "top"?
|
|
||||||
{
|
|
||||||
Vol.Value = 0x7fffffff;
|
|
||||||
Vol.Mode = 0; // disable slide
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// //
|
|
||||||
|
|
||||||
// writes a signed value to the SPU2 ram
|
// writes a signed value to the SPU2 ram
|
||||||
// Performs no cache invalidation -- use only for dynamic memory ranges
|
// Performs no cache invalidation -- use only for dynamic memory ranges
|
||||||
// of the SPU2 (between 0x0000 and SPU2_DYN_MEMLINE)
|
// of the SPU2 (between 0x0000 and SPU2_DYN_MEMLINE)
|
||||||
|
@ -869,8 +645,8 @@ static __forceinline void MixVoice( V_Core& thiscore, V_Voice& vc, s32& VValL, s
|
||||||
// Most games don't use much volume slide effects. So only call the UpdateVolume
|
// 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...
|
// methods when needed by checking the flag outside the method here...
|
||||||
|
|
||||||
if( vc.VolumeL.Mode & VOLFLAG_SLIDE_ENABLE ) UpdateVolume( vc.VolumeL );
|
vc.VolumeL.Update();
|
||||||
if( vc.VolumeR.Mode & VOLFLAG_SLIDE_ENABLE ) UpdateVolume( vc.VolumeR );
|
vc.VolumeR.Update();
|
||||||
|
|
||||||
if( vc.ADSR.Phase > 0 )
|
if( vc.ADSR.Phase > 0 )
|
||||||
{
|
{
|
||||||
|
@ -889,9 +665,8 @@ static __forceinline void MixVoice( V_Core& thiscore, V_Voice& vc, s32& VValL, s
|
||||||
// Record the output (used for modulation effects)
|
// Record the output (used for modulation effects)
|
||||||
vc.OutX = Value;
|
vc.OutX = Value;
|
||||||
|
|
||||||
#ifndef PUBLIC
|
if( IsDevBuild )
|
||||||
DebugCores[core].Voices[voice].displayPeak = max(DebugCores[core].Voices[voice].displayPeak,abs(Value));
|
DebugCores[core].Voices[voice].displayPeak = max(DebugCores[core].Voices[voice].displayPeak,abs(Value));
|
||||||
#endif
|
|
||||||
|
|
||||||
// TODO : Implement this using high-def MulShr32.
|
// TODO : Implement this using high-def MulShr32.
|
||||||
// vc.VolumeL/R are 15 bits. Value should be 32 bits (but is currently 16)
|
// vc.VolumeL/R are 15 bits. Value should be 32 bits (but is currently 16)
|
||||||
|
@ -1017,8 +792,8 @@ static void __fastcall MixCore(s32& OutL, s32& OutR, s32 ExtL, s32 ExtR)
|
||||||
|
|
||||||
// Apply Master Volume. The core will need this when the function returns.
|
// Apply Master Volume. The core will need this when the function returns.
|
||||||
|
|
||||||
if( thiscore.MasterL.Mode & VOLFLAG_SLIDE_ENABLE ) UpdateVolume(thiscore.MasterL);
|
thiscore.MasterL.Update();
|
||||||
if( thiscore.MasterR.Mode & VOLFLAG_SLIDE_ENABLE ) UpdateVolume(thiscore.MasterR);
|
thiscore.MasterR.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
// used to throttle the output rate of cache stat reports
|
// used to throttle the output rate of cache stat reports
|
||||||
|
@ -1107,21 +882,22 @@ void Mix()
|
||||||
OutPos++;
|
OutPos++;
|
||||||
if (OutPos>=0x200) OutPos=0;
|
if (OutPos>=0x200) OutPos=0;
|
||||||
|
|
||||||
#ifndef PUBLIC
|
if( IsDevBuild )
|
||||||
p_cachestat_counter++;
|
|
||||||
if(p_cachestat_counter > (48000*10) )
|
|
||||||
{
|
{
|
||||||
p_cachestat_counter = 0;
|
p_cachestat_counter++;
|
||||||
if( MsgCache() ) ConLog( " * SPU2 > CacheStats > Hits: %d Misses: %d Ignores: %d\n",
|
if(p_cachestat_counter > (48000*10) )
|
||||||
g_counter_cache_hits,
|
{
|
||||||
g_counter_cache_misses,
|
p_cachestat_counter = 0;
|
||||||
g_counter_cache_ignores );
|
if( MsgCache() ) ConLog( " * SPU2 > CacheStats > Hits: %d Misses: %d Ignores: %d\n",
|
||||||
|
g_counter_cache_hits,
|
||||||
|
g_counter_cache_misses,
|
||||||
|
g_counter_cache_ignores );
|
||||||
|
|
||||||
g_counter_cache_hits =
|
g_counter_cache_hits =
|
||||||
g_counter_cache_misses =
|
g_counter_cache_misses =
|
||||||
g_counter_cache_ignores = 0;
|
g_counter_cache_ignores = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -30,7 +30,8 @@ __forceinline void RegLog(int level, char *RName,u32 mem,u32 core,u16 value)
|
||||||
|
|
||||||
void SPU2writeLog(u32 rmem, u16 value)
|
void SPU2writeLog(u32 rmem, u16 value)
|
||||||
{
|
{
|
||||||
#ifndef PUBLIC
|
if( !IsDevBuild ) return;
|
||||||
|
|
||||||
u32 vx=0, vc=0, core=0, omem, mem;
|
u32 vx=0, vc=0, core=0, omem, mem;
|
||||||
omem=mem=rmem & 0x7FF; //FFFF;
|
omem=mem=rmem & 0x7FF; //FFFF;
|
||||||
if (mem & 0x400) { omem^=0x400; core=1; }
|
if (mem & 0x400) { omem^=0x400; core=1; }
|
||||||
|
@ -247,6 +248,5 @@ void SPU2writeLog(u32 rmem, u16 value)
|
||||||
RegLog(2,"UNKNOWN",rmem,core,value); spu2Ru16(mem) = value;
|
RegLog(2,"UNKNOWN",rmem,core,value); spu2Ru16(mem) = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,8 @@
|
||||||
|
|
||||||
#include "spu2.h"
|
#include "spu2.h"
|
||||||
|
|
||||||
//static LPF_data lowpass_left( 11000, SampleRate );
|
static LPF_data lowpass_left( 11000, SampleRate );
|
||||||
//static LPF_data lowpass_right( 11000, SampleRate );
|
static LPF_data lowpass_right( 11000, SampleRate );
|
||||||
|
|
||||||
static s32 EffectsBufferIndexer( V_Core& thiscore, s32 offset )
|
static s32 EffectsBufferIndexer( V_Core& thiscore, s32 offset )
|
||||||
{
|
{
|
||||||
|
@ -34,14 +34,10 @@ static s32 EffectsBufferIndexer( V_Core& thiscore, s32 offset )
|
||||||
if( pos > thiscore.EffectsEndA )
|
if( pos > thiscore.EffectsEndA )
|
||||||
{
|
{
|
||||||
pos = thiscore.EffectsStartA + ((thiscore.ReverbX + offset) % (u32)thiscore.EffectsBufferSize);
|
pos = thiscore.EffectsStartA + ((thiscore.ReverbX + offset) % (u32)thiscore.EffectsBufferSize);
|
||||||
//pos -= thiscore.EffectsEndA+1;
|
|
||||||
//pos += thiscore.EffectsStartA;
|
|
||||||
}
|
}
|
||||||
else if( pos < thiscore.EffectsStartA )
|
else if( pos < thiscore.EffectsStartA )
|
||||||
{
|
{
|
||||||
pos = thiscore.EffectsEndA+1 - ((thiscore.ReverbX + offset) % (u32)thiscore.EffectsBufferSize );
|
pos = thiscore.EffectsEndA+1 - ((thiscore.ReverbX + offset) % (u32)thiscore.EffectsBufferSize );
|
||||||
//pos -= thiscore.EffectsStartA;
|
|
||||||
//pos += thiscore.EffectsEndA+1;
|
|
||||||
}
|
}
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
@ -176,7 +172,12 @@ void DoReverb( V_Core& thiscore, s32& OutL, s32& OutR, s32 InL, s32 InR)
|
||||||
_spu2mem[mix_dest_b0] = clamp_mix( (MulShr32(thiscore.Revb.FB_ALPHA<<14, ACC0) - fb_xor_a0 - ((_spu2mem[fb_src_b0] * thiscore.Revb.FB_X)>>2)) >> 14 );
|
_spu2mem[mix_dest_b0] = clamp_mix( (MulShr32(thiscore.Revb.FB_ALPHA<<14, ACC0) - fb_xor_a0 - ((_spu2mem[fb_src_b0] * thiscore.Revb.FB_X)>>2)) >> 14 );
|
||||||
_spu2mem[mix_dest_b1] = clamp_mix( (MulShr32(thiscore.Revb.FB_ALPHA<<14, ACC1) - fb_xor_a1 - ((_spu2mem[fb_src_b1] * thiscore.Revb.FB_X)>>2)) >> 14 );
|
_spu2mem[mix_dest_b1] = clamp_mix( (MulShr32(thiscore.Revb.FB_ALPHA<<14, ACC1) - fb_xor_a1 - ((_spu2mem[fb_src_b1] * thiscore.Revb.FB_X)>>2)) >> 14 );
|
||||||
|
|
||||||
OutL = thiscore.LastEffectL = clamp_mix(_spu2mem[mix_dest_a0] + _spu2mem[mix_dest_b0]);
|
thiscore.LastEffectL = clamp_mix(_spu2mem[mix_dest_a0] + _spu2mem[mix_dest_b0]);
|
||||||
OutR = thiscore.LastEffectR = clamp_mix(_spu2mem[mix_dest_a1] + _spu2mem[mix_dest_b1]);
|
thiscore.LastEffectR = clamp_mix(_spu2mem[mix_dest_a1] + _spu2mem[mix_dest_b1]);
|
||||||
|
|
||||||
|
//OutL = thiscore.LastEffectL;
|
||||||
|
//OutR = thiscore.LastEffectR;
|
||||||
|
OutL = (s32)(lowpass_left.sample( thiscore.LastEffectL / 32768.0 ) * 32768.0);
|
||||||
|
OutR = (s32)(lowpass_right.sample( thiscore.LastEffectR / 32768.0 ) * 32768.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,6 @@ s32 __fastcall FreezeIt( SPU2freezeData& spud )
|
||||||
spud.OutPos = OutPos;
|
spud.OutPos = OutPos;
|
||||||
spud.InputPos = InputPos;
|
spud.InputPos = InputPos;
|
||||||
spud.Cycles = Cycles;
|
spud.Cycles = Cycles;
|
||||||
spud.uTicks = uTicks;
|
|
||||||
spud.PlayMode = PlayMode;
|
spud.PlayMode = PlayMode;
|
||||||
|
|
||||||
// Save our cache:
|
// Save our cache:
|
||||||
|
@ -156,7 +155,6 @@ s32 __fastcall ThawIt( SPU2freezeData& spud )
|
||||||
OutPos = spud.OutPos;
|
OutPos = spud.OutPos;
|
||||||
InputPos = spud.InputPos;
|
InputPos = spud.InputPos;
|
||||||
Cycles = spud.Cycles;
|
Cycles = spud.Cycles;
|
||||||
uTicks = spud.uTicks;
|
|
||||||
PlayMode = spud.PlayMode;
|
PlayMode = spud.PlayMode;
|
||||||
|
|
||||||
// Load the ADPCM cache:
|
// Load the ADPCM cache:
|
||||||
|
|
|
@ -51,9 +51,7 @@ u8 callirq;
|
||||||
HANDLE hThreadFunc;
|
HANDLE hThreadFunc;
|
||||||
u32 ThreadFuncID;
|
u32 ThreadFuncID;
|
||||||
|
|
||||||
#ifndef PUBLIC
|
|
||||||
V_CoreDebug DebugCores[2];
|
V_CoreDebug DebugCores[2];
|
||||||
#endif
|
|
||||||
V_Core Cores[2];
|
V_Core Cores[2];
|
||||||
V_SPDIF Spdif;
|
V_SPDIF Spdif;
|
||||||
|
|
||||||
|
@ -206,6 +204,44 @@ void V_Core::UpdateEffectsBufferSize()
|
||||||
EffectsBufferSize = EffectsEndA - EffectsStartA + 1;
|
EffectsBufferSize = EffectsEndA - EffectsStartA + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void V_Voice::Start()
|
||||||
|
{
|
||||||
|
if((Cycles-PlayCycle)>=4)
|
||||||
|
{
|
||||||
|
if(StartA&7)
|
||||||
|
{
|
||||||
|
fprintf( stderr, " *** Misaligned StartA %05x!\n",StartA);
|
||||||
|
StartA=(StartA+0xFFFF8)+0x8;
|
||||||
|
}
|
||||||
|
|
||||||
|
ADSR.Releasing=false;
|
||||||
|
ADSR.Value=1;
|
||||||
|
ADSR.Phase=1;
|
||||||
|
PlayCycle=Cycles;
|
||||||
|
SCurrent=28;
|
||||||
|
LoopMode=0;
|
||||||
|
LoopFlags=0;
|
||||||
|
LoopStartA=StartA;
|
||||||
|
NextA=StartA;
|
||||||
|
Prev1=0;
|
||||||
|
Prev2=0;
|
||||||
|
|
||||||
|
PV1=PV2=0;
|
||||||
|
PV3=PV4=0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf(" *** KeyOn after less than 4 T disregarded.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void V_Voice::Stop()
|
||||||
|
{
|
||||||
|
ADSR.Value = 0;
|
||||||
|
ADSR.Phase = 0;
|
||||||
|
//Cores[core].Regs.ENDX|=(1<<vc);
|
||||||
|
}
|
||||||
|
|
||||||
static const int TickInterval = 768;
|
static const int TickInterval = 768;
|
||||||
static const int SanityInterval = 4800;
|
static const int SanityInterval = 4800;
|
||||||
|
|
||||||
|
@ -368,16 +404,16 @@ void SPU_ps1_write(u32 mem, u16 value)
|
||||||
case 2: Cores[0].Voices[voice].Pitch=value; break;
|
case 2: Cores[0].Voices[voice].Pitch=value; break;
|
||||||
case 3: Cores[0].Voices[voice].StartA=(u32)value<<8; break;
|
case 3: Cores[0].Voices[voice].StartA=(u32)value<<8; break;
|
||||||
case 4: // ADSR1 (Envelope)
|
case 4: // ADSR1 (Envelope)
|
||||||
Cores[0].Voices[voice].ADSR.Am=(value & 0x8000)>>15;
|
Cores[0].Voices[voice].ADSR.AttackMode=(value & 0x8000)>>15;
|
||||||
Cores[0].Voices[voice].ADSR.Ar=(value & 0x7F00)>>8;
|
Cores[0].Voices[voice].ADSR.AttackRate=(value & 0x7F00)>>8;
|
||||||
Cores[0].Voices[voice].ADSR.Dr=(value & 0xF0)>>4;
|
Cores[0].Voices[voice].ADSR.DecayRate=(value & 0xF0)>>4;
|
||||||
Cores[0].Voices[voice].ADSR.Sl=(value & 0xF);
|
Cores[0].Voices[voice].ADSR.SustainLevel=(value & 0xF);
|
||||||
Cores[0].Voices[voice].ADSR.Reg_ADSR1 = value; break;
|
Cores[0].Voices[voice].ADSR.Reg_ADSR1 = value; break;
|
||||||
case 5: // ADSR2 (Envelope)
|
case 5: // ADSR2 (Envelope)
|
||||||
Cores[0].Voices[voice].ADSR.Sm=(value & 0xE000)>>13;
|
Cores[0].Voices[voice].ADSR.SustainMode=(value & 0xE000)>>13;
|
||||||
Cores[0].Voices[voice].ADSR.Sr=(value & 0x1FC0)>>6;
|
Cores[0].Voices[voice].ADSR.SustainRate=(value & 0x1FC0)>>6;
|
||||||
Cores[0].Voices[voice].ADSR.Rm=(value & 0x20)>>5;
|
Cores[0].Voices[voice].ADSR.ReleaseMode=(value & 0x20)>>5;
|
||||||
Cores[0].Voices[voice].ADSR.Rr=(value & 0x1F);
|
Cores[0].Voices[voice].ADSR.ReleaseRate=(value & 0x1F);
|
||||||
Cores[0].Voices[voice].ADSR.Reg_ADSR2 = value; break;
|
Cores[0].Voices[voice].ADSR.Reg_ADSR2 = value; break;
|
||||||
case 6:
|
case 6:
|
||||||
Cores[0].Voices[voice].ADSR.Value = ((s32)value<<16) | value;
|
Cores[0].Voices[voice].ADSR.Value = ((s32)value<<16) | value;
|
||||||
|
@ -614,16 +650,16 @@ __forceinline void SPU2_FastWrite( u32 rmem, u16 value )
|
||||||
|
|
||||||
case 2: thisvoice.Pitch=value; break;
|
case 2: thisvoice.Pitch=value; break;
|
||||||
case 3: // ADSR1 (Envelope)
|
case 3: // ADSR1 (Envelope)
|
||||||
thisvoice.ADSR.Am = (value & 0x8000)>>15;
|
thisvoice.ADSR.AttackMode = (value & 0x8000)>>15;
|
||||||
thisvoice.ADSR.Ar = (value & 0x7F00)>>8;
|
thisvoice.ADSR.AttackRate = (value & 0x7F00)>>8;
|
||||||
thisvoice.ADSR.Dr = (value & 0xF0)>>4;
|
thisvoice.ADSR.DecayRate = (value & 0xF0)>>4;
|
||||||
thisvoice.ADSR.Sl = (value & 0xF);
|
thisvoice.ADSR.SustainLevel = (value & 0xF);
|
||||||
thisvoice.ADSR.Reg_ADSR1 = value; break;
|
thisvoice.ADSR.Reg_ADSR1 = value; break;
|
||||||
case 4: // ADSR2 (Envelope)
|
case 4: // ADSR2 (Envelope)
|
||||||
thisvoice.ADSR.Sm = (value & 0xE000)>>13;
|
thisvoice.ADSR.SustainMode = (value & 0xE000)>>13;
|
||||||
thisvoice.ADSR.Sr = (value & 0x1FC0)>>6;
|
thisvoice.ADSR.SustainRate = (value & 0x1FC0)>>6;
|
||||||
thisvoice.ADSR.Rm = (value & 0x20)>>5;
|
thisvoice.ADSR.ReleaseMode = (value & 0x20)>>5;
|
||||||
thisvoice.ADSR.Rr = (value & 0x1F);
|
thisvoice.ADSR.ReleaseRate = (value & 0x1F);
|
||||||
thisvoice.ADSR.Reg_ADSR2 = value; break;
|
thisvoice.ADSR.Reg_ADSR2 = value; break;
|
||||||
case 5:
|
case 5:
|
||||||
// [Air] : Mysterious ADSR set code. Too bad none of my games ever use it.
|
// [Air] : Mysterious ADSR set code. Too bad none of my games ever use it.
|
||||||
|
@ -646,24 +682,35 @@ __forceinline void SPU2_FastWrite( u32 rmem, u16 value )
|
||||||
|
|
||||||
switch (address)
|
switch (address)
|
||||||
{
|
{
|
||||||
case 0: thisvoice.StartA = ((value & 0x0F) << 16) | (thisvoice.StartA & 0xFFF8);
|
case 0:
|
||||||
#ifndef PUBLIC
|
thisvoice.StartA = ((value & 0x0F) << 16) | (thisvoice.StartA & 0xFFF8);
|
||||||
|
if( IsDevBuild )
|
||||||
DebugCores[core].Voices[voice].lastSetStartA = thisvoice.StartA;
|
DebugCores[core].Voices[voice].lastSetStartA = thisvoice.StartA;
|
||||||
#endif
|
break;
|
||||||
break;
|
|
||||||
case 1: thisvoice.StartA = (thisvoice.StartA & 0x0F0000) | (value & 0xFFF8);
|
case 1:
|
||||||
#ifndef PUBLIC
|
thisvoice.StartA = (thisvoice.StartA & 0x0F0000) | (value & 0xFFF8);
|
||||||
|
if( IsDevBuild )
|
||||||
DebugCores[core].Voices[voice].lastSetStartA = thisvoice.StartA;
|
DebugCores[core].Voices[voice].lastSetStartA = thisvoice.StartA;
|
||||||
#endif
|
break;
|
||||||
break;
|
|
||||||
case 2: thisvoice.LoopStartA = ((value & 0x0F) << 16) | (thisvoice.LoopStartA & 0xFFF8);
|
case 2:
|
||||||
thisvoice.LoopMode = 3; break;
|
thisvoice.LoopStartA = ((value & 0x0F) << 16) | (thisvoice.LoopStartA & 0xFFF8);
|
||||||
case 3: thisvoice.LoopStartA = (thisvoice.LoopStartA & 0x0F0000) | (value & 0xFFF8);break;
|
thisvoice.LoopMode = 3;
|
||||||
thisvoice.LoopMode = 3; break;
|
break;
|
||||||
case 4: thisvoice.NextA = ((value & 0x0F) << 16) | (thisvoice.NextA & 0xFFF8);
|
|
||||||
break;
|
case 3:
|
||||||
case 5: thisvoice.NextA = (thisvoice.NextA & 0x0F0000) | (value & 0xFFF8);
|
thisvoice.LoopStartA = (thisvoice.LoopStartA & 0x0F0000) | (value & 0xFFF8);
|
||||||
break;
|
thisvoice.LoopMode = 3;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
thisvoice.NextA = ((value & 0x0F) << 16) | (thisvoice.NextA & 0xFFF8);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
thisvoice.NextA = (thisvoice.NextA & 0x0F0000) | (value & 0xFFF8);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if((mem>=0x07C0) && (mem<0x07CE))
|
else if((mem>=0x07C0) && (mem<0x07CE))
|
||||||
|
@ -930,60 +977,6 @@ __forceinline void SPU2_FastWrite( u32 rmem, u16 value )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void VoiceStart(int core,int vc)
|
|
||||||
{
|
|
||||||
if((Cycles-Cores[core].Voices[vc].PlayCycle)>=4)
|
|
||||||
{
|
|
||||||
if(Cores[core].Voices[vc].StartA&7)
|
|
||||||
{
|
|
||||||
fprintf( stderr, " *** Misaligned StartA %05x!\n",Cores[core].Voices[vc].StartA);
|
|
||||||
Cores[core].Voices[vc].StartA=(Cores[core].Voices[vc].StartA+0xFFFF8)+0x8;
|
|
||||||
}
|
|
||||||
|
|
||||||
Cores[core].Voices[vc].ADSR.Releasing=false;
|
|
||||||
Cores[core].Voices[vc].ADSR.Value=1;
|
|
||||||
Cores[core].Voices[vc].ADSR.Phase=1;
|
|
||||||
Cores[core].Voices[vc].PlayCycle=Cycles;
|
|
||||||
Cores[core].Voices[vc].SCurrent=28;
|
|
||||||
Cores[core].Voices[vc].LoopMode=0;
|
|
||||||
Cores[core].Voices[vc].LoopFlags=0;
|
|
||||||
Cores[core].Voices[vc].LoopStartA=Cores[core].Voices[vc].StartA;
|
|
||||||
Cores[core].Voices[vc].NextA=Cores[core].Voices[vc].StartA;
|
|
||||||
Cores[core].Voices[vc].Prev1=0;
|
|
||||||
Cores[core].Voices[vc].Prev2=0;
|
|
||||||
|
|
||||||
Cores[core].Voices[vc].PV1=Cores[core].Voices[vc].PV2=0;
|
|
||||||
Cores[core].Voices[vc].PV3=Cores[core].Voices[vc].PV4=0;
|
|
||||||
|
|
||||||
Cores[core].Regs.ENDX&=~(1<<vc);
|
|
||||||
|
|
||||||
#ifndef PUBLIC
|
|
||||||
DebugCores[core].Voices[vc].FirstBlock=1;
|
|
||||||
|
|
||||||
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,Cores[core].Voices[vc].StartA,
|
|
||||||
(Cores[core].Voices[vc].DryL)?"+":"-",(Cores[core].Voices[vc].DryR)?"+":"-",
|
|
||||||
(Cores[core].Voices[vc].WetL)?"+":"-",(Cores[core].Voices[vc].WetR)?"+":"-",
|
|
||||||
*(u8*)GetMemPtr(Cores[core].Voices[vc].StartA),*(u8 *)GetMemPtr((Cores[core].Voices[vc].StartA)+1),
|
|
||||||
Cores[core].Voices[vc].Pitch,
|
|
||||||
Cores[core].Voices[vc].VolumeL.Value,Cores[core].Voices[vc].VolumeR.Value,
|
|
||||||
Cores[core].Voices[vc].ADSR.Reg_ADSR1,Cores[core].Voices[vc].ADSR.Reg_ADSR2);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf(" *** KeyOn after less than 4 T disregarded.\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoiceStop(int core,int vc)
|
|
||||||
{
|
|
||||||
Cores[core].Voices[vc].ADSR.Value=0;
|
|
||||||
Cores[core].Voices[vc].ADSR.Phase=0;
|
|
||||||
|
|
||||||
//Cores[core].Regs.ENDX|=(1<<vc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StartVoices(int core, u32 value)
|
void StartVoices(int core, u32 value)
|
||||||
{
|
{
|
||||||
// Optimization: Games like to write zero to the KeyOn reg a lot, so shortcut
|
// Optimization: Games like to write zero to the KeyOn reg a lot, so shortcut
|
||||||
|
@ -996,7 +989,24 @@ void StartVoices(int core, u32 value)
|
||||||
for( u8 vc=0; vc<24; vc++ )
|
for( u8 vc=0; vc<24; vc++ )
|
||||||
{
|
{
|
||||||
if ((value>>vc) & 1)
|
if ((value>>vc) & 1)
|
||||||
VoiceStart(core,vc);
|
{
|
||||||
|
Cores[core].Voices[vc].Start();
|
||||||
|
Cores[core].Regs.ENDX &= ~( 1 << vc );
|
||||||
|
|
||||||
|
if( IsDevBuild )
|
||||||
|
{
|
||||||
|
V_Voice& thisvc( Cores[core].Voices[vc] );
|
||||||
|
|
||||||
|
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,
|
||||||
|
(thisvc.DryL)?"+":"-",(thisvc.DryR)?"+":"-",
|
||||||
|
(thisvc.WetL)?"+":"-",(thisvc.WetR)?"+":"-",
|
||||||
|
*(u8*)GetMemPtr(thisvc.StartA),*(u8 *)GetMemPtr((thisvc.StartA)+1),
|
||||||
|
thisvc.Pitch,
|
||||||
|
thisvc.VolumeL.Value,thisvc.VolumeR.Value,
|
||||||
|
thisvc.ADSR.Reg_ADSR1,thisvc.ADSR.Reg_ADSR2);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -142,9 +142,6 @@ extern void __inline __fastcall spu2M_Write( u32 addr, u16 value );
|
||||||
#define spu2Rs16(mmem) (*(s16 *)((s8 *)spu2regs + ((mmem) & 0x1fff)))
|
#define spu2Rs16(mmem) (*(s16 *)((s8 *)spu2regs + ((mmem) & 0x1fff)))
|
||||||
#define spu2Ru16(mmem) (*(u16 *)((s8 *)spu2regs + ((mmem) & 0x1fff)))
|
#define spu2Ru16(mmem) (*(u16 *)((s8 *)spu2regs + ((mmem) & 0x1fff)))
|
||||||
|
|
||||||
extern void VoiceStart(int core,int vc);
|
|
||||||
extern void VoiceStop(int core,int vc);
|
|
||||||
|
|
||||||
extern u8 callirq;
|
extern u8 callirq;
|
||||||
|
|
||||||
extern void (* _irqcallback)();
|
extern void (* _irqcallback)();
|
||||||
|
@ -162,8 +159,6 @@ extern int PlayMode;
|
||||||
extern int recording;
|
extern int recording;
|
||||||
extern bool disableFreezes;
|
extern bool disableFreezes;
|
||||||
|
|
||||||
|
|
||||||
extern s32 uTicks;
|
|
||||||
extern u32 lClocks;
|
extern u32 lClocks;
|
||||||
extern u32* cPtr;
|
extern u32* cPtr;
|
||||||
extern bool hasPtr;
|
extern bool hasPtr;
|
||||||
|
@ -192,7 +187,7 @@ extern void RecordWrite(s16 left, s16 right);
|
||||||
extern void UpdateSpdifMode();
|
extern void UpdateSpdifMode();
|
||||||
extern void LowPassFilterInit();
|
extern void LowPassFilterInit();
|
||||||
extern void InitADSR();
|
extern void InitADSR();
|
||||||
extern void SndUpdateLimitMode();
|
extern void CalculateADSR( V_Voice& vc );
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
// The Mixer Section //
|
// The Mixer Section //
|
||||||
|
|
|
@ -44,7 +44,7 @@ namespace WaveDump
|
||||||
|
|
||||||
void Open()
|
void Open()
|
||||||
{
|
{
|
||||||
#ifndef PUBLIC
|
if( !IsDevBuild ) return;
|
||||||
if( !WaveLog() ) return;
|
if( !WaveLog() ) return;
|
||||||
|
|
||||||
char wavfilename[256];
|
char wavfilename[256];
|
||||||
|
@ -69,12 +69,11 @@ namespace WaveDump
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Close()
|
void Close()
|
||||||
{
|
{
|
||||||
#ifndef PUBLIC
|
if( !IsDevBuild ) return;
|
||||||
for( uint cidx=0; cidx<2; cidx++ )
|
for( uint cidx=0; cidx<2; cidx++ )
|
||||||
{
|
{
|
||||||
for( int srcidx=0; srcidx<CoreSrc_Count; srcidx++ )
|
for( int srcidx=0; srcidx<CoreSrc_Count; srcidx++ )
|
||||||
|
@ -82,18 +81,16 @@ namespace WaveDump
|
||||||
SAFE_DELETE_OBJ( m_CoreWav[cidx][srcidx] );
|
SAFE_DELETE_OBJ( m_CoreWav[cidx][srcidx] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteCore( uint coreidx, CoreSourceType src, s16 left, s16 right )
|
void WriteCore( uint coreidx, CoreSourceType src, s16 left, s16 right )
|
||||||
{
|
{
|
||||||
#ifndef PUBLIC
|
if( !IsDevBuild ) return;
|
||||||
if( m_CoreWav[coreidx][src] != NULL )
|
if( m_CoreWav[coreidx][src] != NULL )
|
||||||
{
|
{
|
||||||
s16 buffer[2] = { left, right };
|
s16 buffer[2] = { left, right };
|
||||||
m_CoreWav[coreidx][src]->write( buffer, 2 );
|
m_CoreWav[coreidx][src]->write( buffer, 2 );
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,12 +36,12 @@ static LRESULT WINAPI AboutProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
|
||||||
ConvertStaticToHyperlink( hDlg, IDC_LINK_WEBSITE );
|
ConvertStaticToHyperlink( hDlg, IDC_LINK_WEBSITE );
|
||||||
|
|
||||||
wchar_t outstr[256];
|
wchar_t outstr[256];
|
||||||
#ifdef PUBLIC
|
if( IsDevBuild )
|
||||||
swprintf_s( outstr, _T("Release v%d.%d -- Compiled on ") _T(__DATE__),
|
swprintf_s( outstr, _T("Build r%d -- Compiled on ") _T(__DATE__), SVN_REV );
|
||||||
VersionInfo::Release, VersionInfo::Revision );
|
else
|
||||||
#else
|
swprintf_s( outstr, _T("Release v%d.%d -- Compiled on ") _T(__DATE__),
|
||||||
swprintf_s( outstr, _T("Build r%d -- Compiled on ") _T(__DATE__), SVN_REV );
|
VersionInfo::Release, VersionInfo::Revision );
|
||||||
#endif
|
|
||||||
SetWindowText( GetDlgItem(hDlg, IDC_LABEL_VERSION_INFO), outstr );
|
SetWindowText( GetDlgItem(hDlg, IDC_LABEL_VERSION_INFO), outstr );
|
||||||
ShowWindow( hDlg, true );
|
ShowWindow( hDlg, true );
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include "spu2.h"
|
#include "spu2.h"
|
||||||
#include "dialogs.h"
|
#include "dialogs.h"
|
||||||
|
|
||||||
#ifndef PUBLIC
|
#ifdef SPU2X_DEVBUILD
|
||||||
static const int LATENCY_MAX = 3000;
|
static const int LATENCY_MAX = 3000;
|
||||||
#else
|
#else
|
||||||
static const int LATENCY_MAX = 750;
|
static const int LATENCY_MAX = 750;
|
||||||
|
|
|
@ -132,13 +132,8 @@ void EnableControls( HWND hWnd )
|
||||||
{
|
{
|
||||||
EnableMessages( hWnd );
|
EnableMessages( hWnd );
|
||||||
ENABLE_CONTROL(IDC_LOGDMA, DebugEnabled);
|
ENABLE_CONTROL(IDC_LOGDMA, DebugEnabled);
|
||||||
#ifdef PUBLIC
|
ENABLE_CONTROL(IDC_LOGREGS, IsDevBuild ? DebugEnabled : false);
|
||||||
ENABLE_CONTROL(IDC_LOGREGS, false);
|
ENABLE_CONTROL(IDC_LOGWAVE, IsDevBuild ? DebugEnabled : false);
|
||||||
ENABLE_CONTROL(IDC_LOGWAVE, false);
|
|
||||||
#else
|
|
||||||
ENABLE_CONTROL(IDC_LOGREGS, DebugEnabled);
|
|
||||||
ENABLE_CONTROL(IDC_LOGWAVE, DebugEnabled);
|
|
||||||
#endif
|
|
||||||
ENABLE_CONTROL(IDC_DUMPCORE,DebugEnabled);
|
ENABLE_CONTROL(IDC_DUMPCORE,DebugEnabled);
|
||||||
ENABLE_CONTROL(IDC_DUMPMEM, DebugEnabled);
|
ENABLE_CONTROL(IDC_DUMPMEM, DebugEnabled);
|
||||||
ENABLE_CONTROL(IDC_DUMPREGS,DebugEnabled);
|
ENABLE_CONTROL(IDC_DUMPREGS,DebugEnabled);
|
||||||
|
@ -174,11 +169,7 @@ static BOOL CALLBACK DialogProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
|
||||||
SET_CHECK(IDC_DUMPMEM, _MemDump);
|
SET_CHECK(IDC_DUMPMEM, _MemDump);
|
||||||
SET_CHECK(IDC_DUMPREGS,_RegDump);
|
SET_CHECK(IDC_DUMPREGS,_RegDump);
|
||||||
|
|
||||||
#ifdef PUBLIC
|
ShowWindow( GetDlgItem( hWnd, IDC_MSG_PUBLIC_BUILD ), !IsDevBuild );
|
||||||
ShowWindow( GetDlgItem( hWnd, IDC_MSG_PUBLIC_BUILD ), true );
|
|
||||||
#else
|
|
||||||
ShowWindow( GetDlgItem( hWnd, IDC_MSG_PUBLIC_BUILD ), false );
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ static BOOL CALLBACK DebugProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PUBLIC
|
#ifdef SPU2X_DEVBUILD
|
||||||
|
|
||||||
int FillRectangle(HDC dc, int left, int top, int width, int height)
|
int FillRectangle(HDC dc, int left, int top, int width, int height)
|
||||||
{
|
{
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
FavorSizeOrSpeed="1"
|
FavorSizeOrSpeed="1"
|
||||||
OmitFramePointers="true"
|
OmitFramePointers="true"
|
||||||
EnableFiberSafeOptimizations="true"
|
EnableFiberSafeOptimizations="true"
|
||||||
PreprocessorDefinitions="FLOAT_SAMPLES;NDEBUG;_USRDLL"
|
PreprocessorDefinitions="SPU2X_DEVBUILD;FLOAT_SAMPLES;NDEBUG;_USRDLL"
|
||||||
StringPooling="true"
|
StringPooling="true"
|
||||||
RuntimeLibrary="0"
|
RuntimeLibrary="0"
|
||||||
StructMemberAlignment="5"
|
StructMemberAlignment="5"
|
||||||
|
@ -148,7 +148,7 @@
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
PreprocessorDefinitions="FLOAT_SAMPLES;_DEBUG;_USRDLL"
|
PreprocessorDefinitions="SPU2X_DEVBUILD;FLOAT_SAMPLES;_DEBUG;_USRDLL"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
RuntimeLibrary="1"
|
RuntimeLibrary="1"
|
||||||
|
@ -245,7 +245,7 @@
|
||||||
FavorSizeOrSpeed="1"
|
FavorSizeOrSpeed="1"
|
||||||
OmitFramePointers="true"
|
OmitFramePointers="true"
|
||||||
EnableFiberSafeOptimizations="true"
|
EnableFiberSafeOptimizations="true"
|
||||||
PreprocessorDefinitions="FLOAT_SAMPLES;NDEBUG;PUBLIC;_USRDLL"
|
PreprocessorDefinitions="FLOAT_SAMPLES;NDEBUG;_USRDLL"
|
||||||
StringPooling="true"
|
StringPooling="true"
|
||||||
RuntimeLibrary="0"
|
RuntimeLibrary="0"
|
||||||
StructMemberAlignment="5"
|
StructMemberAlignment="5"
|
||||||
|
@ -344,7 +344,7 @@
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
PreprocessorDefinitions="FLOAT_SAMPLES;_DEBUG_FAST;_DEBUG;_USRDLL"
|
PreprocessorDefinitions="SPU2X_DEVBUILD;FLOAT_SAMPLES;_DEBUG_FAST;_DEBUG;_USRDLL"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
RuntimeLibrary="1"
|
RuntimeLibrary="1"
|
||||||
|
@ -727,6 +727,10 @@
|
||||||
<Filter
|
<Filter
|
||||||
Name="SPU2"
|
Name="SPU2"
|
||||||
>
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\ADSR.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\defs.h"
|
RelativePath="..\defs.h"
|
||||||
>
|
>
|
||||||
|
|
|
@ -31,6 +31,9 @@ struct V_Volume
|
||||||
s32 Value;
|
s32 Value;
|
||||||
s8 Increment;
|
s8 Increment;
|
||||||
s8 Mode;
|
s8 Mode;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Update();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct V_ADSR
|
struct V_ADSR
|
||||||
|
@ -38,29 +41,22 @@ struct V_ADSR
|
||||||
u16 Reg_ADSR1;
|
u16 Reg_ADSR1;
|
||||||
u16 Reg_ADSR2;
|
u16 Reg_ADSR2;
|
||||||
|
|
||||||
//also Reg_ENVX
|
s32 Value; // Ranges from 0 to 0x7fffffff (signed values are clamped to 0) [Reg_ENVX]
|
||||||
s32 Value; // Ranges from 0 to 0x7fffffff (signed values are clamped to 0)
|
|
||||||
// Phase
|
|
||||||
u8 Phase;
|
u8 Phase;
|
||||||
//Attack Rate
|
u8 AttackRate; // Ar
|
||||||
u8 Ar;
|
u8 AttackMode; // Am
|
||||||
//Attack Mode
|
u8 DecayRate; // Dr
|
||||||
u8 Am;
|
u8 SustainLevel; // Sl
|
||||||
//Decay Rate
|
u8 SustainRate; // Sr
|
||||||
u8 Dr;
|
u8 SustainMode; // Sm
|
||||||
//Sustain Level
|
u8 ReleaseRate; // Rr
|
||||||
u8 Sl;
|
u8 ReleaseMode; // Rm
|
||||||
//Sustain Rate
|
|
||||||
u8 Sr;
|
|
||||||
//Sustain Mode
|
|
||||||
u8 Sm;
|
|
||||||
//Release Rate
|
|
||||||
u8 Rr;
|
|
||||||
//Release Mode
|
|
||||||
u8 Rm;
|
|
||||||
|
|
||||||
//Ready To Release
|
bool Releasing; // Ready To Release, triggered by Voice.Stop();
|
||||||
bool Releasing;
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool Calculate();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -133,9 +129,10 @@ struct V_Voice
|
||||||
// sample position within the current decoded packet.
|
// sample position within the current decoded packet.
|
||||||
s32 SCurrent;
|
s32 SCurrent;
|
||||||
|
|
||||||
|
void Start();
|
||||||
|
void Stop();
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef PUBLIC
|
|
||||||
// ** Begin Debug-only variables section **
|
// ** Begin Debug-only variables section **
|
||||||
// Separated from the V_Voice struct to improve cache performance of
|
// Separated from the V_Voice struct to improve cache performance of
|
||||||
// the Public Release build.
|
// the Public Release build.
|
||||||
|
@ -158,7 +155,6 @@ struct V_CoreDebug
|
||||||
|
|
||||||
// Debug tracking information - 24 voices and 2 cores.
|
// Debug tracking information - 24 voices and 2 cores.
|
||||||
extern V_CoreDebug DebugCores[2];
|
extern V_CoreDebug DebugCores[2];
|
||||||
#endif
|
|
||||||
|
|
||||||
struct V_Reverb
|
struct V_Reverb
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue