mirror of https://github.com/PCSX2/pcsx2.git
clang-format spu2x
Note: it doesn't play well with define around forceinline (might need to fix the inline btw) And a single macro in RegTable.cpp
This commit is contained in:
parent
0f022da98c
commit
039573b133
|
@ -19,219 +19,201 @@
|
|||
|
||||
static const s32 ADSR_MAX_VOL = 0x7fffffff;
|
||||
|
||||
static const int InvExpOffsets[] = { 0,4,6,8,9,10,11,12 };
|
||||
static const int InvExpOffsets[] = {0, 4, 6, 8, 9, 10, 11, 12};
|
||||
static u32 PsxRates[160];
|
||||
|
||||
|
||||
void InitADSR() // INIT ADSR
|
||||
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;
|
||||
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)std::min( rate, (s64)0x3fffffffLL );
|
||||
}
|
||||
PsxRates[i] = (int)std::min(rate, (s64)0x3fffffffLL);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the linear slide value for AR and SR inputs.
|
||||
// (currently not used, it's buggy)
|
||||
static int GetLinearSrAr( uint SrAr )
|
||||
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:
|
||||
// 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));
|
||||
const uint newSr = 0x7f - SrAr;
|
||||
return ((1 | (newSr & 3)) << (newSr >> 2));
|
||||
}
|
||||
|
||||
bool V_ADSR::Calculate()
|
||||
{
|
||||
pxAssume( Phase != 0 );
|
||||
pxAssume(Phase != 0);
|
||||
|
||||
if(Releasing && (Phase < 5))
|
||||
Phase = 5;
|
||||
if (Releasing && (Phase < 5))
|
||||
Phase = 5;
|
||||
|
||||
switch (Phase)
|
||||
{
|
||||
case 1: // attack
|
||||
if( Value == ADSR_MAX_VOL )
|
||||
{
|
||||
// Already maxed out. Progress phase and nothing more:
|
||||
Phase++;
|
||||
break;
|
||||
}
|
||||
switch (Phase) {
|
||||
case 1: // attack
|
||||
if (Value == ADSR_MAX_VOL) {
|
||||
// Already maxed out. Progress phase and nothing more:
|
||||
Phase++;
|
||||
break;
|
||||
}
|
||||
|
||||
// Case 1 below is for pseudo exponential below 75%.
|
||||
// Pseudo Exp > 75% and Linear are the same.
|
||||
// Case 1 below is for pseudo exponential below 75%.
|
||||
// Pseudo Exp > 75% and Linear are the same.
|
||||
|
||||
if( AttackMode && (Value>=0x60000000) )
|
||||
Value += PsxRates[(AttackRate^0x7f)-0x18+32];
|
||||
else
|
||||
Value += PsxRates[(AttackRate^0x7f)-0x10+32];
|
||||
if (AttackMode && (Value >= 0x60000000))
|
||||
Value += PsxRates[(AttackRate ^ 0x7f) - 0x18 + 32];
|
||||
else
|
||||
Value += PsxRates[(AttackRate ^ 0x7f) - 0x10 + 32];
|
||||
|
||||
if( Value < 0 )
|
||||
{
|
||||
// We hit the ceiling.
|
||||
Phase++;
|
||||
Value = ADSR_MAX_VOL;
|
||||
}
|
||||
break;
|
||||
if (Value < 0) {
|
||||
// We hit the ceiling.
|
||||
Phase++;
|
||||
Value = ADSR_MAX_VOL;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // decay
|
||||
{
|
||||
u32 off = InvExpOffsets[(Value>>28)&7];
|
||||
Value -= PsxRates[((DecayRate^0x1f)*4)-0x18+off+32];
|
||||
case 2: // decay
|
||||
{
|
||||
u32 off = InvExpOffsets[(Value >> 28) & 7];
|
||||
Value -= PsxRates[((DecayRate ^ 0x1f) * 4) - 0x18 + off + 32];
|
||||
|
||||
// calculate sustain level as a factor of the ADSR maximum volume.
|
||||
// calculate sustain level as a factor of the ADSR maximum volume.
|
||||
|
||||
s32 suslev = ((0x80000000 / 0x10 ) * (SustainLevel+1)) - 1;
|
||||
s32 suslev = ((0x80000000 / 0x10) * (SustainLevel + 1)) - 1;
|
||||
|
||||
if( Value <= suslev )
|
||||
{
|
||||
if (Value < 0)
|
||||
Value = 0;
|
||||
Phase++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
if (Value <= suslev) {
|
||||
if (Value < 0)
|
||||
Value = 0;
|
||||
Phase++;
|
||||
}
|
||||
} break;
|
||||
|
||||
case 3: // sustain
|
||||
{
|
||||
// 0x7f disables sustain (infinite sustain)
|
||||
if( SustainRate == 0x7f ) return true;
|
||||
case 3: // sustain
|
||||
{
|
||||
// 0x7f disables sustain (infinite sustain)
|
||||
if (SustainRate == 0x7f)
|
||||
return true;
|
||||
|
||||
if (SustainMode&2) // decreasing
|
||||
{
|
||||
if (SustainMode&4) // exponential
|
||||
{
|
||||
u32 off = InvExpOffsets[(Value>>28)&7];
|
||||
Value -= PsxRates[(SustainRate^0x7f)-0x1b+off+32];
|
||||
}
|
||||
else // linear
|
||||
Value -= PsxRates[(SustainRate^0x7f)-0xf+32];
|
||||
if (SustainMode & 2) // decreasing
|
||||
{
|
||||
if (SustainMode & 4) // exponential
|
||||
{
|
||||
u32 off = InvExpOffsets[(Value >> 28) & 7];
|
||||
Value -= PsxRates[(SustainRate ^ 0x7f) - 0x1b + off + 32];
|
||||
} else // linear
|
||||
Value -= PsxRates[(SustainRate ^ 0x7f) - 0xf + 32];
|
||||
|
||||
if( Value <= 0 )
|
||||
{
|
||||
Value = 0;
|
||||
Phase++;
|
||||
}
|
||||
}
|
||||
else // increasing
|
||||
{
|
||||
if( (SustainMode&4) && (Value>=0x60000000) )
|
||||
Value += PsxRates[(SustainRate^0x7f)-0x18+32];
|
||||
else
|
||||
// linear / Pseudo below 75% (they're the same)
|
||||
Value += PsxRates[(SustainRate^0x7f)-0x10+32];
|
||||
if (Value <= 0) {
|
||||
Value = 0;
|
||||
Phase++;
|
||||
}
|
||||
} else { // increasing
|
||||
if ((SustainMode & 4) && (Value >= 0x60000000))
|
||||
Value += PsxRates[(SustainRate ^ 0x7f) - 0x18 + 32];
|
||||
else
|
||||
// linear / Pseudo below 75% (they're the same)
|
||||
Value += PsxRates[(SustainRate ^ 0x7f) - 0x10 + 32];
|
||||
|
||||
if( Value < 0 )
|
||||
{
|
||||
Value = ADSR_MAX_VOL;
|
||||
Phase++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
if (Value < 0) {
|
||||
Value = ADSR_MAX_VOL;
|
||||
Phase++;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case 4: // sustain end
|
||||
Value = (SustainMode&2) ? 0 : ADSR_MAX_VOL;
|
||||
if(Value==0)
|
||||
Phase=6;
|
||||
break;
|
||||
case 4: // sustain end
|
||||
Value = (SustainMode & 2) ? 0 : ADSR_MAX_VOL;
|
||||
if (Value == 0)
|
||||
Phase = 6;
|
||||
break;
|
||||
|
||||
case 5: // release
|
||||
if (ReleaseMode) // exponential
|
||||
{
|
||||
u32 off=InvExpOffsets[(Value>>28)&7];
|
||||
Value-=PsxRates[((ReleaseRate^0x1f)*4)-0x18+off+32];
|
||||
}
|
||||
else // linear
|
||||
{
|
||||
//Value-=PsxRates[((ReleaseRate^0x1f)*4)-0xc+32];
|
||||
if( ReleaseRate != 0x1f )
|
||||
Value -= (1 << (0x1f-ReleaseRate));
|
||||
}
|
||||
case 5: // release
|
||||
if (ReleaseMode) // exponential
|
||||
{
|
||||
u32 off = InvExpOffsets[(Value >> 28) & 7];
|
||||
Value -= PsxRates[((ReleaseRate ^ 0x1f) * 4) - 0x18 + off + 32];
|
||||
} else { // linear
|
||||
//Value-=PsxRates[((ReleaseRate^0x1f)*4)-0xc+32];
|
||||
if (ReleaseRate != 0x1f)
|
||||
Value -= (1 << (0x1f - ReleaseRate));
|
||||
}
|
||||
|
||||
if( Value <= 0 )
|
||||
{
|
||||
Value=0;
|
||||
Phase++;
|
||||
}
|
||||
break;
|
||||
if (Value <= 0) {
|
||||
Value = 0;
|
||||
Phase++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 6: // release end
|
||||
Value=0;
|
||||
break;
|
||||
case 6: // release end
|
||||
Value = 0;
|
||||
break;
|
||||
|
||||
jNO_DEFAULT
|
||||
}
|
||||
jNO_DEFAULT
|
||||
}
|
||||
|
||||
// returns true if the voice is active, or false if it's stopping.
|
||||
return Phase != 6;
|
||||
// returns true if the voice is active, or false if it's stopping.
|
||||
return Phase != 6;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
|
||||
#define VOLFLAG_REVERSE_PHASE (1ul<<0)
|
||||
#define VOLFLAG_DECREMENT (1ul<<1)
|
||||
#define VOLFLAG_EXPONENTIAL (1ul<<2)
|
||||
#define VOLFLAG_SLIDE_ENABLE (1ul<<3)
|
||||
#define VOLFLAG_REVERSE_PHASE (1ul << 0)
|
||||
#define VOLFLAG_DECREMENT (1ul << 1)
|
||||
#define VOLFLAG_EXPONENTIAL (1ul << 2)
|
||||
#define VOLFLAG_SLIDE_ENABLE (1ul << 3)
|
||||
|
||||
void V_VolumeSlide::Update()
|
||||
{
|
||||
if( !(Mode & VOLFLAG_SLIDE_ENABLE) ) return;
|
||||
if (!(Mode & VOLFLAG_SLIDE_ENABLE))
|
||||
return;
|
||||
|
||||
// Volume slides use the same basic logic as ADSR, but simplified (single-stage
|
||||
// instead of multi-stage)
|
||||
// Volume slides use the same basic logic as ADSR, but simplified (single-stage
|
||||
// instead of multi-stage)
|
||||
|
||||
if( Increment == 0x7f ) return;
|
||||
if (Increment == 0x7f)
|
||||
return;
|
||||
|
||||
s32 value = abs(Value);
|
||||
s32 value = abs(Value);
|
||||
|
||||
if (Mode & VOLFLAG_DECREMENT)
|
||||
{
|
||||
// Decrement
|
||||
if (Mode & VOLFLAG_DECREMENT) {
|
||||
// Decrement
|
||||
|
||||
if(Mode & VOLFLAG_EXPONENTIAL)
|
||||
{
|
||||
u32 off = InvExpOffsets[(value>>28)&7];
|
||||
value -= PsxRates[(Increment^0x7f)-0x1b+off+32];
|
||||
}
|
||||
else
|
||||
value -= PsxRates[(Increment^0x7f)-0xf+32];
|
||||
if (Mode & VOLFLAG_EXPONENTIAL) {
|
||||
u32 off = InvExpOffsets[(value >> 28) & 7];
|
||||
value -= PsxRates[(Increment ^ 0x7f) - 0x1b + off + 32];
|
||||
} else
|
||||
value -= PsxRates[(Increment ^ 0x7f) - 0xf + 32];
|
||||
|
||||
if (value < 0)
|
||||
{
|
||||
value = 0;
|
||||
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 (value < 0) {
|
||||
value = 0;
|
||||
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( (Mode & VOLFLAG_EXPONENTIAL) && (value>=0x60000000))
|
||||
value += PsxRates[(Increment^0x7f)-0x18+32];
|
||||
else
|
||||
// linear / Pseudo below 75% (they're the same)
|
||||
value += PsxRates[(Increment^0x7f)-0x10+32];
|
||||
if ((Mode & VOLFLAG_EXPONENTIAL) && (value >= 0x60000000))
|
||||
value += PsxRates[(Increment ^ 0x7f) - 0x18 + 32];
|
||||
else
|
||||
// linear / Pseudo below 75% (they're the same)
|
||||
value += PsxRates[(Increment ^ 0x7f) - 0x10 + 32];
|
||||
|
||||
if( value < 0 ) // wrapped around the "top"?
|
||||
{
|
||||
value = 0x7fffffff;
|
||||
Mode = 0; // disable slide
|
||||
}
|
||||
}
|
||||
|
||||
Value = (Value < 0) ? -value : value;
|
||||
if (value < 0) // wrapped around the "top"?
|
||||
{
|
||||
value = 0x7fffffff;
|
||||
Mode = 0; // disable slide
|
||||
}
|
||||
}
|
||||
|
||||
Value = (Value < 0) ? -value : value;
|
||||
}
|
||||
|
|
|
@ -36,23 +36,23 @@ extern bool _MemDump;
|
|||
extern bool _RegDump;
|
||||
extern bool _visual_debug_enabled;
|
||||
|
||||
static __forceinline bool MsgToConsole() { return _MsgToConsole & DebugEnabled; }
|
||||
static __forceinline bool MsgToConsole() { return _MsgToConsole & DebugEnabled; }
|
||||
|
||||
static __forceinline bool MsgKeyOnOff() { return _MsgKeyOnOff & MsgToConsole(); }
|
||||
static __forceinline bool MsgVoiceOff() { return _MsgVoiceOff & MsgToConsole(); }
|
||||
static __forceinline bool MsgDMA() { return _MsgDMA & MsgToConsole(); }
|
||||
static __forceinline bool MsgAutoDMA() { return _MsgAutoDMA & MsgToConsole(); }
|
||||
static __forceinline bool MsgOverruns() { return _MsgOverruns & MsgToConsole(); }
|
||||
static __forceinline bool MsgCache() { return _MsgCache & MsgToConsole(); }
|
||||
static __forceinline bool MsgKeyOnOff() { return _MsgKeyOnOff & MsgToConsole(); }
|
||||
static __forceinline bool MsgVoiceOff() { return _MsgVoiceOff & MsgToConsole(); }
|
||||
static __forceinline bool MsgDMA() { return _MsgDMA & MsgToConsole(); }
|
||||
static __forceinline bool MsgAutoDMA() { return _MsgAutoDMA & MsgToConsole(); }
|
||||
static __forceinline bool MsgOverruns() { return _MsgOverruns & MsgToConsole(); }
|
||||
static __forceinline bool MsgCache() { return _MsgCache & MsgToConsole(); }
|
||||
|
||||
static __forceinline bool AccessLog() { return _AccessLog & DebugEnabled; }
|
||||
static __forceinline bool DMALog() { return _DMALog & DebugEnabled; }
|
||||
static __forceinline bool WaveLog() { return _WaveLog & DebugEnabled; }
|
||||
static __forceinline bool AccessLog() { return _AccessLog & DebugEnabled; }
|
||||
static __forceinline bool DMALog() { return _DMALog & DebugEnabled; }
|
||||
static __forceinline bool WaveLog() { return _WaveLog & DebugEnabled; }
|
||||
|
||||
static __forceinline bool CoresDump() { return _CoresDump & DebugEnabled; }
|
||||
static __forceinline bool MemDump() { return _MemDump & DebugEnabled; }
|
||||
static __forceinline bool RegDump() { return _RegDump & DebugEnabled; }
|
||||
static __forceinline bool VisualDebug() { return _visual_debug_enabled & DebugEnabled; }
|
||||
static __forceinline bool CoresDump() { return _CoresDump & DebugEnabled; }
|
||||
static __forceinline bool MemDump() { return _MemDump & DebugEnabled; }
|
||||
static __forceinline bool RegDump() { return _RegDump & DebugEnabled; }
|
||||
static __forceinline bool VisualDebug() { return _visual_debug_enabled & DebugEnabled; }
|
||||
|
||||
extern wxString AccessLogFileName;
|
||||
extern wxString DMA4LogFileName;
|
||||
|
@ -64,7 +64,7 @@ extern wxString RegDumpFileName;
|
|||
extern int Interpolation;
|
||||
extern int numSpeakers;
|
||||
extern bool EffectsDisabled;
|
||||
extern float FinalVolume; // Global / pre-scale
|
||||
extern float FinalVolume; // Global / pre-scale
|
||||
extern bool AdvancedVolumeControl;
|
||||
extern float VolumeAdjustFLdb;
|
||||
extern float VolumeAdjustCdb;
|
||||
|
@ -85,14 +85,14 @@ extern int SynchMode;
|
|||
|
||||
#ifndef __POSIX__
|
||||
extern wchar_t dspPlugin[];
|
||||
extern int dspPluginModule;
|
||||
extern int dspPluginModule;
|
||||
|
||||
extern bool dspPluginEnabled;
|
||||
extern bool dspPluginEnabled;
|
||||
#endif
|
||||
|
||||
namespace SoundtouchCfg
|
||||
{
|
||||
extern void ApplySettings( soundtouch::SoundTouch& sndtouch );
|
||||
extern void ApplySettings(soundtouch::SoundTouch &sndtouch);
|
||||
}
|
||||
|
||||
//////
|
||||
|
|
|
@ -24,28 +24,28 @@
|
|||
class DPLII
|
||||
{
|
||||
public:
|
||||
static const bool UseAveraging = false;
|
||||
static const bool UseAveraging = false;
|
||||
|
||||
protected:
|
||||
s32 LAccum;
|
||||
s32 RAccum;
|
||||
s32 ANum;
|
||||
s32 LAccum;
|
||||
s32 RAccum;
|
||||
s32 ANum;
|
||||
|
||||
LPF_data lpf_l;
|
||||
LPF_data lpf_r;
|
||||
LPF_data lpf_l;
|
||||
LPF_data lpf_r;
|
||||
|
||||
u8 bufdone;
|
||||
s32 Gfl,Gfr;
|
||||
u8 bufdone;
|
||||
s32 Gfl, Gfr;
|
||||
|
||||
s32 spdif_data[6];
|
||||
s32 LMax,RMax;
|
||||
s32 spdif_data[6];
|
||||
s32 LMax, RMax;
|
||||
|
||||
s32 LBuff[128];
|
||||
s32 RBuff[128];
|
||||
s32 LBuff[128];
|
||||
s32 RBuff[128];
|
||||
|
||||
public:
|
||||
DPLII( s32 lowpass_freq, s32 samplerate );
|
||||
void Convert( s16 *obuffer, s32 ValL, s32 ValR );
|
||||
DPLII(s32 lowpass_freq, s32 samplerate);
|
||||
void Convert(s16 *obuffer, s32 ValL, s32 ValR);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,25 +17,28 @@
|
|||
|
||||
#include "Global.h"
|
||||
|
||||
int crazy_debug=0;
|
||||
int crazy_debug = 0;
|
||||
|
||||
char s[4096];
|
||||
|
||||
FILE *spu2Log = NULL;
|
||||
|
||||
void FileLog(const char *fmt, ...) {
|
||||
void FileLog(const char *fmt, ...)
|
||||
{
|
||||
#ifdef SPU2_LOG
|
||||
va_list list;
|
||||
va_list list;
|
||||
|
||||
if(!AccessLog()) return;
|
||||
if(!spu2Log) return;
|
||||
if (!AccessLog())
|
||||
return;
|
||||
if (!spu2Log)
|
||||
return;
|
||||
|
||||
va_start(list, fmt);
|
||||
vsprintf(s,fmt, list);
|
||||
va_end(list);
|
||||
va_start(list, fmt);
|
||||
vsprintf(s, fmt, list);
|
||||
va_end(list);
|
||||
|
||||
fputs(s,spu2Log);
|
||||
fflush(spu2Log);
|
||||
fputs(s, spu2Log);
|
||||
fflush(spu2Log);
|
||||
|
||||
#if 0
|
||||
if(crazy_debug)
|
||||
|
@ -51,212 +54,205 @@ void FileLog(const char *fmt, ...) {
|
|||
// while ConLog doesn't print anything if messages to console are disabled at the GUI,
|
||||
// it's still better to outright not call it on tight loop scenarios, by testing MsgToConsole() (which is inline and very quick).
|
||||
// Else, there's some (small) overhead in calling and returning from ConLog.
|
||||
void ConLog(const char *fmt, ...) {
|
||||
if(!MsgToConsole()) return;
|
||||
void ConLog(const char *fmt, ...)
|
||||
{
|
||||
if (!MsgToConsole())
|
||||
return;
|
||||
|
||||
va_list list;
|
||||
va_start(list, fmt);
|
||||
vsprintf(s,fmt, list);
|
||||
va_end(list);
|
||||
va_list list;
|
||||
va_start(list, fmt);
|
||||
vsprintf(s, fmt, list);
|
||||
va_end(list);
|
||||
|
||||
fputs(s,stderr);
|
||||
fflush(stderr);
|
||||
fputs(s, stderr);
|
||||
fflush(stderr);
|
||||
|
||||
if(spu2Log)
|
||||
{
|
||||
fputs(s,spu2Log);
|
||||
fflush(spu2Log);
|
||||
}
|
||||
if (spu2Log) {
|
||||
fputs(s, spu2Log);
|
||||
fflush(spu2Log);
|
||||
}
|
||||
}
|
||||
|
||||
void V_VolumeSlide::DebugDump( FILE* dump, const char* title, const char* nameLR )
|
||||
void V_VolumeSlide::DebugDump(FILE *dump, const char *title, const char *nameLR)
|
||||
{
|
||||
fprintf( dump, "%s Volume for %s Channel:\t%x\n"
|
||||
" - Value: %x\n"
|
||||
" - Mode: %x\n"
|
||||
" - Increment: %x\n",
|
||||
title, nameLR, Reg_VOL, Value, Mode, Increment);
|
||||
fprintf(dump, "%s Volume for %s Channel:\t%x\n"
|
||||
" - Value: %x\n"
|
||||
" - Mode: %x\n"
|
||||
" - Increment: %x\n",
|
||||
title, nameLR, Reg_VOL, Value, Mode, Increment);
|
||||
}
|
||||
|
||||
void V_VolumeSlideLR::DebugDump( FILE* dump, const char* title )
|
||||
void V_VolumeSlideLR::DebugDump(FILE *dump, const char *title)
|
||||
{
|
||||
Left.DebugDump( dump, title, "Left" );
|
||||
Right.DebugDump( dump, title, "Right" );
|
||||
Left.DebugDump(dump, title, "Left");
|
||||
Right.DebugDump(dump, title, "Right");
|
||||
}
|
||||
|
||||
void V_VolumeLR::DebugDump( FILE* dump, const char* title )
|
||||
void V_VolumeLR::DebugDump(FILE *dump, const char *title)
|
||||
{
|
||||
fprintf( dump, "Volume for %s (%s Channel):\t%x\n", title, "Left", Left );
|
||||
fprintf( dump, "Volume for %s (%s Channel):\t%x\n", title, "Right", Right );
|
||||
fprintf(dump, "Volume for %s (%s Channel):\t%x\n", title, "Left", Left);
|
||||
fprintf(dump, "Volume for %s (%s Channel):\t%x\n", title, "Right", Right);
|
||||
}
|
||||
|
||||
void DoFullDump()
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
#ifdef SPU2_LOG
|
||||
FILE *dump;
|
||||
u8 c=0, v=0;
|
||||
FILE *dump;
|
||||
u8 c = 0, v = 0;
|
||||
|
||||
if(MemDump())
|
||||
{
|
||||
dump = fopen( wxString(MemDumpFileName).ToUTF8(), "wb" );
|
||||
if (dump)
|
||||
{
|
||||
fwrite(_spu2mem,0x200000,1,dump);
|
||||
fclose(dump);
|
||||
}
|
||||
}
|
||||
if(RegDump())
|
||||
{
|
||||
dump = fopen( wxString(RegDumpFileName).ToUTF8(), "wb" );
|
||||
if (dump)
|
||||
{
|
||||
fwrite(spu2regs,0x2000,1,dump);
|
||||
fclose(dump);
|
||||
}
|
||||
}
|
||||
if (MemDump()) {
|
||||
dump = fopen(wxString(MemDumpFileName).ToUTF8(), "wb");
|
||||
if (dump) {
|
||||
fwrite(_spu2mem, 0x200000, 1, dump);
|
||||
fclose(dump);
|
||||
}
|
||||
}
|
||||
if (RegDump()) {
|
||||
dump = fopen(wxString(RegDumpFileName).ToUTF8(), "wb");
|
||||
if (dump) {
|
||||
fwrite(spu2regs, 0x2000, 1, dump);
|
||||
fclose(dump);
|
||||
}
|
||||
}
|
||||
|
||||
if(!CoresDump()) return;
|
||||
dump = fopen( wxString(CoresDumpFileName).ToUTF8(), "wt" );
|
||||
if (dump)
|
||||
{
|
||||
for(c=0;c<2;c++)
|
||||
{
|
||||
fprintf(dump,"#### CORE %d DUMP.\n",c);
|
||||
if (!CoresDump())
|
||||
return;
|
||||
dump = fopen(wxString(CoresDumpFileName).ToUTF8(), "wt");
|
||||
if (dump) {
|
||||
for (c = 0; c < 2; c++) {
|
||||
fprintf(dump, "#### CORE %d DUMP.\n", c);
|
||||
|
||||
Cores[c].MasterVol.DebugDump( dump, "Master" );
|
||||
Cores[c].MasterVol.DebugDump(dump, "Master");
|
||||
|
||||
Cores[c].ExtVol.DebugDump( dump, "External Data Input" );
|
||||
Cores[c].InpVol.DebugDump( dump, "Voice Data Input [dry]" );
|
||||
Cores[c].FxVol.DebugDump( dump, "Effects/Reverb [wet]" );
|
||||
Cores[c].ExtVol.DebugDump(dump, "External Data Input");
|
||||
Cores[c].InpVol.DebugDump(dump, "Voice Data Input [dry]");
|
||||
Cores[c].FxVol.DebugDump(dump, "Effects/Reverb [wet]");
|
||||
|
||||
fprintf(dump,"Interrupt Address: %x\n",Cores[c].IRQA);
|
||||
fprintf(dump,"DMA Transfer Start Address: %x\n",Cores[c].TSA);
|
||||
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].DryGate.ExtR?"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].WetGate.ExtR?"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].DryGate.SndR?"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].WetGate.SndR?"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].DryGate.InpR?"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].WetGate.InpR?"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,"Mute Enabled: %s\n",Cores[c].Mute?"Yes":"No");
|
||||
fprintf(dump,"Noise Clock: %d\n",Cores[c].NoiseClk);
|
||||
fprintf(dump,"DMA Bits: %d\n",Cores[c].DMABits);
|
||||
fprintf(dump,"Effects Start: %x\n",Cores[c].EffectsStartA);
|
||||
fprintf(dump,"Effects End: %x\n",Cores[c].EffectsEndA);
|
||||
fprintf(dump,"Registers:\n");
|
||||
fprintf(dump," - PMON: %x\n",Cores[c].Regs.PMON);
|
||||
fprintf(dump," - NON: %x\n",Cores[c].Regs.NON);
|
||||
fprintf(dump," - VMIXL: %x\n",Cores[c].Regs.VMIXL);
|
||||
fprintf(dump," - VMIXR: %x\n",Cores[c].Regs.VMIXR);
|
||||
fprintf(dump," - VMIXEL: %x\n",Cores[c].Regs.VMIXEL);
|
||||
fprintf(dump," - VMIXER: %x\n",Cores[c].Regs.VMIXER);
|
||||
fprintf(dump," - MMIX: %x\n",Cores[c].Regs.VMIXEL);
|
||||
fprintf(dump," - ENDX: %x\n",Cores[c].Regs.VMIXER);
|
||||
fprintf(dump," - STATX: %x\n",Cores[c].Regs.VMIXEL);
|
||||
fprintf(dump," - ATTR: %x\n",Cores[c].Regs.VMIXER);
|
||||
for(v=0;v<24;v++)
|
||||
{
|
||||
fprintf(dump,"Voice %d:\n",v);
|
||||
Cores[c].Voices[v].Volume.DebugDump( dump, "" );
|
||||
fprintf(dump, "Interrupt Address: %x\n", Cores[c].IRQA);
|
||||
fprintf(dump, "DMA Transfer Start Address: %x\n", Cores[c].TSA);
|
||||
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].DryGate.ExtR ? "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].WetGate.ExtR ? "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].DryGate.SndR ? "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].WetGate.SndR ? "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].DryGate.InpR ? "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].WetGate.InpR ? "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, "Mute Enabled: %s\n", Cores[c].Mute ? "Yes" : "No");
|
||||
fprintf(dump, "Noise Clock: %d\n", Cores[c].NoiseClk);
|
||||
fprintf(dump, "DMA Bits: %d\n", Cores[c].DMABits);
|
||||
fprintf(dump, "Effects Start: %x\n", Cores[c].EffectsStartA);
|
||||
fprintf(dump, "Effects End: %x\n", Cores[c].EffectsEndA);
|
||||
fprintf(dump, "Registers:\n");
|
||||
fprintf(dump, " - PMON: %x\n", Cores[c].Regs.PMON);
|
||||
fprintf(dump, " - NON: %x\n", Cores[c].Regs.NON);
|
||||
fprintf(dump, " - VMIXL: %x\n", Cores[c].Regs.VMIXL);
|
||||
fprintf(dump, " - VMIXR: %x\n", Cores[c].Regs.VMIXR);
|
||||
fprintf(dump, " - VMIXEL: %x\n", Cores[c].Regs.VMIXEL);
|
||||
fprintf(dump, " - VMIXER: %x\n", Cores[c].Regs.VMIXER);
|
||||
fprintf(dump, " - MMIX: %x\n", Cores[c].Regs.VMIXEL);
|
||||
fprintf(dump, " - ENDX: %x\n", Cores[c].Regs.VMIXER);
|
||||
fprintf(dump, " - STATX: %x\n", Cores[c].Regs.VMIXEL);
|
||||
fprintf(dump, " - ATTR: %x\n", Cores[c].Regs.VMIXER);
|
||||
for (v = 0; v < 24; v++) {
|
||||
fprintf(dump, "Voice %d:\n", v);
|
||||
Cores[c].Voices[v].Volume.DebugDump(dump, "");
|
||||
|
||||
fprintf(dump," - ADSR Envelope: %x & %x\n"
|
||||
" - Ar: %x\n"
|
||||
" - Am: %x\n"
|
||||
" - Dr: %x\n"
|
||||
" - Sl: %x\n"
|
||||
" - Sr: %x\n"
|
||||
" - Sm: %x\n"
|
||||
" - Rr: %x\n"
|
||||
" - Rm: %x\n"
|
||||
" - Phase: %x\n"
|
||||
" - Value: %x\n",
|
||||
Cores[c].Voices[v].ADSR.regADSR1,
|
||||
Cores[c].Voices[v].ADSR.regADSR2,
|
||||
Cores[c].Voices[v].ADSR.AttackRate,
|
||||
Cores[c].Voices[v].ADSR.AttackMode,
|
||||
Cores[c].Voices[v].ADSR.DecayRate,
|
||||
Cores[c].Voices[v].ADSR.SustainLevel,
|
||||
Cores[c].Voices[v].ADSR.SustainRate,
|
||||
Cores[c].Voices[v].ADSR.SustainMode,
|
||||
Cores[c].Voices[v].ADSR.ReleaseRate,
|
||||
Cores[c].Voices[v].ADSR.ReleaseMode,
|
||||
Cores[c].Voices[v].ADSR.Phase,
|
||||
Cores[c].Voices[v].ADSR.Value);
|
||||
fprintf(dump, " - ADSR Envelope: %x & %x\n"
|
||||
" - Ar: %x\n"
|
||||
" - Am: %x\n"
|
||||
" - Dr: %x\n"
|
||||
" - Sl: %x\n"
|
||||
" - Sr: %x\n"
|
||||
" - Sm: %x\n"
|
||||
" - Rr: %x\n"
|
||||
" - Rm: %x\n"
|
||||
" - Phase: %x\n"
|
||||
" - Value: %x\n",
|
||||
Cores[c].Voices[v].ADSR.regADSR1,
|
||||
Cores[c].Voices[v].ADSR.regADSR2,
|
||||
Cores[c].Voices[v].ADSR.AttackRate,
|
||||
Cores[c].Voices[v].ADSR.AttackMode,
|
||||
Cores[c].Voices[v].ADSR.DecayRate,
|
||||
Cores[c].Voices[v].ADSR.SustainLevel,
|
||||
Cores[c].Voices[v].ADSR.SustainRate,
|
||||
Cores[c].Voices[v].ADSR.SustainMode,
|
||||
Cores[c].Voices[v].ADSR.ReleaseRate,
|
||||
Cores[c].Voices[v].ADSR.ReleaseMode,
|
||||
Cores[c].Voices[v].ADSR.Phase,
|
||||
Cores[c].Voices[v].ADSR.Value);
|
||||
|
||||
fprintf(dump," - Pitch: %x\n",Cores[c].Voices[v].Pitch);
|
||||
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," - 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].VoiceGates[v].DryR?"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].VoiceGates[v].WetR?"Yes":"No");
|
||||
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," - Next Data Address: %x\n",Cores[c].Voices[v].NextA);
|
||||
fprintf(dump," - Play Start Cycle: %d\n",Cores[c].Voices[v].PlayCycle);
|
||||
fprintf(dump," - Play Status: %s\n",(Cores[c].Voices[v].ADSR.Phase>0)?"Playing":"Not Playing");
|
||||
fprintf(dump," - Block Sample: %d\n",Cores[c].Voices[v].SCurrent);
|
||||
}
|
||||
fprintf(dump,"#### END OF DUMP.\n\n");
|
||||
}
|
||||
fclose(dump);
|
||||
}
|
||||
|
||||
dump = fopen( "logs/effects.txt", "wt" );
|
||||
if (dump)
|
||||
{
|
||||
for(c=0;c<2;c++)
|
||||
{
|
||||
fprintf(dump,"#### CORE %d EFFECTS PROCESSOR DUMP.\n",c);
|
||||
fprintf(dump, " - Pitch: %x\n", Cores[c].Voices[v].Pitch);
|
||||
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, " - 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].VoiceGates[v].DryR ? "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].VoiceGates[v].WetR ? "Yes" : "No");
|
||||
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, " - Next Data Address: %x\n", Cores[c].Voices[v].NextA);
|
||||
fprintf(dump, " - Play Start Cycle: %d\n", Cores[c].Voices[v].PlayCycle);
|
||||
fprintf(dump, " - Play Status: %s\n", (Cores[c].Voices[v].ADSR.Phase > 0) ? "Playing" : "Not Playing");
|
||||
fprintf(dump, " - Block Sample: %d\n", Cores[c].Voices[v].SCurrent);
|
||||
}
|
||||
fprintf(dump, "#### END OF DUMP.\n\n");
|
||||
}
|
||||
fclose(dump);
|
||||
}
|
||||
|
||||
fprintf(dump," - IN_COEF_L: %x\n",Cores[c].Revb.IN_COEF_R);
|
||||
fprintf(dump," - IN_COEF_R: %x\n",Cores[c].Revb.IN_COEF_L);
|
||||
dump = fopen("logs/effects.txt", "wt");
|
||||
if (dump) {
|
||||
for (c = 0; c < 2; c++) {
|
||||
fprintf(dump, "#### CORE %d EFFECTS PROCESSOR DUMP.\n", c);
|
||||
|
||||
fprintf(dump," - FB_ALPHA: %x\n",Cores[c].Revb.FB_ALPHA);
|
||||
fprintf(dump," - FB_X: %x\n",Cores[c].Revb.FB_X);
|
||||
fprintf(dump," - FB_SRC_A: %x\n",Cores[c].Revb.FB_SRC_A);
|
||||
fprintf(dump," - FB_SRC_B: %x\n",Cores[c].Revb.FB_SRC_B);
|
||||
fprintf(dump, " - IN_COEF_L: %x\n", Cores[c].Revb.IN_COEF_R);
|
||||
fprintf(dump, " - IN_COEF_R: %x\n", Cores[c].Revb.IN_COEF_L);
|
||||
|
||||
fprintf(dump," - IIR_ALPHA: %x\n",Cores[c].Revb.IIR_ALPHA);
|
||||
fprintf(dump," - IIR_COEF: %x\n",Cores[c].Revb.IIR_COEF);
|
||||
fprintf(dump," - IIR_SRC_A0: %x\n",Cores[c].Revb.IIR_SRC_A0);
|
||||
fprintf(dump," - IIR_SRC_A1: %x\n",Cores[c].Revb.IIR_SRC_A1);
|
||||
fprintf(dump," - IIR_SRC_B1: %x\n",Cores[c].Revb.IIR_SRC_B0);
|
||||
fprintf(dump," - IIR_SRC_B0: %x\n",Cores[c].Revb.IIR_SRC_B1);
|
||||
fprintf(dump," - IIR_DEST_A0: %x\n",Cores[c].Revb.IIR_DEST_A0);
|
||||
fprintf(dump," - IIR_DEST_A1: %x\n",Cores[c].Revb.IIR_DEST_A1);
|
||||
fprintf(dump," - IIR_DEST_B0: %x\n",Cores[c].Revb.IIR_DEST_B0);
|
||||
fprintf(dump," - IIR_DEST_B1: %x\n",Cores[c].Revb.IIR_DEST_B1);
|
||||
fprintf(dump, " - FB_ALPHA: %x\n", Cores[c].Revb.FB_ALPHA);
|
||||
fprintf(dump, " - FB_X: %x\n", Cores[c].Revb.FB_X);
|
||||
fprintf(dump, " - FB_SRC_A: %x\n", Cores[c].Revb.FB_SRC_A);
|
||||
fprintf(dump, " - FB_SRC_B: %x\n", Cores[c].Revb.FB_SRC_B);
|
||||
|
||||
fprintf(dump," - ACC_COEF_A: %x\n",Cores[c].Revb.ACC_COEF_A);
|
||||
fprintf(dump," - ACC_COEF_B: %x\n",Cores[c].Revb.ACC_COEF_B);
|
||||
fprintf(dump," - ACC_COEF_C: %x\n",Cores[c].Revb.ACC_COEF_C);
|
||||
fprintf(dump," - ACC_COEF_D: %x\n",Cores[c].Revb.ACC_COEF_D);
|
||||
fprintf(dump," - ACC_SRC_A0: %x\n",Cores[c].Revb.ACC_SRC_A0);
|
||||
fprintf(dump," - ACC_SRC_A1: %x\n",Cores[c].Revb.ACC_SRC_A1);
|
||||
fprintf(dump," - ACC_SRC_B0: %x\n",Cores[c].Revb.ACC_SRC_B0);
|
||||
fprintf(dump," - ACC_SRC_B1: %x\n",Cores[c].Revb.ACC_SRC_B1);
|
||||
fprintf(dump," - ACC_SRC_C0: %x\n",Cores[c].Revb.ACC_SRC_C0);
|
||||
fprintf(dump," - ACC_SRC_C1: %x\n",Cores[c].Revb.ACC_SRC_C1);
|
||||
fprintf(dump," - ACC_SRC_D0: %x\n",Cores[c].Revb.ACC_SRC_D0);
|
||||
fprintf(dump," - ACC_SRC_D1: %x\n",Cores[c].Revb.ACC_SRC_D1);
|
||||
fprintf(dump, " - IIR_ALPHA: %x\n", Cores[c].Revb.IIR_ALPHA);
|
||||
fprintf(dump, " - IIR_COEF: %x\n", Cores[c].Revb.IIR_COEF);
|
||||
fprintf(dump, " - IIR_SRC_A0: %x\n", Cores[c].Revb.IIR_SRC_A0);
|
||||
fprintf(dump, " - IIR_SRC_A1: %x\n", Cores[c].Revb.IIR_SRC_A1);
|
||||
fprintf(dump, " - IIR_SRC_B1: %x\n", Cores[c].Revb.IIR_SRC_B0);
|
||||
fprintf(dump, " - IIR_SRC_B0: %x\n", Cores[c].Revb.IIR_SRC_B1);
|
||||
fprintf(dump, " - IIR_DEST_A0: %x\n", Cores[c].Revb.IIR_DEST_A0);
|
||||
fprintf(dump, " - IIR_DEST_A1: %x\n", Cores[c].Revb.IIR_DEST_A1);
|
||||
fprintf(dump, " - IIR_DEST_B0: %x\n", Cores[c].Revb.IIR_DEST_B0);
|
||||
fprintf(dump, " - IIR_DEST_B1: %x\n", Cores[c].Revb.IIR_DEST_B1);
|
||||
|
||||
fprintf(dump," - MIX_DEST_A0: %x\n",Cores[c].Revb.MIX_DEST_A0);
|
||||
fprintf(dump," - MIX_DEST_A1: %x\n",Cores[c].Revb.MIX_DEST_A1);
|
||||
fprintf(dump," - MIX_DEST_B0: %x\n",Cores[c].Revb.MIX_DEST_B0);
|
||||
fprintf(dump," - MIX_DEST_B1: %x\n",Cores[c].Revb.MIX_DEST_B1);
|
||||
fprintf(dump,"#### END OF DUMP.\n\n");
|
||||
}
|
||||
fclose(dump);
|
||||
}
|
||||
fprintf(dump, " - ACC_COEF_A: %x\n", Cores[c].Revb.ACC_COEF_A);
|
||||
fprintf(dump, " - ACC_COEF_B: %x\n", Cores[c].Revb.ACC_COEF_B);
|
||||
fprintf(dump, " - ACC_COEF_C: %x\n", Cores[c].Revb.ACC_COEF_C);
|
||||
fprintf(dump, " - ACC_COEF_D: %x\n", Cores[c].Revb.ACC_COEF_D);
|
||||
fprintf(dump, " - ACC_SRC_A0: %x\n", Cores[c].Revb.ACC_SRC_A0);
|
||||
fprintf(dump, " - ACC_SRC_A1: %x\n", Cores[c].Revb.ACC_SRC_A1);
|
||||
fprintf(dump, " - ACC_SRC_B0: %x\n", Cores[c].Revb.ACC_SRC_B0);
|
||||
fprintf(dump, " - ACC_SRC_B1: %x\n", Cores[c].Revb.ACC_SRC_B1);
|
||||
fprintf(dump, " - ACC_SRC_C0: %x\n", Cores[c].Revb.ACC_SRC_C0);
|
||||
fprintf(dump, " - ACC_SRC_C1: %x\n", Cores[c].Revb.ACC_SRC_C1);
|
||||
fprintf(dump, " - ACC_SRC_D0: %x\n", Cores[c].Revb.ACC_SRC_D0);
|
||||
fprintf(dump, " - ACC_SRC_D1: %x\n", Cores[c].Revb.ACC_SRC_D1);
|
||||
|
||||
fprintf(dump, " - MIX_DEST_A0: %x\n", Cores[c].Revb.MIX_DEST_A0);
|
||||
fprintf(dump, " - MIX_DEST_A1: %x\n", Cores[c].Revb.MIX_DEST_A1);
|
||||
fprintf(dump, " - MIX_DEST_B0: %x\n", Cores[c].Revb.MIX_DEST_B0);
|
||||
fprintf(dump, " - MIX_DEST_B1: %x\n", Cores[c].Revb.MIX_DEST_B1);
|
||||
fprintf(dump, "#### END OF DUMP.\n\n");
|
||||
}
|
||||
fclose(dump);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -26,40 +26,39 @@ extern void ConLog(const char *fmt, ...);
|
|||
|
||||
extern void DoFullDump();
|
||||
|
||||
extern FILE* OpenBinaryLog( const wxString& logfile );
|
||||
extern FILE* OpenLog( const wxString& logfile );
|
||||
extern FILE* OpenDump( const wxString& logfile );
|
||||
extern FILE *OpenBinaryLog(const wxString &logfile);
|
||||
extern FILE *OpenLog(const wxString &logfile);
|
||||
extern FILE *OpenDump(const wxString &logfile);
|
||||
|
||||
namespace WaveDump
|
||||
{
|
||||
enum CoreSourceType
|
||||
{
|
||||
// Core's input stream, usually pulled from ADMA streams.
|
||||
CoreSrc_Input = 0
|
||||
enum CoreSourceType {
|
||||
// Core's input stream, usually pulled from ADMA streams.
|
||||
CoreSrc_Input = 0,
|
||||
|
||||
// Output of the actual 24 input voices which have dry output enabled.
|
||||
, CoreSrc_DryVoiceMix
|
||||
// Output of the actual 24 input voices which have dry output enabled.
|
||||
CoreSrc_DryVoiceMix,
|
||||
|
||||
// Output of the actual 24 input voices that have wet output enabled.
|
||||
, CoreSrc_WetVoiceMix
|
||||
// Output of the actual 24 input voices that have wet output enabled.
|
||||
CoreSrc_WetVoiceMix,
|
||||
|
||||
// Wet mix including inputs and externals, prior to the application of reverb.
|
||||
, CoreSrc_PreReverb
|
||||
// Wet mix including inputs and externals, prior to the application of reverb.
|
||||
CoreSrc_PreReverb,
|
||||
|
||||
// Wet mix after reverb has turned it into a pile of garbly gook.
|
||||
, CoreSrc_PostReverb
|
||||
// Wet mix after reverb has turned it into a pile of garbly gook.
|
||||
CoreSrc_PostReverb,
|
||||
|
||||
// Final output of the core. For core 0, it's the feed into Core1.
|
||||
// For Core1, it's the feed into SndOut.
|
||||
, CoreSrc_External
|
||||
// Final output of the core. For core 0, it's the feed into Core1.
|
||||
// For Core1, it's the feed into SndOut.
|
||||
CoreSrc_External,
|
||||
|
||||
, CoreSrc_Count
|
||||
};
|
||||
CoreSrc_Count
|
||||
};
|
||||
|
||||
extern void Open();
|
||||
extern void Close();
|
||||
extern void WriteCore( uint coreidx, CoreSourceType src, s16 left, s16 right );
|
||||
extern void WriteCore( uint coreidx, CoreSourceType src, const StereoOut16& sample );
|
||||
extern void Open();
|
||||
extern void Close();
|
||||
extern void WriteCore(uint coreidx, CoreSourceType src, s16 left, s16 right);
|
||||
extern void WriteCore(uint coreidx, CoreSourceType src, const StereoOut16 &sample);
|
||||
}
|
||||
|
||||
using WaveDump::CoreSrc_Input;
|
||||
|
@ -69,4 +68,4 @@ using WaveDump::CoreSrc_PreReverb;
|
|||
using WaveDump::CoreSrc_PostReverb;
|
||||
using WaveDump::CoreSrc_External;
|
||||
|
||||
#endif // DEBUG_H_INCLUDED //
|
||||
#endif // DEBUG_H_INCLUDED //
|
||||
|
|
|
@ -23,131 +23,132 @@
|
|||
#include <string.h>
|
||||
|
||||
static const u8 sLogTable[256] = {
|
||||
0x00,0x3C,0x60,0x78,0x8C,0x9C,0xA8,0xB4,0xBE,0xC8,0xD0,0xD8,0xDE,0xE4,0xEA,0xF0,
|
||||
0xF6,0xFA,0xFE,0x04,0x08,0x0C,0x10,0x14,0x16,0x1A,0x1E,0x20,0x24,0x26,0x2A,0x2C,
|
||||
0x2E,0x32,0x34,0x36,0x38,0x3A,0x3E,0x40,0x42,0x44,0x46,0x48,0x4A,0x4C,0x4E,0x50,
|
||||
0x50,0x52,0x54,0x56,0x58,0x5A,0x5A,0x5C,0x5E,0x60,0x60,0x62,0x64,0x66,0x66,0x68,
|
||||
0x6A,0x6A,0x6C,0x6E,0x6E,0x70,0x70,0x72,0x74,0x74,0x76,0x76,0x78,0x7A,0x7A,0x7C,
|
||||
0x7C,0x7E,0x7E,0x80,0x80,0x82,0x82,0x84,0x84,0x86,0x86,0x88,0x88,0x8A,0x8A,0x8C,
|
||||
0x8C,0x8C,0x8E,0x8E,0x90,0x90,0x92,0x92,0x92,0x94,0x94,0x96,0x96,0x96,0x98,0x98,
|
||||
0x9A,0x9A,0x9A,0x9C,0x9C,0x9C,0x9E,0x9E,0xA0,0xA0,0xA0,0xA2,0xA2,0xA2,0xA4,0xA4,
|
||||
0xA4,0xA6,0xA6,0xA6,0xA8,0xA8,0xA8,0xAA,0xAA,0xAA,0xAC,0xAC,0xAC,0xAC,0xAE,0xAE,
|
||||
0xAE,0xB0,0xB0,0xB0,0xB2,0xB2,0xB2,0xB2,0xB4,0xB4,0xB4,0xB6,0xB6,0xB6,0xB6,0xB8,
|
||||
0xB8,0xB8,0xB8,0xBA,0xBA,0xBA,0xBC,0xBC,0xBC,0xBC,0xBE,0xBE,0xBE,0xBE,0xC0,0xC0,
|
||||
0xC0,0xC0,0xC2,0xC2,0xC2,0xC2,0xC2,0xC4,0xC4,0xC4,0xC4,0xC6,0xC6,0xC6,0xC6,0xC8,
|
||||
0xC8,0xC8,0xC8,0xC8,0xCA,0xCA,0xCA,0xCA,0xCC,0xCC,0xCC,0xCC,0xCC,0xCE,0xCE,0xCE,
|
||||
0xCE,0xCE,0xD0,0xD0,0xD0,0xD0,0xD0,0xD2,0xD2,0xD2,0xD2,0xD2,0xD4,0xD4,0xD4,0xD4,
|
||||
0xD4,0xD6,0xD6,0xD6,0xD6,0xD6,0xD8,0xD8,0xD8,0xD8,0xD8,0xD8,0xDA,0xDA,0xDA,0xDA,
|
||||
0xDA,0xDC,0xDC,0xDC,0xDC,0xDC,0xDC,0xDE,0xDE,0xDE,0xDE,0xDE,0xDE,0xE0,0xE0,0xE0,
|
||||
0x00, 0x3C, 0x60, 0x78, 0x8C, 0x9C, 0xA8, 0xB4, 0xBE, 0xC8, 0xD0, 0xD8, 0xDE, 0xE4, 0xEA, 0xF0,
|
||||
0xF6, 0xFA, 0xFE, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x16, 0x1A, 0x1E, 0x20, 0x24, 0x26, 0x2A, 0x2C,
|
||||
0x2E, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3E, 0x40, 0x42, 0x44, 0x46, 0x48, 0x4A, 0x4C, 0x4E, 0x50,
|
||||
0x50, 0x52, 0x54, 0x56, 0x58, 0x5A, 0x5A, 0x5C, 0x5E, 0x60, 0x60, 0x62, 0x64, 0x66, 0x66, 0x68,
|
||||
0x6A, 0x6A, 0x6C, 0x6E, 0x6E, 0x70, 0x70, 0x72, 0x74, 0x74, 0x76, 0x76, 0x78, 0x7A, 0x7A, 0x7C,
|
||||
0x7C, 0x7E, 0x7E, 0x80, 0x80, 0x82, 0x82, 0x84, 0x84, 0x86, 0x86, 0x88, 0x88, 0x8A, 0x8A, 0x8C,
|
||||
0x8C, 0x8C, 0x8E, 0x8E, 0x90, 0x90, 0x92, 0x92, 0x92, 0x94, 0x94, 0x96, 0x96, 0x96, 0x98, 0x98,
|
||||
0x9A, 0x9A, 0x9A, 0x9C, 0x9C, 0x9C, 0x9E, 0x9E, 0xA0, 0xA0, 0xA0, 0xA2, 0xA2, 0xA2, 0xA4, 0xA4,
|
||||
0xA4, 0xA6, 0xA6, 0xA6, 0xA8, 0xA8, 0xA8, 0xAA, 0xAA, 0xAA, 0xAC, 0xAC, 0xAC, 0xAC, 0xAE, 0xAE,
|
||||
0xAE, 0xB0, 0xB0, 0xB0, 0xB2, 0xB2, 0xB2, 0xB2, 0xB4, 0xB4, 0xB4, 0xB6, 0xB6, 0xB6, 0xB6, 0xB8,
|
||||
0xB8, 0xB8, 0xB8, 0xBA, 0xBA, 0xBA, 0xBC, 0xBC, 0xBC, 0xBC, 0xBE, 0xBE, 0xBE, 0xBE, 0xC0, 0xC0,
|
||||
0xC0, 0xC0, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC4, 0xC4, 0xC4, 0xC4, 0xC6, 0xC6, 0xC6, 0xC6, 0xC8,
|
||||
0xC8, 0xC8, 0xC8, 0xC8, 0xCA, 0xCA, 0xCA, 0xCA, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCE, 0xCE, 0xCE,
|
||||
0xCE, 0xCE, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD4, 0xD4, 0xD4, 0xD4,
|
||||
0xD4, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xDA, 0xDA, 0xDA, 0xDA,
|
||||
0xDA, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xE0, 0xE0, 0xE0,
|
||||
};
|
||||
|
||||
DPLII::DPLII( s32 lowpass_freq, s32 samplerate ) :
|
||||
LAccum( 0 ),
|
||||
RAccum( 0 ),
|
||||
ANum( 0 ),
|
||||
lpf_l( lowpass_freq, samplerate ),
|
||||
lpf_r( lowpass_freq, samplerate ),
|
||||
bufdone( 1 ),
|
||||
Gfl( 0 ),
|
||||
Gfr( 0 ),
|
||||
LMax( 0 ),
|
||||
RMax( 0 )
|
||||
DPLII::DPLII(s32 lowpass_freq, s32 samplerate)
|
||||
: LAccum(0)
|
||||
, RAccum(0)
|
||||
, ANum(0)
|
||||
, lpf_l(lowpass_freq, samplerate)
|
||||
, lpf_r(lowpass_freq, samplerate)
|
||||
, bufdone(1)
|
||||
, Gfl(0)
|
||||
, Gfr(0)
|
||||
, LMax(0)
|
||||
, RMax(0)
|
||||
{
|
||||
memset( LBuff, 0, sizeof( LBuff ) );
|
||||
memset( RBuff, 0, sizeof( RBuff ) );
|
||||
memset( spdif_data, 0, sizeof( spdif_data ) );
|
||||
memset(LBuff, 0, sizeof(LBuff));
|
||||
memset(RBuff, 0, sizeof(RBuff));
|
||||
memset(spdif_data, 0, sizeof(spdif_data));
|
||||
}
|
||||
|
||||
// Takes a single stereo input sample and translates it into six output samples
|
||||
// for 5.1 audio support on non-DPL2 hardware.
|
||||
void DPLII::Convert( s16 *obuffer, s32 ValL, s32 ValR )
|
||||
void DPLII::Convert(s16 *obuffer, s32 ValL, s32 ValR)
|
||||
{
|
||||
ValL >>= 2;
|
||||
ValR >>= 2;
|
||||
if(PlayMode&4)
|
||||
{
|
||||
spdif_get_samples(spdif_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
spdif_data[0]=0;
|
||||
spdif_data[1]=0;
|
||||
spdif_data[2]=0;
|
||||
spdif_data[3]=0;
|
||||
spdif_data[4]=0;
|
||||
spdif_data[5]=0;
|
||||
}
|
||||
ValL >>= 2;
|
||||
ValR >>= 2;
|
||||
if (PlayMode & 4) {
|
||||
spdif_get_samples(spdif_data);
|
||||
} else {
|
||||
spdif_data[0] = 0;
|
||||
spdif_data[1] = 0;
|
||||
spdif_data[2] = 0;
|
||||
spdif_data[3] = 0;
|
||||
spdif_data[4] = 0;
|
||||
spdif_data[5] = 0;
|
||||
}
|
||||
|
||||
//const u8 shift = SndOutVolumeShift;
|
||||
//const u8 shift = SndOutVolumeShift;
|
||||
|
||||
s32 XL = abs(ValL>>8);
|
||||
s32 XR = abs(ValR>>8);
|
||||
s32 XL = abs(ValL >> 8);
|
||||
s32 XR = abs(ValR >> 8);
|
||||
|
||||
if(XL>LMax) LMax = XL;
|
||||
if(XR>RMax) RMax = XR;
|
||||
if (XL > LMax)
|
||||
LMax = XL;
|
||||
if (XR > RMax)
|
||||
RMax = XR;
|
||||
|
||||
ANum++;
|
||||
if(ANum>=128)
|
||||
{
|
||||
ANum=0;
|
||||
LAccum = 1+((LAccum * 224 + LMax * 31)>>8);
|
||||
RAccum = 1+((RAccum * 224 + RMax * 31)>>8);
|
||||
ANum++;
|
||||
if (ANum >= 128) {
|
||||
ANum = 0;
|
||||
LAccum = 1 + ((LAccum * 224 + LMax * 31) >> 8);
|
||||
RAccum = 1 + ((RAccum * 224 + RMax * 31) >> 8);
|
||||
|
||||
LMax = 0;
|
||||
RMax = 0;
|
||||
LMax = 0;
|
||||
RMax = 0;
|
||||
|
||||
s32 Tfl=(RAccum)*255/(LAccum);
|
||||
s32 Tfr=(LAccum)*255/(RAccum);
|
||||
s32 Tfl = (RAccum)*255 / (LAccum);
|
||||
s32 Tfr = (LAccum)*255 / (RAccum);
|
||||
|
||||
int gMax = max(Tfl,Tfr);
|
||||
Tfl=Tfl*255/gMax;
|
||||
Tfr=Tfr*255/gMax;
|
||||
int gMax = max(Tfl, Tfr);
|
||||
Tfl = Tfl * 255 / gMax;
|
||||
Tfr = Tfr * 255 / gMax;
|
||||
|
||||
if(Tfl>255) Tfl=255;
|
||||
if(Tfr>255) Tfr=255;
|
||||
if(Tfl<1) Tfl=1;
|
||||
if(Tfr<1) Tfr=1;
|
||||
if (Tfl > 255)
|
||||
Tfl = 255;
|
||||
if (Tfr > 255)
|
||||
Tfr = 255;
|
||||
if (Tfl < 1)
|
||||
Tfl = 1;
|
||||
if (Tfr < 1)
|
||||
Tfr = 1;
|
||||
|
||||
Gfl = (Gfl * 200 + Tfl * 56)>>8;
|
||||
Gfr = (Gfr * 200 + Tfr * 56)>>8;
|
||||
Gfl = (Gfl * 200 + Tfl * 56) >> 8;
|
||||
Gfr = (Gfr * 200 + Tfr * 56) >> 8;
|
||||
}
|
||||
|
||||
}
|
||||
s32 L, R, C, LFE, SL, SR, LL, LR;
|
||||
|
||||
s32 L,R,C,LFE,SL,SR,LL,LR;
|
||||
extern double pow_2_31;
|
||||
LL = (s32)(lpf_l.sample((ValL >> 4) / pow_2_31) * pow_2_31);
|
||||
LR = (s32)(lpf_r.sample((ValR >> 4) / pow_2_31) * pow_2_31);
|
||||
LFE = (LL + LR) >> 4;
|
||||
|
||||
extern double pow_2_31;
|
||||
LL = (s32)(lpf_l.sample((ValL>>4)/pow_2_31)*pow_2_31);
|
||||
LR = (s32)(lpf_r.sample((ValR>>4)/pow_2_31)*pow_2_31);
|
||||
LFE = (LL + LR)>>4;
|
||||
C = (ValL + ValR) >> 1; //16.8
|
||||
|
||||
C=(ValL+ValR)>>1; //16.8
|
||||
ValL -= C; //16.8
|
||||
ValR -= C; //16.8
|
||||
|
||||
ValL-=C;//16.8
|
||||
ValR-=C;//16.8
|
||||
L = ValL >> 8; //16.0
|
||||
R = ValR >> 8; //16.0
|
||||
C = C >> 8; //16.0
|
||||
|
||||
L=ValL>>8; //16.0
|
||||
R=ValR>>8; //16.0
|
||||
C=C>>8; //16.0
|
||||
const s32 Cfl = 1 + sLogTable[Gfl];
|
||||
const s32 Cfr = 1 + sLogTable[Gfr];
|
||||
|
||||
const s32 Cfl = 1 + sLogTable[Gfl];
|
||||
const s32 Cfr = 1 + sLogTable[Gfr];
|
||||
const s32 VL = (ValL >> 4) * Cfl; //16.12
|
||||
const s32 VR = (ValR >> 4) * Cfr;
|
||||
|
||||
const s32 VL = (ValL>>4) * Cfl; //16.12
|
||||
const s32 VR = (ValR>>4) * Cfr;
|
||||
const s32 SC = (VL - VR) >> 15;
|
||||
|
||||
const s32 SC = (VL-VR)>>15;
|
||||
SL = (((VR / 148 - VL / 209) >> 4) * Cfr) >> 8;
|
||||
SR = (((VR / 209 - VL / 148) >> 4) * Cfl) >> 8;
|
||||
|
||||
SL = (((VR/148 - VL/209)>>4)*Cfr)>>8;
|
||||
SR = (((VR/209 - VL/148)>>4)*Cfl)>>8;
|
||||
int AddCX = (C * Config_DSound51.AddCLR) >> 8;
|
||||
|
||||
int AddCX = (C * Config_DSound51.AddCLR)>>8;
|
||||
|
||||
obuffer[0]=spdif_data[0] + (((L * Config_DSound51.GainL ))>>8) + AddCX;
|
||||
obuffer[1]=spdif_data[1] + (((R * Config_DSound51.GainR ))>>8) + AddCX;
|
||||
obuffer[2]=spdif_data[2] + (((C * Config_DSound51.GainC ))>>8); // - AddCX;
|
||||
obuffer[3]=spdif_data[3] + (((LFE * Config_DSound51.GainLFE))>>8);
|
||||
obuffer[4]=spdif_data[4] + (((SL * Config_DSound51.GainSL ))>>8);
|
||||
obuffer[5]=spdif_data[5] + (((SR * Config_DSound51.GainSR ))>>8);
|
||||
obuffer[0] = spdif_data[0] + (((L * Config_DSound51.GainL)) >> 8) + AddCX;
|
||||
obuffer[1] = spdif_data[1] + (((R * Config_DSound51.GainR)) >> 8) + AddCX;
|
||||
obuffer[2] = spdif_data[2] + (((C * Config_DSound51.GainC)) >> 8); // - AddCX;
|
||||
obuffer[3] = spdif_data[3] + (((LFE * Config_DSound51.GainLFE)) >> 8);
|
||||
obuffer[4] = spdif_data[4] + (((SL * Config_DSound51.GainSL)) >> 8);
|
||||
obuffer[5] = spdif_data[5] + (((SR * Config_DSound51.GainSR)) >> 8);
|
||||
|
||||
#if 0
|
||||
if( UseAveraging )
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -21,154 +21,154 @@
|
|||
#include "Global.h"
|
||||
|
||||
static const u8 sLogTable[256] = {
|
||||
0x00,0x3C,0x60,0x78,0x8C,0x9C,0xA8,0xB4,0xBE,0xC8,0xD0,0xD8,0xDE,0xE4,0xEA,0xF0,
|
||||
0xF6,0xFA,0xFE,0x04,0x08,0x0C,0x10,0x14,0x16,0x1A,0x1E,0x20,0x24,0x26,0x2A,0x2C,
|
||||
0x2E,0x32,0x34,0x36,0x38,0x3A,0x3E,0x40,0x42,0x44,0x46,0x48,0x4A,0x4C,0x4E,0x50,
|
||||
0x50,0x52,0x54,0x56,0x58,0x5A,0x5A,0x5C,0x5E,0x60,0x60,0x62,0x64,0x66,0x66,0x68,
|
||||
0x6A,0x6A,0x6C,0x6E,0x6E,0x70,0x70,0x72,0x74,0x74,0x76,0x76,0x78,0x7A,0x7A,0x7C,
|
||||
0x7C,0x7E,0x7E,0x80,0x80,0x82,0x82,0x84,0x84,0x86,0x86,0x88,0x88,0x8A,0x8A,0x8C,
|
||||
0x8C,0x8C,0x8E,0x8E,0x90,0x90,0x92,0x92,0x92,0x94,0x94,0x96,0x96,0x96,0x98,0x98,
|
||||
0x9A,0x9A,0x9A,0x9C,0x9C,0x9C,0x9E,0x9E,0xA0,0xA0,0xA0,0xA2,0xA2,0xA2,0xA4,0xA4,
|
||||
0xA4,0xA6,0xA6,0xA6,0xA8,0xA8,0xA8,0xAA,0xAA,0xAA,0xAC,0xAC,0xAC,0xAC,0xAE,0xAE,
|
||||
0xAE,0xB0,0xB0,0xB0,0xB2,0xB2,0xB2,0xB2,0xB4,0xB4,0xB4,0xB6,0xB6,0xB6,0xB6,0xB8,
|
||||
0xB8,0xB8,0xB8,0xBA,0xBA,0xBA,0xBC,0xBC,0xBC,0xBC,0xBE,0xBE,0xBE,0xBE,0xC0,0xC0,
|
||||
0xC0,0xC0,0xC2,0xC2,0xC2,0xC2,0xC2,0xC4,0xC4,0xC4,0xC4,0xC6,0xC6,0xC6,0xC6,0xC8,
|
||||
0xC8,0xC8,0xC8,0xC8,0xCA,0xCA,0xCA,0xCA,0xCC,0xCC,0xCC,0xCC,0xCC,0xCE,0xCE,0xCE,
|
||||
0xCE,0xCE,0xD0,0xD0,0xD0,0xD0,0xD0,0xD2,0xD2,0xD2,0xD2,0xD2,0xD4,0xD4,0xD4,0xD4,
|
||||
0xD4,0xD6,0xD6,0xD6,0xD6,0xD6,0xD8,0xD8,0xD8,0xD8,0xD8,0xD8,0xDA,0xDA,0xDA,0xDA,
|
||||
0xDA,0xDC,0xDC,0xDC,0xDC,0xDC,0xDC,0xDE,0xDE,0xDE,0xDE,0xDE,0xDE,0xE0,0xE0,0xE0,
|
||||
0x00, 0x3C, 0x60, 0x78, 0x8C, 0x9C, 0xA8, 0xB4, 0xBE, 0xC8, 0xD0, 0xD8, 0xDE, 0xE4, 0xEA, 0xF0,
|
||||
0xF6, 0xFA, 0xFE, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x16, 0x1A, 0x1E, 0x20, 0x24, 0x26, 0x2A, 0x2C,
|
||||
0x2E, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3E, 0x40, 0x42, 0x44, 0x46, 0x48, 0x4A, 0x4C, 0x4E, 0x50,
|
||||
0x50, 0x52, 0x54, 0x56, 0x58, 0x5A, 0x5A, 0x5C, 0x5E, 0x60, 0x60, 0x62, 0x64, 0x66, 0x66, 0x68,
|
||||
0x6A, 0x6A, 0x6C, 0x6E, 0x6E, 0x70, 0x70, 0x72, 0x74, 0x74, 0x76, 0x76, 0x78, 0x7A, 0x7A, 0x7C,
|
||||
0x7C, 0x7E, 0x7E, 0x80, 0x80, 0x82, 0x82, 0x84, 0x84, 0x86, 0x86, 0x88, 0x88, 0x8A, 0x8A, 0x8C,
|
||||
0x8C, 0x8C, 0x8E, 0x8E, 0x90, 0x90, 0x92, 0x92, 0x92, 0x94, 0x94, 0x96, 0x96, 0x96, 0x98, 0x98,
|
||||
0x9A, 0x9A, 0x9A, 0x9C, 0x9C, 0x9C, 0x9E, 0x9E, 0xA0, 0xA0, 0xA0, 0xA2, 0xA2, 0xA2, 0xA4, 0xA4,
|
||||
0xA4, 0xA6, 0xA6, 0xA6, 0xA8, 0xA8, 0xA8, 0xAA, 0xAA, 0xAA, 0xAC, 0xAC, 0xAC, 0xAC, 0xAE, 0xAE,
|
||||
0xAE, 0xB0, 0xB0, 0xB0, 0xB2, 0xB2, 0xB2, 0xB2, 0xB4, 0xB4, 0xB4, 0xB6, 0xB6, 0xB6, 0xB6, 0xB8,
|
||||
0xB8, 0xB8, 0xB8, 0xBA, 0xBA, 0xBA, 0xBC, 0xBC, 0xBC, 0xBC, 0xBE, 0xBE, 0xBE, 0xBE, 0xC0, 0xC0,
|
||||
0xC0, 0xC0, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC4, 0xC4, 0xC4, 0xC4, 0xC6, 0xC6, 0xC6, 0xC6, 0xC8,
|
||||
0xC8, 0xC8, 0xC8, 0xC8, 0xCA, 0xCA, 0xCA, 0xCA, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCE, 0xCE, 0xCE,
|
||||
0xCE, 0xCE, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD4, 0xD4, 0xD4, 0xD4,
|
||||
0xD4, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xDA, 0xDA, 0xDA, 0xDA,
|
||||
0xDA, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xE0, 0xE0, 0xE0,
|
||||
};
|
||||
|
||||
static float Gfl=0,Gfr=0;
|
||||
static float LMax=0,RMax=0;
|
||||
static float Gfl = 0, Gfr = 0;
|
||||
static float LMax = 0, RMax = 0;
|
||||
|
||||
static float AccL=0;
|
||||
static float AccR=0;
|
||||
static float AccL = 0;
|
||||
static float AccR = 0;
|
||||
|
||||
const float Scale = 4294967296.0f; // tweak this value to change the overall output volume
|
||||
const float Scale = 4294967296.0f; // tweak this value to change the overall output volume
|
||||
|
||||
const float GainL = 0.80f * Scale;
|
||||
const float GainR = 0.80f * Scale;
|
||||
const float GainL = 0.80f * Scale;
|
||||
const float GainR = 0.80f * Scale;
|
||||
|
||||
const float GainC = 0.75f * Scale;
|
||||
const float GainC = 0.75f * Scale;
|
||||
|
||||
const float GainSL = 0.90f * Scale;
|
||||
const float GainSR = 0.90f * Scale;
|
||||
|
||||
const float GainLFE= 0.90f * Scale;
|
||||
const float GainLFE = 0.90f * Scale;
|
||||
|
||||
const float AddCLR = 0.20f * Scale; // Stereo expansion
|
||||
const float AddCLR = 0.20f * Scale; // Stereo expansion
|
||||
|
||||
extern void ResetDplIIDecoder()
|
||||
{
|
||||
Gfl=0;
|
||||
Gfr=0;
|
||||
LMax=0;
|
||||
RMax=0;
|
||||
AccL=0;
|
||||
AccR=0;
|
||||
Gfl = 0;
|
||||
Gfr = 0;
|
||||
LMax = 0;
|
||||
RMax = 0;
|
||||
AccL = 0;
|
||||
AccR = 0;
|
||||
}
|
||||
|
||||
void ProcessDplIISample32( const StereoOut32& src, Stereo51Out32DplII * s)
|
||||
void ProcessDplIISample32(const StereoOut32 &src, Stereo51Out32DplII *s)
|
||||
{
|
||||
float IL = src.Left / (float)(1<<(SndOutVolumeShift+16));
|
||||
float IR = src.Right / (float)(1<<(SndOutVolumeShift+16));
|
||||
float IL = src.Left / (float)(1 << (SndOutVolumeShift + 16));
|
||||
float IR = src.Right / (float)(1 << (SndOutVolumeShift + 16));
|
||||
|
||||
// Calculate center channel and LFE
|
||||
float C = (IL+IR) * 0.5f;
|
||||
float SUB = C; // no need to lowpass, the speaker amplifier should take care of it
|
||||
// Calculate center channel and LFE
|
||||
float C = (IL + IR) * 0.5f;
|
||||
float SUB = C; // no need to lowpass, the speaker amplifier should take care of it
|
||||
|
||||
float L = IL - C; // Effective L/R data
|
||||
float R = IR - C;
|
||||
float L = IL - C; // Effective L/R data
|
||||
float R = IR - C;
|
||||
|
||||
// Peak L/R
|
||||
float PL = std::abs(L);
|
||||
float PR = std::abs(R);
|
||||
// Peak L/R
|
||||
float PL = std::abs(L);
|
||||
float PR = std::abs(R);
|
||||
|
||||
AccL += (PL-AccL)*0.1f;
|
||||
AccR += (PR-AccR)*0.1f;
|
||||
|
||||
// Calculate power balance
|
||||
float Balance = (AccR-AccL); // -1 .. 1
|
||||
AccL += (PL - AccL) * 0.1f;
|
||||
AccR += (PR - AccR) * 0.1f;
|
||||
|
||||
// If the power levels are different, then the audio is meant for the front speakers
|
||||
float Frontness = std::abs(Balance);
|
||||
float Rearness = 1-Frontness; // And the other way around
|
||||
// Calculate power balance
|
||||
float Balance = (AccR - AccL); // -1 .. 1
|
||||
|
||||
// Equalize the power levels for L/R
|
||||
float B = std::min(0.9f,std::max(-0.9f,Balance));
|
||||
// If the power levels are different, then the audio is meant for the front speakers
|
||||
float Frontness = std::abs(Balance);
|
||||
float Rearness = 1 - Frontness; // And the other way around
|
||||
|
||||
float VL = L / (1-B); // if B>0, it means R>L, so increase L, else decrease L
|
||||
float VR = R / (1+B); // vice-versa
|
||||
// Equalize the power levels for L/R
|
||||
float B = std::min(0.9f, std::max(-0.9f, Balance));
|
||||
|
||||
// 1.73+1.22 = 2.94; 2.94 = 0.34 = 0.9996; Close enough.
|
||||
// The range for VL/VR is approximately 0..1,
|
||||
// But in the cases where VL/VR are > 0.5, Rearness is 0 so it should never overflow.
|
||||
const float RearScale = 0.34f * 2;
|
||||
float VL = L / (1 - B); // if B>0, it means R>L, so increase L, else decrease L
|
||||
float VR = R / (1 + B); // vice-versa
|
||||
|
||||
float SL = (VR*1.73f - VL*1.22f) * RearScale * Rearness;
|
||||
float SR = (VR*1.22f - VL*1.73f) * RearScale * Rearness;
|
||||
// Possible experiment: Play with stereo expension levels on rear
|
||||
// 1.73+1.22 = 2.94; 2.94 = 0.34 = 0.9996; Close enough.
|
||||
// The range for VL/VR is approximately 0..1,
|
||||
// But in the cases where VL/VR are > 0.5, Rearness is 0 so it should never overflow.
|
||||
const float RearScale = 0.34f * 2;
|
||||
|
||||
// Adjust the volume of the front speakers based on what we calculated above
|
||||
L *= Frontness;
|
||||
R *= Frontness;
|
||||
|
||||
s32 CX = (s32)(C * AddCLR);
|
||||
float SL = (VR * 1.73f - VL * 1.22f) * RearScale * Rearness;
|
||||
float SR = (VR * 1.22f - VL * 1.73f) * RearScale * Rearness;
|
||||
// Possible experiment: Play with stereo expension levels on rear
|
||||
|
||||
s->Left = (s32)(L * GainL ) + CX;
|
||||
s->Right = (s32)(R * GainR ) + CX;
|
||||
s->Center = (s32)(C * GainC );
|
||||
s->LFE = (s32)(SUB * GainLFE);
|
||||
s->LeftBack = (s32)(SL * GainSL );
|
||||
s->RightBack = (s32)(SR * GainSR );
|
||||
// Adjust the volume of the front speakers based on what we calculated above
|
||||
L *= Frontness;
|
||||
R *= Frontness;
|
||||
|
||||
s32 CX = (s32)(C * AddCLR);
|
||||
|
||||
s->Left = (s32)(L * GainL) + CX;
|
||||
s->Right = (s32)(R * GainR) + CX;
|
||||
s->Center = (s32)(C * GainC);
|
||||
s->LFE = (s32)(SUB * GainLFE);
|
||||
s->LeftBack = (s32)(SL * GainSL);
|
||||
s->RightBack = (s32)(SR * GainSR);
|
||||
}
|
||||
|
||||
void ProcessDplIISample16( const StereoOut32& src, Stereo51Out16DplII * s)
|
||||
void ProcessDplIISample16(const StereoOut32 &src, Stereo51Out16DplII *s)
|
||||
{
|
||||
Stereo51Out32DplII ss;
|
||||
ProcessDplIISample32(src, &ss);
|
||||
Stereo51Out32DplII ss;
|
||||
ProcessDplIISample32(src, &ss);
|
||||
|
||||
s->Left = ss.Left >> 16;
|
||||
s->Right = ss.Right >> 16;
|
||||
s->Center = ss.Center >> 16;
|
||||
s->LFE = ss.LFE >> 16;
|
||||
s->LeftBack = ss.LeftBack >> 16;
|
||||
s->RightBack = ss.RightBack >> 16;
|
||||
s->Left = ss.Left >> 16;
|
||||
s->Right = ss.Right >> 16;
|
||||
s->Center = ss.Center >> 16;
|
||||
s->LFE = ss.LFE >> 16;
|
||||
s->LeftBack = ss.LeftBack >> 16;
|
||||
s->RightBack = ss.RightBack >> 16;
|
||||
}
|
||||
|
||||
void ProcessDplSample32( const StereoOut32& src, Stereo51Out32Dpl * s)
|
||||
void ProcessDplSample32(const StereoOut32 &src, Stereo51Out32Dpl *s)
|
||||
{
|
||||
float ValL = src.Left / (float)(1<<(SndOutVolumeShift+16));
|
||||
float ValR = src.Right / (float)(1<<(SndOutVolumeShift+16));
|
||||
float ValL = src.Left / (float)(1 << (SndOutVolumeShift + 16));
|
||||
float ValR = src.Right / (float)(1 << (SndOutVolumeShift + 16));
|
||||
|
||||
float C = (ValL+ValR)*0.5f; //+15.8
|
||||
float S = (ValL-ValR)*0.5f;
|
||||
float C = (ValL + ValR) * 0.5f; //+15.8
|
||||
float S = (ValL - ValR) * 0.5f;
|
||||
|
||||
float L=ValL-C; //+15.8
|
||||
float R=ValR-C;
|
||||
float L = ValL - C; //+15.8
|
||||
float R = ValR - C;
|
||||
|
||||
float SUB = C;
|
||||
|
||||
s32 CX = (s32)(C * AddCLR); // +15.16
|
||||
float SUB = C;
|
||||
|
||||
s->Left = (s32)(L * GainL ) + CX; // +15.16 = +31, can grow to +32 if (GainL + AddCLR)>255
|
||||
s->Right = (s32)(R * GainR ) + CX;
|
||||
s->Center = (s32)(C * GainC ); // +15.16 = +31
|
||||
s->LFE = (s32)(SUB * GainLFE);
|
||||
s->LeftBack = (s32)(S * GainSL );
|
||||
s->RightBack = (s32)(S * GainSR );
|
||||
s32 CX = (s32)(C * AddCLR); // +15.16
|
||||
|
||||
s->Left = (s32)(L * GainL) + CX; // +15.16 = +31, can grow to +32 if (GainL + AddCLR)>255
|
||||
s->Right = (s32)(R * GainR) + CX;
|
||||
s->Center = (s32)(C * GainC); // +15.16 = +31
|
||||
s->LFE = (s32)(SUB * GainLFE);
|
||||
s->LeftBack = (s32)(S * GainSL);
|
||||
s->RightBack = (s32)(S * GainSR);
|
||||
}
|
||||
|
||||
void ProcessDplSample16( const StereoOut32& src, Stereo51Out16Dpl * s)
|
||||
void ProcessDplSample16(const StereoOut32 &src, Stereo51Out16Dpl *s)
|
||||
{
|
||||
Stereo51Out32Dpl ss;
|
||||
ProcessDplSample32(src, &ss);
|
||||
Stereo51Out32Dpl ss;
|
||||
ProcessDplSample32(src, &ss);
|
||||
|
||||
s->Left = ss.Left >> 16;
|
||||
s->Right = ss.Right >> 16;
|
||||
s->Center = ss.Center >> 16;
|
||||
s->LFE = ss.LFE >> 16;
|
||||
s->LeftBack = ss.LeftBack >> 16;
|
||||
s->RightBack = ss.RightBack >> 16;
|
||||
s->Left = ss.Left >> 16;
|
||||
s->Right = ss.Right >> 16;
|
||||
s->Center = ss.Center >> 16;
|
||||
s->LFE = ss.LFE >> 16;
|
||||
s->LeftBack = ss.LeftBack >> 16;
|
||||
s->RightBack = ss.RightBack >> 16;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ struct V_Core;
|
|||
|
||||
namespace soundtouch
|
||||
{
|
||||
class SoundTouch;
|
||||
class SoundTouch;
|
||||
}
|
||||
|
||||
#include <assert.h>
|
||||
|
@ -47,8 +47,8 @@ namespace soundtouch
|
|||
|
||||
namespace VersionInfo
|
||||
{
|
||||
static const u8 Release = 2;
|
||||
static const u8 Revision = 0; // increase that with each version
|
||||
static const u8 Release = 2;
|
||||
static const u8 Revision = 0; // increase that with each version
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -58,16 +58,16 @@ namespace VersionInfo
|
|||
#undef min
|
||||
#undef max
|
||||
|
||||
template< typename T >
|
||||
static __forceinline void Clampify( T& src, T min, T max )
|
||||
template <typename T>
|
||||
static __forceinline void Clampify(T &src, T min, T max)
|
||||
{
|
||||
src = std::min( std::max( src, min ), max );
|
||||
src = std::min(std::max(src, min), max);
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
static __forceinline T GetClamped( T src, T min, T max )
|
||||
template <typename T>
|
||||
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);
|
||||
}
|
||||
|
||||
#ifdef __WXMAC__
|
||||
|
@ -83,13 +83,13 @@ extern void SysMessage(const wchar_t *fmt, ...);
|
|||
// Abbreviated macros for dev/debug only consoles and msgboxes.
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
# define DevMsg MsgBox
|
||||
#define DevMsg MsgBox
|
||||
#else
|
||||
# define DevMsg
|
||||
#define DevMsg
|
||||
#endif
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
# define SPU2_LOG
|
||||
#define SPU2_LOG
|
||||
#endif
|
||||
|
||||
// Uncomment to enable debug keys on numpad (0 to 5)
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Dialogs.h"
|
||||
#include "Dialogs.h"
|
||||
|
||||
void AboutBox()
|
||||
{
|
||||
SysMessage("Yay: Aboutbox.");
|
||||
SysMessage("Yay: Aboutbox.");
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Adapted from ZeroSPU2 code by Zerofrog. Heavily modified by Arcum42.
|
||||
// Adapted from ZeroSPU2 code by Zerofrog. Heavily modified by Arcum42.
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
|
@ -24,241 +24,229 @@
|
|||
#include "Global.h"
|
||||
#include "Alsa.h"
|
||||
#include "SndOut.h"
|
||||
|
||||
|
||||
// Does not work, except as effectively a null plugin.
|
||||
class AlsaMod: public SndOutModule
|
||||
class AlsaMod : public SndOutModule
|
||||
{
|
||||
protected:
|
||||
static const int PacketsPerBuffer = 1; // increase this if ALSA can't keep up with 512-sample packets
|
||||
static const int MAX_BUFFER_COUNT = 4;
|
||||
static const int NumBuffers = 4; // TODO: this should be configurable someday -- lower values reduce latency.
|
||||
unsigned int pspeed;
|
||||
static const int PacketsPerBuffer = 1; // increase this if ALSA can't keep up with 512-sample packets
|
||||
static const int MAX_BUFFER_COUNT = 4;
|
||||
static const int NumBuffers = 4; // TODO: this should be configurable someday -- lower values reduce latency.
|
||||
unsigned int pspeed;
|
||||
|
||||
snd_pcm_t *handle;
|
||||
snd_pcm_uframes_t buffer_size;
|
||||
snd_async_handler_t *pcm_callback;
|
||||
snd_pcm_t *handle;
|
||||
snd_pcm_uframes_t buffer_size;
|
||||
snd_async_handler_t *pcm_callback;
|
||||
|
||||
uint period_time;
|
||||
uint buffer_time;
|
||||
uint period_time;
|
||||
uint buffer_time;
|
||||
|
||||
protected:
|
||||
// Invoked by the static ExternalCallback method below.
|
||||
void _InternalCallback()
|
||||
{
|
||||
snd_pcm_sframes_t avail;
|
||||
fprintf(stderr,"* SPU2-X:Iz in your internal callback.\n");
|
||||
// Invoked by the static ExternalCallback method below.
|
||||
void _InternalCallback()
|
||||
{
|
||||
snd_pcm_sframes_t avail;
|
||||
fprintf(stderr, "* SPU2-X:Iz in your internal callback.\n");
|
||||
|
||||
avail = snd_pcm_avail_update( handle );
|
||||
while (avail >= (int)period_time )
|
||||
{
|
||||
StereoOut16 buff[PacketsPerBuffer * SndOutPacketSize];
|
||||
StereoOut16* p1 = buff;
|
||||
avail = snd_pcm_avail_update(handle);
|
||||
while (avail >= (int)period_time) {
|
||||
StereoOut16 buff[PacketsPerBuffer * SndOutPacketSize];
|
||||
StereoOut16 *p1 = buff;
|
||||
|
||||
for( int p=0; p<PacketsPerBuffer; p++, p1+=SndOutPacketSize )
|
||||
SndBuffer::ReadSamples( p1 );
|
||||
for (int p = 0; p < PacketsPerBuffer; p++, p1 += SndOutPacketSize)
|
||||
SndBuffer::ReadSamples(p1);
|
||||
|
||||
snd_pcm_writei( handle, buff, period_time );
|
||||
avail = snd_pcm_avail_update(handle);
|
||||
}
|
||||
}
|
||||
snd_pcm_writei(handle, buff, period_time);
|
||||
avail = snd_pcm_avail_update(handle);
|
||||
}
|
||||
}
|
||||
|
||||
// Preps and invokes the _InternalCallback above. This provides a cdecl-compliant
|
||||
// entry point for our C++ified object state. :)
|
||||
static void ExternalCallback( snd_async_handler_t *pcm_call)
|
||||
{
|
||||
fprintf(stderr,"* SPU2-X:Iz in your external callback.\n");
|
||||
AlsaMod *data = (AlsaMod*)snd_async_handler_get_callback_private( pcm_call );
|
||||
// Preps and invokes the _InternalCallback above. This provides a cdecl-compliant
|
||||
// entry point for our C++ified object state. :)
|
||||
static void ExternalCallback(snd_async_handler_t *pcm_call)
|
||||
{
|
||||
fprintf(stderr, "* SPU2-X:Iz in your external callback.\n");
|
||||
AlsaMod *data = (AlsaMod *)snd_async_handler_get_callback_private(pcm_call);
|
||||
|
||||
pxAssume( data != NULL );
|
||||
//pxAssume( data->handle == snd_async_handler_get_pcm(pcm_call) );
|
||||
pxAssume(data != NULL);
|
||||
//pxAssume( data->handle == snd_async_handler_get_pcm(pcm_call) );
|
||||
|
||||
// Not sure if we just need an assert, or something like this:
|
||||
if (data->handle != snd_async_handler_get_pcm(pcm_call))
|
||||
{
|
||||
fprintf(stderr,"* SPU2-X: Failed to handle sound.\n");
|
||||
return;
|
||||
}
|
||||
// Not sure if we just need an assert, or something like this:
|
||||
if (data->handle != snd_async_handler_get_pcm(pcm_call)) {
|
||||
fprintf(stderr, "* SPU2-X: Failed to handle sound.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
data->_InternalCallback();
|
||||
}
|
||||
data->_InternalCallback();
|
||||
}
|
||||
|
||||
public:
|
||||
s32 Init()
|
||||
{
|
||||
//fprintf(stderr,"* SPU2-X: Initing Alsa\n");
|
||||
snd_pcm_hw_params_t *hwparams;
|
||||
snd_pcm_sw_params_t *swparams;
|
||||
snd_pcm_status_t *status;
|
||||
int pchannels = 2;
|
||||
snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
|
||||
|
||||
s32 Init()
|
||||
{
|
||||
//fprintf(stderr,"* SPU2-X: Initing Alsa\n");
|
||||
snd_pcm_hw_params_t *hwparams;
|
||||
snd_pcm_sw_params_t *swparams;
|
||||
snd_pcm_status_t *status;
|
||||
int pchannels = 2;
|
||||
snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
|
||||
handle = NULL;
|
||||
pcm_callback = NULL;
|
||||
pspeed = SAMPLE_RATE;
|
||||
|
||||
handle = NULL;
|
||||
pcm_callback = NULL;
|
||||
pspeed = SAMPLE_RATE;
|
||||
// buffer time and period time are in microseconds...
|
||||
// (don't simplify the equation below -- it'll just cause integer rounding errors.
|
||||
period_time = (SndOutPacketSize * 1000) / (SampleRate / 1000);
|
||||
buffer_time = period_time * NumBuffers;
|
||||
|
||||
// buffer time and period time are in microseconds...
|
||||
// (don't simplify the equation below -- it'll just cause integer rounding errors.
|
||||
period_time = (SndOutPacketSize*1000) / (SampleRate / 1000);
|
||||
buffer_time = period_time * NumBuffers;
|
||||
int err;
|
||||
|
||||
int err;
|
||||
err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, SND_PCM_ASYNC /*| SND_PCM_NONBLOCK*/);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Audio open error: %s\n", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, SND_PCM_ASYNC /*| SND_PCM_NONBLOCK*/);
|
||||
if(err < 0)
|
||||
{
|
||||
fprintf(stderr,"Audio open error: %s\n", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
err = snd_pcm_nonblock(handle, 0);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Can't set blocking mode: %s\n", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = snd_pcm_nonblock(handle, 0);
|
||||
if(err < 0)
|
||||
{
|
||||
fprintf(stderr,"Can't set blocking mode: %s\n", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
snd_pcm_hw_params_alloca(&hwparams);
|
||||
snd_pcm_sw_params_alloca(&swparams);
|
||||
|
||||
snd_pcm_hw_params_alloca(&hwparams);
|
||||
snd_pcm_sw_params_alloca(&swparams);
|
||||
err = snd_pcm_hw_params_any(handle, hwparams);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Broken configuration for this PCM: %s\n", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_params_any(handle, hwparams);
|
||||
if (err < 0)
|
||||
{
|
||||
fprintf(stderr,"Broken configuration for this PCM: %s\n", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Access type not available: %s\n", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
|
||||
if (err < 0)
|
||||
{
|
||||
fprintf(stderr,"Access type not available: %s\n", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
err = snd_pcm_hw_params_set_format(handle, hwparams, format);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Sample format not available: %s\n", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_params_set_format(handle, hwparams, format);
|
||||
if (err < 0)
|
||||
{
|
||||
fprintf(stderr,"Sample format not available: %s\n", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
err = snd_pcm_hw_params_set_channels(handle, hwparams, pchannels);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Channels count not available: %s\n", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &pspeed, 0);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Rate not available: %s\n", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_params_set_channels(handle, hwparams, pchannels);
|
||||
if (err < 0)
|
||||
{
|
||||
fprintf(stderr,"Channels count not available: %s\n", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &pspeed, 0);
|
||||
if (err < 0)
|
||||
{
|
||||
fprintf(stderr,"Rate not available: %s\n", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, 0);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Buffer time error: %s\n", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, 0);
|
||||
if(err < 0) {
|
||||
fprintf(stderr,"Buffer time error: %s\n", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, 0);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Period time error: %s\n", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, 0);
|
||||
if (err < 0)
|
||||
{
|
||||
fprintf(stderr,"Period time error: %s\n", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
err = snd_pcm_hw_params(handle, hwparams);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Unable to install hw params: %s\n", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_params(handle, hwparams);
|
||||
if (err < 0)
|
||||
{
|
||||
fprintf(stderr,"Unable to install hw params: %s\n", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
snd_pcm_status_alloca(&status);
|
||||
err = snd_pcm_status(handle, status);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Unable to get status: %s\n", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
snd_pcm_status_alloca(&status);
|
||||
err = snd_pcm_status(handle, status);
|
||||
if(err < 0)
|
||||
{
|
||||
fprintf(stderr,"Unable to get status: %s\n", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
// Bind our asynchronous callback magic:
|
||||
|
||||
// Bind our asynchronous callback magic:
|
||||
if (handle == NULL)
|
||||
fprintf(stderr, "No handle.");
|
||||
|
||||
if (handle == NULL) fprintf(stderr, "No handle.");
|
||||
|
||||
//fprintf(stderr,"* SPU2-X:Iz setting your internal callback.\n");
|
||||
// The external handler never seems to get called after this.
|
||||
snd_async_add_pcm_handler( &pcm_callback, handle, ExternalCallback, this );
|
||||
err = snd_pcm_start( handle );
|
||||
if(err < 0)
|
||||
{
|
||||
fprintf(stderr,"Pcm start failed: %s\n", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
// Diagnostic code:
|
||||
//buffer_size = snd_pcm_status_get_avail(status);
|
||||
|
||||
//fprintf(stderr,"All set up.\n");
|
||||
return 0;
|
||||
}
|
||||
//fprintf(stderr,"* SPU2-X:Iz setting your internal callback.\n");
|
||||
// The external handler never seems to get called after this.
|
||||
snd_async_add_pcm_handler(&pcm_callback, handle, ExternalCallback, this);
|
||||
err = snd_pcm_start(handle);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Pcm start failed: %s\n", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
// Diagnostic code:
|
||||
//buffer_size = snd_pcm_status_get_avail(status);
|
||||
|
||||
void Close()
|
||||
{
|
||||
//fprintf(stderr,"* SPU2-X: Closing Alsa\n");
|
||||
if(handle == NULL) return;
|
||||
//fprintf(stderr,"All set up.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
snd_pcm_drop(handle);
|
||||
snd_pcm_close(handle);
|
||||
handle = NULL;
|
||||
}
|
||||
void Close()
|
||||
{
|
||||
//fprintf(stderr,"* SPU2-X: Closing Alsa\n");
|
||||
if (handle == NULL)
|
||||
return;
|
||||
|
||||
virtual void Configure(uptr parent)
|
||||
{
|
||||
}
|
||||
snd_pcm_drop(handle);
|
||||
snd_pcm_close(handle);
|
||||
handle = NULL;
|
||||
}
|
||||
|
||||
virtual bool Is51Out() const { return false; }
|
||||
virtual void Configure(uptr parent)
|
||||
{
|
||||
}
|
||||
|
||||
s32 Test() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
virtual bool Is51Out() const { return false; }
|
||||
|
||||
int GetEmptySampleCount()
|
||||
{
|
||||
if(handle == NULL)
|
||||
{
|
||||
fprintf(stderr,"Handle is NULL!\n");
|
||||
return 0;
|
||||
}
|
||||
s32 Test() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Returns the amount of free buffer space, in samples.
|
||||
int l = snd_pcm_avail_update(handle);
|
||||
if( l < 0 ) return 0;
|
||||
return (l / 1000) * (SampleRate / 1000);
|
||||
}
|
||||
int GetEmptySampleCount()
|
||||
{
|
||||
if (handle == NULL) {
|
||||
fprintf(stderr, "Handle is NULL!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const wchar_t* GetIdent() const
|
||||
{
|
||||
return L"Alsa";
|
||||
}
|
||||
// Returns the amount of free buffer space, in samples.
|
||||
int l = snd_pcm_avail_update(handle);
|
||||
if (l < 0)
|
||||
return 0;
|
||||
return (l / 1000) * (SampleRate / 1000);
|
||||
}
|
||||
|
||||
const wchar_t* GetLongName() const
|
||||
{
|
||||
return L"Alsa";
|
||||
}
|
||||
const wchar_t *GetIdent() const
|
||||
{
|
||||
return L"Alsa";
|
||||
}
|
||||
|
||||
void ReadSettings()
|
||||
{
|
||||
}
|
||||
const wchar_t *GetLongName() const
|
||||
{
|
||||
return L"Alsa";
|
||||
}
|
||||
|
||||
void SetApiSettings(wxString api)
|
||||
{
|
||||
}
|
||||
void ReadSettings()
|
||||
{
|
||||
}
|
||||
|
||||
void WriteSettings() const
|
||||
{
|
||||
}
|
||||
void SetApiSettings(wxString api)
|
||||
{
|
||||
}
|
||||
|
||||
void WriteSettings() const
|
||||
{
|
||||
}
|
||||
} static Alsa;
|
||||
|
||||
SndOutModule *AlsaOut = &Alsa;
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_H__
|
||||
#define __LINUX_H__
|
||||
#ifndef __LINUX_H__
|
||||
#define __LINUX_H__
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -32,11 +32,11 @@
|
|||
extern int AlsaSetupSound();
|
||||
extern void AlsaRemoveSound();
|
||||
extern int AlsaSoundGetBytesBuffered();
|
||||
extern void AlsaSoundFeedVoiceData(unsigned char* pSound,long lBytes);
|
||||
extern void AlsaSoundFeedVoiceData(unsigned char *pSound, long lBytes);
|
||||
|
||||
extern int SetupSound();
|
||||
extern void RemoveSound();
|
||||
extern int SoundGetBytesBuffered();
|
||||
extern void SoundFeedVoiceData(unsigned char* pSound,long lBytes);
|
||||
extern void SoundFeedVoiceData(unsigned char *pSound, long lBytes);
|
||||
|
||||
#endif // __LINUX_H__
|
||||
#endif // __LINUX_H__
|
||||
|
|
|
@ -15,93 +15,94 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Dialogs.h"
|
||||
#include <wx/fileconf.h>
|
||||
#include "Dialogs.h"
|
||||
#include <wx/fileconf.h>
|
||||
|
||||
wxFileConfig *spuConfig = NULL;
|
||||
wxString path(L"~/.pcsx2/inis/spu2-x.ini");
|
||||
bool pathSet = false;
|
||||
wxFileConfig *spuConfig = NULL;
|
||||
wxString path(L"~/.pcsx2/inis/spu2-x.ini");
|
||||
bool pathSet = false;
|
||||
|
||||
void initIni()
|
||||
{
|
||||
if (spuConfig == NULL) spuConfig = new wxFileConfig(L"", L"", path, L"", wxCONFIG_USE_LOCAL_FILE);
|
||||
if (spuConfig == NULL)
|
||||
spuConfig = new wxFileConfig(L"", L"", path, L"", wxCONFIG_USE_LOCAL_FILE);
|
||||
}
|
||||
|
||||
void setIni(const wchar_t* Section)
|
||||
{
|
||||
initIni();
|
||||
spuConfig->SetPath(wxsFormat(L"/%s", Section));
|
||||
}
|
||||
|
||||
void CfgSetSettingsDir(const char* dir)
|
||||
void setIni(const wchar_t *Section)
|
||||
{
|
||||
FileLog("CfgSetSettingsDir(%s)\n", dir);
|
||||
path = wxString::FromAscii(dir) + L"/spu2-x.ini";
|
||||
pathSet = true;
|
||||
initIni();
|
||||
spuConfig->SetPath(wxsFormat(L"/%s", Section));
|
||||
}
|
||||
|
||||
void CfgWriteBool(const wchar_t* Section, const wchar_t* Name, bool Value)
|
||||
void CfgSetSettingsDir(const char *dir)
|
||||
{
|
||||
setIni(Section);
|
||||
spuConfig->Write(Name, Value);
|
||||
FileLog("CfgSetSettingsDir(%s)\n", dir);
|
||||
path = wxString::FromAscii(dir) + L"/spu2-x.ini";
|
||||
pathSet = true;
|
||||
}
|
||||
|
||||
void CfgWriteInt(const wchar_t* Section, const wchar_t* Name, int Value)
|
||||
void CfgWriteBool(const wchar_t *Section, const wchar_t *Name, bool Value)
|
||||
{
|
||||
setIni(Section);
|
||||
spuConfig->Write(Name, Value);
|
||||
setIni(Section);
|
||||
spuConfig->Write(Name, Value);
|
||||
}
|
||||
|
||||
void CfgWriteFloat(const wchar_t* Section, const wchar_t* Name, float Value)
|
||||
void CfgWriteInt(const wchar_t *Section, const wchar_t *Name, int Value)
|
||||
{
|
||||
setIni(Section);
|
||||
spuConfig->Write(Name, (double)Value);
|
||||
setIni(Section);
|
||||
spuConfig->Write(Name, Value);
|
||||
}
|
||||
|
||||
void CfgWriteStr(const wchar_t* Section, const wchar_t* Name, const wxString& Data)
|
||||
void CfgWriteFloat(const wchar_t *Section, const wchar_t *Name, float Value)
|
||||
{
|
||||
setIni(Section);
|
||||
spuConfig->Write(Name, Data);
|
||||
setIni(Section);
|
||||
spuConfig->Write(Name, (double)Value);
|
||||
}
|
||||
|
||||
bool CfgReadBool(const wchar_t *Section,const wchar_t* Name, bool Default)
|
||||
void CfgWriteStr(const wchar_t *Section, const wchar_t *Name, const wxString &Data)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
setIni(Section);
|
||||
spuConfig->Read(Name, &ret, Default);
|
||||
|
||||
return ret;
|
||||
setIni(Section);
|
||||
spuConfig->Write(Name, Data);
|
||||
}
|
||||
|
||||
int CfgReadInt(const wchar_t* Section, const wchar_t* Name,int Default)
|
||||
bool CfgReadBool(const wchar_t *Section, const wchar_t *Name, bool Default)
|
||||
{
|
||||
int ret;
|
||||
bool ret;
|
||||
|
||||
setIni(Section);
|
||||
spuConfig->Read(Name, &ret, Default);
|
||||
setIni(Section);
|
||||
spuConfig->Read(Name, &ret, Default);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
float CfgReadFloat(const wchar_t* Section, const wchar_t* Name, float Default)
|
||||
int CfgReadInt(const wchar_t *Section, const wchar_t *Name, int Default)
|
||||
{
|
||||
double ret;
|
||||
int ret;
|
||||
|
||||
setIni(Section);
|
||||
spuConfig->Read(Name, &ret, (double)Default);
|
||||
setIni(Section);
|
||||
spuConfig->Read(Name, &ret, Default);
|
||||
|
||||
return (float)ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CfgReadStr(const wchar_t* Section, const wchar_t* Name, wchar_t* Data, int DataSize, const wchar_t* Default)
|
||||
float CfgReadFloat(const wchar_t *Section, const wchar_t *Name, float Default)
|
||||
{
|
||||
setIni(Section);
|
||||
wcscpy(Data, spuConfig->Read(Name, Default).wc_str());
|
||||
double ret;
|
||||
|
||||
setIni(Section);
|
||||
spuConfig->Read(Name, &ret, (double)Default);
|
||||
|
||||
return (float)ret;
|
||||
}
|
||||
|
||||
void CfgReadStr(const wchar_t* Section, const wchar_t* Name, wxString& Data, const wchar_t* Default)
|
||||
void CfgReadStr(const wchar_t *Section, const wchar_t *Name, wchar_t *Data, int DataSize, const wchar_t *Default)
|
||||
{
|
||||
setIni(Section);
|
||||
Data = spuConfig->Read(Name, Default);
|
||||
setIni(Section);
|
||||
wcscpy(Data, spuConfig->Read(Name, Default).wc_str());
|
||||
}
|
||||
|
||||
void CfgReadStr(const wchar_t *Section, const wchar_t *Name, wxString &Data, const wchar_t *Default)
|
||||
{
|
||||
setIni(Section);
|
||||
Data = spuConfig->Read(Name, Default);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ static const int LATENCY_MAX = 750;
|
|||
|
||||
static const int LATENCY_MIN = 15;
|
||||
|
||||
int AutoDMAPlayRate[2] = {0,0};
|
||||
int AutoDMAPlayRate[2] = {0, 0};
|
||||
|
||||
// Default settings.
|
||||
|
||||
|
@ -47,9 +47,9 @@ int Interpolation = 4;
|
|||
*/
|
||||
|
||||
bool EffectsDisabled = false;
|
||||
float FinalVolume; // global
|
||||
float FinalVolume; // global
|
||||
bool AdvancedVolumeControl;
|
||||
float VolumeAdjustFLdb; // decibels settings, cos audiophiles love that
|
||||
float VolumeAdjustFLdb; // decibels settings, cos audiophiles love that
|
||||
float VolumeAdjustCdb;
|
||||
float VolumeAdjustFRdb;
|
||||
float VolumeAdjustBLdb;
|
||||
|
@ -57,7 +57,7 @@ float VolumeAdjustBRdb;
|
|||
float VolumeAdjustSLdb;
|
||||
float VolumeAdjustSRdb;
|
||||
float VolumeAdjustLFEdb;
|
||||
float VolumeAdjustFL; // linear coefs calcualted from decibels,
|
||||
float VolumeAdjustFL; // linear coefs calcualted from decibels,
|
||||
float VolumeAdjustC;
|
||||
float VolumeAdjustFR;
|
||||
float VolumeAdjustBL;
|
||||
|
@ -69,12 +69,12 @@ unsigned int delayCycles;
|
|||
|
||||
bool postprocess_filter_enabled = true;
|
||||
bool postprocess_filter_dealias = false;
|
||||
bool _visual_debug_enabled = false; // windows only feature
|
||||
bool _visual_debug_enabled = false; // windows only feature
|
||||
|
||||
// OUTPUT
|
||||
u32 OutputModule = 0;
|
||||
int SndOutLatencyMS = 300;
|
||||
int SynchMode = 0; // Time Stretch, Async or Disabled
|
||||
int SynchMode = 0; // Time Stretch, Async or Disabled
|
||||
static u32 OutputAPI = 0;
|
||||
static u32 SdlOutputAPI = 0;
|
||||
|
||||
|
@ -84,135 +84,138 @@ int dplLevel = 0;
|
|||
|
||||
void ReadSettings()
|
||||
{
|
||||
// For some reason this can be called before we know what ini file we're writing to.
|
||||
// Lets not try to read it if that happens.
|
||||
if (!pathSet)
|
||||
{
|
||||
FileLog("Read called without the path set.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
Interpolation = CfgReadInt( L"MIXING",L"Interpolation", 4 );
|
||||
EffectsDisabled = CfgReadBool( L"MIXING", L"Disable_Effects", false );
|
||||
postprocess_filter_dealias = CfgReadBool( L"MIXING", L"DealiasFilter", false );
|
||||
FinalVolume = ((float)CfgReadInt( L"MIXING", L"FinalVolume", 100 )) / 100;
|
||||
if ( FinalVolume > 1.0f) FinalVolume = 1.0f;
|
||||
// For some reason this can be called before we know what ini file we're writing to.
|
||||
// Lets not try to read it if that happens.
|
||||
if (!pathSet) {
|
||||
FileLog("Read called without the path set.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
AdvancedVolumeControl = CfgReadBool(L"MIXING", L"AdvancedVolumeControl", false);
|
||||
VolumeAdjustCdb = CfgReadFloat(L"MIXING", L"VolumeAdjustC(dB)", 0);
|
||||
VolumeAdjustFLdb = CfgReadFloat(L"MIXING", L"VolumeAdjustFL(dB)", 0);
|
||||
VolumeAdjustFRdb = CfgReadFloat(L"MIXING", L"VolumeAdjustFR(dB)", 0);
|
||||
VolumeAdjustBLdb = CfgReadFloat(L"MIXING", L"VolumeAdjustBL(dB)", 0);
|
||||
VolumeAdjustBRdb = CfgReadFloat(L"MIXING", L"VolumeAdjustBR(dB)", 0);
|
||||
VolumeAdjustSLdb = CfgReadFloat(L"MIXING", L"VolumeAdjustSL(dB)", 0);
|
||||
VolumeAdjustSRdb = CfgReadFloat(L"MIXING", L"VolumeAdjustSR(dB)", 0);
|
||||
VolumeAdjustLFEdb = CfgReadFloat(L"MIXING", L"VolumeAdjustLFE(dB)", 0);
|
||||
VolumeAdjustC = powf(10, VolumeAdjustCdb / 10);
|
||||
VolumeAdjustFL = powf(10, VolumeAdjustFLdb / 10);
|
||||
VolumeAdjustFR = powf(10, VolumeAdjustFRdb / 10);
|
||||
VolumeAdjustBL = powf(10, VolumeAdjustBLdb / 10);
|
||||
VolumeAdjustBR = powf(10, VolumeAdjustBRdb / 10);
|
||||
VolumeAdjustSL = powf(10, VolumeAdjustSLdb / 10);
|
||||
VolumeAdjustSR = powf(10, VolumeAdjustSRdb / 10);
|
||||
VolumeAdjustLFE = powf(10, VolumeAdjustLFEdb / 10);
|
||||
delayCycles = CfgReadInt(L"DEBUG", L"DelayCycles", 4);
|
||||
Interpolation = CfgReadInt(L"MIXING", L"Interpolation", 4);
|
||||
EffectsDisabled = CfgReadBool(L"MIXING", L"Disable_Effects", false);
|
||||
postprocess_filter_dealias = CfgReadBool(L"MIXING", L"DealiasFilter", false);
|
||||
FinalVolume = ((float)CfgReadInt(L"MIXING", L"FinalVolume", 100)) / 100;
|
||||
if (FinalVolume > 1.0f)
|
||||
FinalVolume = 1.0f;
|
||||
|
||||
AdvancedVolumeControl = CfgReadBool(L"MIXING", L"AdvancedVolumeControl", false);
|
||||
VolumeAdjustCdb = CfgReadFloat(L"MIXING", L"VolumeAdjustC(dB)", 0);
|
||||
VolumeAdjustFLdb = CfgReadFloat(L"MIXING", L"VolumeAdjustFL(dB)", 0);
|
||||
VolumeAdjustFRdb = CfgReadFloat(L"MIXING", L"VolumeAdjustFR(dB)", 0);
|
||||
VolumeAdjustBLdb = CfgReadFloat(L"MIXING", L"VolumeAdjustBL(dB)", 0);
|
||||
VolumeAdjustBRdb = CfgReadFloat(L"MIXING", L"VolumeAdjustBR(dB)", 0);
|
||||
VolumeAdjustSLdb = CfgReadFloat(L"MIXING", L"VolumeAdjustSL(dB)", 0);
|
||||
VolumeAdjustSRdb = CfgReadFloat(L"MIXING", L"VolumeAdjustSR(dB)", 0);
|
||||
VolumeAdjustLFEdb = CfgReadFloat(L"MIXING", L"VolumeAdjustLFE(dB)", 0);
|
||||
VolumeAdjustC = powf(10, VolumeAdjustCdb / 10);
|
||||
VolumeAdjustFL = powf(10, VolumeAdjustFLdb / 10);
|
||||
VolumeAdjustFR = powf(10, VolumeAdjustFRdb / 10);
|
||||
VolumeAdjustBL = powf(10, VolumeAdjustBLdb / 10);
|
||||
VolumeAdjustBR = powf(10, VolumeAdjustBRdb / 10);
|
||||
VolumeAdjustSL = powf(10, VolumeAdjustSLdb / 10);
|
||||
VolumeAdjustSR = powf(10, VolumeAdjustSRdb / 10);
|
||||
VolumeAdjustLFE = powf(10, VolumeAdjustLFEdb / 10);
|
||||
delayCycles = CfgReadInt(L"DEBUG", L"DelayCycles", 4);
|
||||
|
||||
|
||||
wxString temp;
|
||||
CfgReadStr( L"OUTPUT", L"Output_Module", temp, PortaudioOut->GetIdent() );
|
||||
OutputModule = FindOutputModuleById( temp.c_str() );// find the driver index of this module
|
||||
wxString temp;
|
||||
CfgReadStr(L"OUTPUT", L"Output_Module", temp, PortaudioOut->GetIdent());
|
||||
OutputModule = FindOutputModuleById(temp.c_str()); // find the driver index of this module
|
||||
|
||||
// find current API
|
||||
// find current API
|
||||
#ifdef __linux__
|
||||
CfgReadStr( L"PORTAUDIO", L"HostApi", temp, L"ALSA" );
|
||||
OutputAPI = -1;
|
||||
if (temp == L"ALSA") OutputAPI = 0;
|
||||
if (temp == L"OSS") OutputAPI = 1;
|
||||
if (temp == L"JACK") OutputAPI = 2;
|
||||
CfgReadStr(L"PORTAUDIO", L"HostApi", temp, L"ALSA");
|
||||
OutputAPI = -1;
|
||||
if (temp == L"ALSA")
|
||||
OutputAPI = 0;
|
||||
if (temp == L"OSS")
|
||||
OutputAPI = 1;
|
||||
if (temp == L"JACK")
|
||||
OutputAPI = 2;
|
||||
#else
|
||||
CfgReadStr( L"PORTAUDIO", L"HostApi", temp, L"OSS" );
|
||||
OutputAPI = -1;
|
||||
CfgReadStr(L"PORTAUDIO", L"HostApi", temp, L"OSS");
|
||||
OutputAPI = -1;
|
||||
|
||||
if (temp == L"OSS") OutputAPI = 0;
|
||||
if (temp == L"OSS")
|
||||
OutputAPI = 0;
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
CfgReadStr( L"SDL", L"HostApi", temp, L"pulseaudio" );
|
||||
SdlOutputAPI = -1;
|
||||
CfgReadStr(L"SDL", L"HostApi", temp, L"pulseaudio");
|
||||
SdlOutputAPI = -1;
|
||||
#if SDL_MAJOR_VERSION >= 2
|
||||
// YES It sucks ...
|
||||
for (int i = 0; i < SDL_GetNumAudioDrivers(); ++i) {
|
||||
if (!temp.Cmp(wxString(SDL_GetAudioDriver(i), wxConvUTF8)))
|
||||
SdlOutputAPI = i;
|
||||
}
|
||||
// YES It sucks ...
|
||||
for (int i = 0; i < SDL_GetNumAudioDrivers(); ++i) {
|
||||
if (!temp.Cmp(wxString(SDL_GetAudioDriver(i), wxConvUTF8)))
|
||||
SdlOutputAPI = i;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
SndOutLatencyMS = CfgReadInt(L"OUTPUT",L"Latency", 300);
|
||||
SynchMode = CfgReadInt( L"OUTPUT", L"Synch_Mode", 0);
|
||||
SndOutLatencyMS = CfgReadInt(L"OUTPUT", L"Latency", 300);
|
||||
SynchMode = CfgReadInt(L"OUTPUT", L"Synch_Mode", 0);
|
||||
|
||||
PortaudioOut->ReadSettings();
|
||||
PortaudioOut->ReadSettings();
|
||||
#ifdef __linux__
|
||||
SDLOut->ReadSettings();
|
||||
SDLOut->ReadSettings();
|
||||
#endif
|
||||
SoundtouchCfg::ReadSettings();
|
||||
DebugConfig::ReadSettings();
|
||||
SoundtouchCfg::ReadSettings();
|
||||
DebugConfig::ReadSettings();
|
||||
|
||||
// Sanity Checks
|
||||
// -------------
|
||||
// Sanity Checks
|
||||
// -------------
|
||||
|
||||
Clampify( SndOutLatencyMS, LATENCY_MIN, LATENCY_MAX );
|
||||
Clampify(SndOutLatencyMS, LATENCY_MIN, LATENCY_MAX);
|
||||
|
||||
WriteSettings();
|
||||
spuConfig->Flush();
|
||||
WriteSettings();
|
||||
spuConfig->Flush();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void WriteSettings()
|
||||
{
|
||||
if (!pathSet)
|
||||
{
|
||||
FileLog("Write called without the path set.\n");
|
||||
return;
|
||||
}
|
||||
if (!pathSet) {
|
||||
FileLog("Write called without the path set.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
CfgWriteInt(L"MIXING",L"Interpolation",Interpolation);
|
||||
CfgWriteBool(L"MIXING",L"Disable_Effects",EffectsDisabled);
|
||||
CfgWriteBool(L"MIXING",L"DealiasFilter",postprocess_filter_dealias);
|
||||
CfgWriteInt(L"MIXING",L"FinalVolume",(int)(FinalVolume * 100 +0.5f));
|
||||
CfgWriteInt(L"MIXING", L"Interpolation", Interpolation);
|
||||
CfgWriteBool(L"MIXING", L"Disable_Effects", EffectsDisabled);
|
||||
CfgWriteBool(L"MIXING", L"DealiasFilter", postprocess_filter_dealias);
|
||||
CfgWriteInt(L"MIXING", L"FinalVolume", (int)(FinalVolume * 100 + 0.5f));
|
||||
|
||||
CfgWriteBool(L"MIXING", L"AdvancedVolumeControl", AdvancedVolumeControl);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustC(dB)", VolumeAdjustCdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustFL(dB)", VolumeAdjustFLdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustFR(dB)", VolumeAdjustFRdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustBL(dB)", VolumeAdjustBLdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustBR(dB)", VolumeAdjustBRdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustSL(dB)", VolumeAdjustSLdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustSR(dB)", VolumeAdjustSRdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustLFE(dB)", VolumeAdjustLFEdb);
|
||||
CfgWriteBool(L"MIXING", L"AdvancedVolumeControl", AdvancedVolumeControl);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustC(dB)", VolumeAdjustCdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustFL(dB)", VolumeAdjustFLdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustFR(dB)", VolumeAdjustFRdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustBL(dB)", VolumeAdjustBLdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustBR(dB)", VolumeAdjustBRdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustSL(dB)", VolumeAdjustSLdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustSR(dB)", VolumeAdjustSRdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustLFE(dB)", VolumeAdjustLFEdb);
|
||||
|
||||
CfgWriteStr(L"OUTPUT",L"Output_Module", mods[OutputModule]->GetIdent() );
|
||||
CfgWriteInt(L"OUTPUT",L"Latency", SndOutLatencyMS);
|
||||
CfgWriteInt(L"OUTPUT",L"Synch_Mode", SynchMode);
|
||||
CfgWriteInt(L"DEBUG", L"DelayCycles", delayCycles);
|
||||
CfgWriteStr(L"OUTPUT", L"Output_Module", mods[OutputModule]->GetIdent());
|
||||
CfgWriteInt(L"OUTPUT", L"Latency", SndOutLatencyMS);
|
||||
CfgWriteInt(L"OUTPUT", L"Synch_Mode", SynchMode);
|
||||
CfgWriteInt(L"DEBUG", L"DelayCycles", delayCycles);
|
||||
|
||||
PortaudioOut->WriteSettings();
|
||||
PortaudioOut->WriteSettings();
|
||||
#ifdef __linux__
|
||||
SDLOut->WriteSettings();
|
||||
SDLOut->WriteSettings();
|
||||
#endif
|
||||
SoundtouchCfg::WriteSettings();
|
||||
DebugConfig::WriteSettings();
|
||||
SoundtouchCfg::WriteSettings();
|
||||
DebugConfig::WriteSettings();
|
||||
}
|
||||
|
||||
void advanced_dialog()
|
||||
{
|
||||
SoundtouchCfg::DisplayDialog();
|
||||
SoundtouchCfg::DisplayDialog();
|
||||
}
|
||||
|
||||
void debug_dialog()
|
||||
{
|
||||
DebugConfig::DisplayDialog();
|
||||
DebugConfig::DisplayDialog();
|
||||
}
|
||||
|
||||
#if defined(__unix__)
|
||||
|
@ -241,16 +244,16 @@ void DisplayDialog()
|
|||
GtkWidget *advanced_button;
|
||||
|
||||
/* Create the widgets */
|
||||
dialog = gtk_dialog_new_with_buttons (
|
||||
"SPU2-X Config",
|
||||
NULL, /* parent window*/
|
||||
(GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
|
||||
"OK", GTK_RESPONSE_ACCEPT,
|
||||
"Cancel", GTK_RESPONSE_REJECT,
|
||||
NULL);
|
||||
dialog = gtk_dialog_new_with_buttons(
|
||||
"SPU2-X Config",
|
||||
NULL, /* parent window*/
|
||||
(GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
|
||||
"OK", GTK_RESPONSE_ACCEPT,
|
||||
"Cancel", GTK_RESPONSE_REJECT,
|
||||
NULL);
|
||||
|
||||
int_label = gtk_label_new ("Interpolation:");
|
||||
int_box = gtk_combo_box_text_new ();
|
||||
int_label = gtk_label_new("Interpolation:");
|
||||
int_box = gtk_combo_box_text_new();
|
||||
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(int_box), "0 - Nearest (fastest/bad quality)");
|
||||
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(int_box), "1 - Linear (simple/okay sound)");
|
||||
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(int_box), "2 - Cubic (artificial highs)");
|
||||
|
@ -262,10 +265,10 @@ void DisplayDialog()
|
|||
dealias_filter = gtk_check_button_new_with_label("Use the de-alias filter (overemphasizes the highs)");
|
||||
|
||||
debug_check = gtk_check_button_new_with_label("Enable Debug Options");
|
||||
debug_button = gtk_button_new_with_label("Debug...");
|
||||
debug_button = gtk_button_new_with_label("Debug...");
|
||||
|
||||
mod_label = gtk_label_new ("Module:");
|
||||
mod_box = gtk_combo_box_text_new ();
|
||||
mod_label = gtk_label_new("Module:");
|
||||
mod_box = gtk_combo_box_text_new();
|
||||
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(mod_box), "0 - No Sound (emulate SPU2 only)");
|
||||
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(mod_box), "1 - PortAudio (cross-platform)");
|
||||
#ifdef __linux__
|
||||
|
@ -274,10 +277,10 @@ void DisplayDialog()
|
|||
//gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(mod_box), "3 - Alsa (probably doesn't work)");
|
||||
gtk_combo_box_set_active(GTK_COMBO_BOX(mod_box), OutputModule);
|
||||
|
||||
api_label = gtk_label_new ("PortAudio API:");
|
||||
api_box = gtk_combo_box_text_new ();
|
||||
api_label = gtk_label_new("PortAudio API:");
|
||||
api_box = gtk_combo_box_text_new();
|
||||
#ifdef __linux__
|
||||
// In order to keep it the menu light, I only put linux major api
|
||||
// In order to keep it the menu light, I only put linux major api
|
||||
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(api_box), "0 - ALSA (recommended)");
|
||||
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(api_box), "1 - OSS (legacy)");
|
||||
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(api_box), "2 - JACK");
|
||||
|
@ -287,8 +290,8 @@ void DisplayDialog()
|
|||
gtk_combo_box_set_active(GTK_COMBO_BOX(api_box), OutputAPI);
|
||||
|
||||
#if SDL_MAJOR_VERSION >= 2
|
||||
sdl_api_label = gtk_label_new ("SDL API:");
|
||||
sdl_api_box = gtk_combo_box_text_new ();
|
||||
sdl_api_label = gtk_label_new("SDL API:");
|
||||
sdl_api_box = gtk_combo_box_text_new();
|
||||
// YES It sucks ...
|
||||
for (int i = 0; i < SDL_GetNumAudioDrivers(); ++i) {
|
||||
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(sdl_api_box), SDL_GetAudioDriver(i));
|
||||
|
@ -296,7 +299,7 @@ void DisplayDialog()
|
|||
gtk_combo_box_set_active(GTK_COMBO_BOX(sdl_api_box), SdlOutputAPI);
|
||||
#endif
|
||||
|
||||
latency_label = gtk_label_new ("Latency:");
|
||||
latency_label = gtk_label_new("Latency:");
|
||||
#if GTK_MAJOR_VERSION < 3
|
||||
latency_slide = gtk_hscale_new_with_range(LATENCY_MIN, LATENCY_MAX, 5);
|
||||
#else
|
||||
|
@ -304,123 +307,131 @@ void DisplayDialog()
|
|||
#endif
|
||||
gtk_range_set_value(GTK_RANGE(latency_slide), SndOutLatencyMS);
|
||||
|
||||
sync_label = gtk_label_new ("Synchronization Mode:");
|
||||
sync_box = gtk_combo_box_text_new ();
|
||||
sync_label = gtk_label_new("Synchronization Mode:");
|
||||
sync_box = gtk_combo_box_text_new();
|
||||
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(sync_box), "TimeStretch (Recommended)");
|
||||
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(sync_box), "Async Mix (Breaks some games!)");
|
||||
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(sync_box), "None (Audio can skip.)");
|
||||
gtk_combo_box_set_active(GTK_COMBO_BOX(sync_box), SynchMode);
|
||||
|
||||
advanced_button = gtk_button_new_with_label("Advanced...");
|
||||
advanced_button = gtk_button_new_with_label("Advanced...");
|
||||
|
||||
main_box = gtk_hbox_new(false, 5);
|
||||
main_frame = gtk_frame_new ("SPU2-X Config");
|
||||
gtk_container_add (GTK_CONTAINER(main_frame), main_box);
|
||||
main_frame = gtk_frame_new("SPU2-X Config");
|
||||
gtk_container_add(GTK_CONTAINER(main_frame), main_box);
|
||||
|
||||
mixing_box = gtk_vbox_new(false, 5);
|
||||
mixing_frame = gtk_frame_new ("Mixing Settings:");
|
||||
gtk_container_add (GTK_CONTAINER(mixing_frame), mixing_box);
|
||||
mixing_frame = gtk_frame_new("Mixing Settings:");
|
||||
gtk_container_add(GTK_CONTAINER(mixing_frame), mixing_box);
|
||||
|
||||
output_box = gtk_vbox_new(false, 5);
|
||||
output_frame = gtk_frame_new ("Output Settings:");
|
||||
gtk_container_add (GTK_CONTAINER(output_frame), output_box);
|
||||
output_frame = gtk_frame_new("Output Settings:");
|
||||
gtk_container_add(GTK_CONTAINER(output_frame), output_box);
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(mixing_box), int_label);
|
||||
gtk_container_add(GTK_CONTAINER(mixing_box), int_box);
|
||||
gtk_container_add(GTK_CONTAINER(mixing_box), effects_check);
|
||||
gtk_container_add(GTK_CONTAINER(mixing_box), dealias_filter);
|
||||
gtk_container_add(GTK_CONTAINER(mixing_box), debug_check);
|
||||
gtk_container_add(GTK_CONTAINER(mixing_box), debug_button);
|
||||
gtk_container_add(GTK_CONTAINER(mixing_box), int_label);
|
||||
gtk_container_add(GTK_CONTAINER(mixing_box), int_box);
|
||||
gtk_container_add(GTK_CONTAINER(mixing_box), effects_check);
|
||||
gtk_container_add(GTK_CONTAINER(mixing_box), dealias_filter);
|
||||
gtk_container_add(GTK_CONTAINER(mixing_box), debug_check);
|
||||
gtk_container_add(GTK_CONTAINER(mixing_box), debug_button);
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(output_box), mod_label);
|
||||
gtk_container_add(GTK_CONTAINER(output_box), mod_box);
|
||||
gtk_container_add(GTK_CONTAINER(output_box), api_label);
|
||||
gtk_container_add(GTK_CONTAINER(output_box), api_box);
|
||||
gtk_container_add(GTK_CONTAINER(output_box), mod_label);
|
||||
gtk_container_add(GTK_CONTAINER(output_box), mod_box);
|
||||
gtk_container_add(GTK_CONTAINER(output_box), api_label);
|
||||
gtk_container_add(GTK_CONTAINER(output_box), api_box);
|
||||
#if SDL_MAJOR_VERSION >= 2
|
||||
gtk_container_add(GTK_CONTAINER(output_box), sdl_api_label);
|
||||
gtk_container_add(GTK_CONTAINER(output_box), sdl_api_box);
|
||||
gtk_container_add(GTK_CONTAINER(output_box), sdl_api_label);
|
||||
gtk_container_add(GTK_CONTAINER(output_box), sdl_api_box);
|
||||
#endif
|
||||
gtk_container_add(GTK_CONTAINER(output_box), sync_label);
|
||||
gtk_container_add(GTK_CONTAINER(output_box), sync_box);
|
||||
gtk_container_add(GTK_CONTAINER(output_box), latency_label);
|
||||
gtk_container_add(GTK_CONTAINER(output_box), latency_slide);
|
||||
gtk_container_add(GTK_CONTAINER(output_box), advanced_button);
|
||||
gtk_container_add(GTK_CONTAINER(output_box), sync_label);
|
||||
gtk_container_add(GTK_CONTAINER(output_box), sync_box);
|
||||
gtk_container_add(GTK_CONTAINER(output_box), latency_label);
|
||||
gtk_container_add(GTK_CONTAINER(output_box), latency_slide);
|
||||
gtk_container_add(GTK_CONTAINER(output_box), advanced_button);
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(main_box), mixing_frame);
|
||||
gtk_container_add(GTK_CONTAINER(main_box), output_frame);
|
||||
gtk_container_add(GTK_CONTAINER(main_box), mixing_frame);
|
||||
gtk_container_add(GTK_CONTAINER(main_box), output_frame);
|
||||
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(effects_check), EffectsDisabled);
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dealias_filter), postprocess_filter_dealias);
|
||||
//FinalVolume;
|
||||
//FinalVolume;
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(debug_check), DebugEnabled);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), main_frame);
|
||||
gtk_widget_show_all (dialog);
|
||||
gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), main_frame);
|
||||
gtk_widget_show_all(dialog);
|
||||
|
||||
g_signal_connect_swapped(advanced_button, "clicked", G_CALLBACK(advanced_dialog), advanced_button);
|
||||
g_signal_connect_swapped(debug_button, "clicked", G_CALLBACK(debug_dialog), debug_button);
|
||||
|
||||
return_value = gtk_dialog_run (GTK_DIALOG (dialog));
|
||||
return_value = gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
|
||||
if (return_value == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
DebugEnabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(debug_check));
|
||||
postprocess_filter_dealias = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dealias_filter));
|
||||
if (gtk_combo_box_get_active(GTK_COMBO_BOX(int_box)) != -1)
|
||||
Interpolation = gtk_combo_box_get_active(GTK_COMBO_BOX(int_box));
|
||||
if (return_value == GTK_RESPONSE_ACCEPT) {
|
||||
DebugEnabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(debug_check));
|
||||
postprocess_filter_dealias = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dealias_filter));
|
||||
if (gtk_combo_box_get_active(GTK_COMBO_BOX(int_box)) != -1)
|
||||
Interpolation = gtk_combo_box_get_active(GTK_COMBO_BOX(int_box));
|
||||
|
||||
EffectsDisabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(effects_check));
|
||||
//FinalVolume;
|
||||
EffectsDisabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(effects_check));
|
||||
//FinalVolume;
|
||||
|
||||
if (gtk_combo_box_get_active(GTK_COMBO_BOX(mod_box)) != -1)
|
||||
OutputModule = gtk_combo_box_get_active(GTK_COMBO_BOX(mod_box));
|
||||
if (gtk_combo_box_get_active(GTK_COMBO_BOX(mod_box)) != -1)
|
||||
OutputModule = gtk_combo_box_get_active(GTK_COMBO_BOX(mod_box));
|
||||
|
||||
if (gtk_combo_box_get_active(GTK_COMBO_BOX(api_box)) != -1) {
|
||||
OutputAPI = gtk_combo_box_get_active(GTK_COMBO_BOX(api_box));
|
||||
if (gtk_combo_box_get_active(GTK_COMBO_BOX(api_box)) != -1) {
|
||||
OutputAPI = gtk_combo_box_get_active(GTK_COMBO_BOX(api_box));
|
||||
#ifdef __linux__
|
||||
switch(OutputAPI) {
|
||||
case 0: PortaudioOut->SetApiSettings(L"ALSA"); break;
|
||||
case 1: PortaudioOut->SetApiSettings(L"OSS"); break;
|
||||
case 2: PortaudioOut->SetApiSettings(L"JACK"); break;
|
||||
default: PortaudioOut->SetApiSettings(L"Unknown");
|
||||
}
|
||||
switch (OutputAPI) {
|
||||
case 0:
|
||||
PortaudioOut->SetApiSettings(L"ALSA");
|
||||
break;
|
||||
case 1:
|
||||
PortaudioOut->SetApiSettings(L"OSS");
|
||||
break;
|
||||
case 2:
|
||||
PortaudioOut->SetApiSettings(L"JACK");
|
||||
break;
|
||||
default:
|
||||
PortaudioOut->SetApiSettings(L"Unknown");
|
||||
}
|
||||
#else
|
||||
switch(OutputAPI) {
|
||||
case 0: PortaudioOut->SetApiSettings(L"OSS"); break;
|
||||
default: PortaudioOut->SetApiSettings(L"Unknown");
|
||||
}
|
||||
switch (OutputAPI) {
|
||||
case 0:
|
||||
PortaudioOut->SetApiSettings(L"OSS");
|
||||
break;
|
||||
default:
|
||||
PortaudioOut->SetApiSettings(L"Unknown");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if SDL_MAJOR_VERSION >= 2
|
||||
if (gtk_combo_box_get_active(GTK_COMBO_BOX(sdl_api_box)) != -1) {
|
||||
SdlOutputAPI = gtk_combo_box_get_active(GTK_COMBO_BOX(sdl_api_box));
|
||||
// YES It sucks ...
|
||||
SDLOut->SetApiSettings(wxString(SDL_GetAudioDriver(SdlOutputAPI), wxConvUTF8));
|
||||
}
|
||||
if (gtk_combo_box_get_active(GTK_COMBO_BOX(sdl_api_box)) != -1) {
|
||||
SdlOutputAPI = gtk_combo_box_get_active(GTK_COMBO_BOX(sdl_api_box));
|
||||
// YES It sucks ...
|
||||
SDLOut->SetApiSettings(wxString(SDL_GetAudioDriver(SdlOutputAPI), wxConvUTF8));
|
||||
}
|
||||
#endif
|
||||
|
||||
SndOutLatencyMS = gtk_range_get_value(GTK_RANGE(latency_slide));
|
||||
|
||||
if (gtk_combo_box_get_active(GTK_COMBO_BOX(sync_box)) != -1)
|
||||
SynchMode = gtk_combo_box_get_active(GTK_COMBO_BOX(sync_box));
|
||||
SndOutLatencyMS = gtk_range_get_value(GTK_RANGE(latency_slide));
|
||||
|
||||
if (gtk_combo_box_get_active(GTK_COMBO_BOX(sync_box)) != -1)
|
||||
SynchMode = gtk_combo_box_get_active(GTK_COMBO_BOX(sync_box));
|
||||
}
|
||||
|
||||
gtk_widget_destroy (dialog);
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
#else
|
||||
void DisplayDialog()
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
void configure()
|
||||
{
|
||||
initIni();
|
||||
ReadSettings();
|
||||
DisplayDialog();
|
||||
WriteSettings();
|
||||
delete spuConfig;
|
||||
spuConfig = NULL;
|
||||
initIni();
|
||||
ReadSettings();
|
||||
DisplayDialog();
|
||||
WriteSettings();
|
||||
delete spuConfig;
|
||||
spuConfig = NULL;
|
||||
}
|
||||
|
|
|
@ -82,16 +82,16 @@ extern u32 OutputModule;
|
|||
extern int SndOutLatencyMS;
|
||||
|
||||
extern wchar_t dspPlugin[];
|
||||
extern int dspPluginModule;
|
||||
extern int dspPluginModule;
|
||||
|
||||
extern bool dspPluginEnabled;
|
||||
extern bool dspPluginEnabled;
|
||||
extern int SynchMode;
|
||||
|
||||
namespace SoundtouchCfg
|
||||
{
|
||||
void ReadSettings();
|
||||
void WriteSettings();
|
||||
void DisplayDialog();
|
||||
void ReadSettings();
|
||||
void WriteSettings();
|
||||
void DisplayDialog();
|
||||
};
|
||||
|
||||
void ReadSettings();
|
||||
|
@ -101,4 +101,4 @@ void AboutBox();
|
|||
extern wxFileConfig *spuConfig;
|
||||
extern bool pathSet;
|
||||
extern void initIni();
|
||||
#endif // CONFIG_H_INCLUDED
|
||||
#endif // CONFIG_H_INCLUDED
|
||||
|
|
|
@ -20,22 +20,22 @@
|
|||
#include "Config.h"
|
||||
#include "Utilities/Path.h"
|
||||
|
||||
bool DebugEnabled=false;
|
||||
bool _MsgToConsole=false;
|
||||
bool _MsgKeyOnOff=false;
|
||||
bool _MsgVoiceOff=false;
|
||||
bool _MsgDMA=false;
|
||||
bool _MsgAutoDMA=false;
|
||||
bool _MsgOverruns=false;
|
||||
bool _MsgCache=false;
|
||||
bool DebugEnabled = false;
|
||||
bool _MsgToConsole = false;
|
||||
bool _MsgKeyOnOff = false;
|
||||
bool _MsgVoiceOff = false;
|
||||
bool _MsgDMA = false;
|
||||
bool _MsgAutoDMA = false;
|
||||
bool _MsgOverruns = false;
|
||||
bool _MsgCache = false;
|
||||
|
||||
bool _AccessLog=false;
|
||||
bool _DMALog=false;
|
||||
bool _WaveLog=false;
|
||||
bool _AccessLog = false;
|
||||
bool _DMALog = false;
|
||||
bool _WaveLog = false;
|
||||
|
||||
bool _CoresDump=false;
|
||||
bool _MemDump=false;
|
||||
bool _RegDump=false;
|
||||
bool _CoresDump = false;
|
||||
bool _MemDump = false;
|
||||
bool _RegDump = false;
|
||||
|
||||
// this is set true if PCSX2 invokes the SetLogDir callback, which tells SPU2-X to use that over
|
||||
// the configured crap in the ini file.
|
||||
|
@ -53,105 +53,105 @@ wxString CoresDumpFileName;
|
|||
wxString MemDumpFileName;
|
||||
wxString RegDumpFileName;
|
||||
|
||||
void CfgSetLogDir( const char* dir )
|
||||
void CfgSetLogDir(const char *dir)
|
||||
{
|
||||
LogsFolder = (dir==NULL) ? wxString(L"logs") : fromUTF8(dir);
|
||||
DumpsFolder = (dir==NULL) ? wxString(L"logs") : fromUTF8(dir);
|
||||
LogLocationSetByPcsx2 = (dir!=NULL);
|
||||
LogsFolder = (dir == NULL) ? wxString(L"logs") : fromUTF8(dir);
|
||||
DumpsFolder = (dir == NULL) ? wxString(L"logs") : fromUTF8(dir);
|
||||
LogLocationSetByPcsx2 = (dir != NULL);
|
||||
}
|
||||
|
||||
FILE* OpenBinaryLog( const wxString& logfile )
|
||||
FILE *OpenBinaryLog(const wxString &logfile)
|
||||
{
|
||||
return wxFopen( Path::Combine(LogsFolder, logfile), L"wb" );
|
||||
return wxFopen(Path::Combine(LogsFolder, logfile), L"wb");
|
||||
}
|
||||
|
||||
FILE* OpenLog( const wxString& logfile )
|
||||
FILE *OpenLog(const wxString &logfile)
|
||||
{
|
||||
return wxFopen( Path::Combine(LogsFolder, logfile), L"w" );
|
||||
return wxFopen(Path::Combine(LogsFolder, logfile), L"w");
|
||||
}
|
||||
|
||||
FILE* OpenDump( const wxString& logfile )
|
||||
FILE *OpenDump(const wxString &logfile)
|
||||
{
|
||||
return wxFopen( Path::Combine(DumpsFolder, logfile), L"w" );
|
||||
return wxFopen(Path::Combine(DumpsFolder, logfile), L"w");
|
||||
}
|
||||
|
||||
namespace DebugConfig {
|
||||
static const wchar_t* Section = L"DEBUG";
|
||||
namespace DebugConfig
|
||||
{
|
||||
static const wchar_t *Section = L"DEBUG";
|
||||
|
||||
static void set_default_filenames()
|
||||
{
|
||||
AccessLogFileName = L"SPU2Log.txt";
|
||||
WaveLogFileName = L"SPU2log.wav";
|
||||
DMA4LogFileName = L"SPU2dma4.dat";
|
||||
DMA7LogFileName = L"SPU2dma7.dat";
|
||||
AccessLogFileName = L"SPU2Log.txt";
|
||||
WaveLogFileName = L"SPU2log.wav";
|
||||
DMA4LogFileName = L"SPU2dma4.dat";
|
||||
DMA7LogFileName = L"SPU2dma7.dat";
|
||||
|
||||
CoresDumpFileName = L"SPU2Cores.txt";
|
||||
MemDumpFileName = L"SPU2mem.dat";
|
||||
RegDumpFileName = L"SPU2regs.dat";
|
||||
CoresDumpFileName = L"SPU2Cores.txt";
|
||||
MemDumpFileName = L"SPU2mem.dat";
|
||||
RegDumpFileName = L"SPU2regs.dat";
|
||||
}
|
||||
|
||||
void ReadSettings()
|
||||
{
|
||||
DebugEnabled = CfgReadBool(Section, L"Global_Enable",0);
|
||||
_MsgToConsole= CfgReadBool(Section, L"Show_Messages",0);
|
||||
_MsgKeyOnOff = CfgReadBool(Section, L"Show_Messages_Key_On_Off",0);
|
||||
_MsgVoiceOff = CfgReadBool(Section, L"Show_Messages_Voice_Off",0);
|
||||
_MsgDMA = CfgReadBool(Section, L"Show_Messages_DMA_Transfer",0);
|
||||
_MsgAutoDMA = CfgReadBool(Section, L"Show_Messages_AutoDMA",0);
|
||||
_MsgOverruns = CfgReadBool(Section, L"Show_Messages_Overruns",0);
|
||||
_MsgCache = CfgReadBool(Section, L"Show_Messages_CacheStats",0);
|
||||
DebugEnabled = CfgReadBool(Section, L"Global_Enable", 0);
|
||||
_MsgToConsole = CfgReadBool(Section, L"Show_Messages", 0);
|
||||
_MsgKeyOnOff = CfgReadBool(Section, L"Show_Messages_Key_On_Off", 0);
|
||||
_MsgVoiceOff = CfgReadBool(Section, L"Show_Messages_Voice_Off", 0);
|
||||
_MsgDMA = CfgReadBool(Section, L"Show_Messages_DMA_Transfer", 0);
|
||||
_MsgAutoDMA = CfgReadBool(Section, L"Show_Messages_AutoDMA", 0);
|
||||
_MsgOverruns = CfgReadBool(Section, L"Show_Messages_Overruns", 0);
|
||||
_MsgCache = CfgReadBool(Section, L"Show_Messages_CacheStats", 0);
|
||||
|
||||
_AccessLog = CfgReadBool(Section, L"Log_Register_Access",0);
|
||||
_DMALog = CfgReadBool(Section, L"Log_DMA_Transfers",0);
|
||||
_WaveLog = CfgReadBool(Section, L"Log_WAVE_Output",0);
|
||||
_AccessLog = CfgReadBool(Section, L"Log_Register_Access", 0);
|
||||
_DMALog = CfgReadBool(Section, L"Log_DMA_Transfers", 0);
|
||||
_WaveLog = CfgReadBool(Section, L"Log_WAVE_Output", 0);
|
||||
|
||||
_CoresDump = CfgReadBool(Section, L"Dump_Info",0);
|
||||
_MemDump = CfgReadBool(Section, L"Dump_Memory",0);
|
||||
_RegDump = CfgReadBool(Section, L"Dump_Regs",0);
|
||||
_CoresDump = CfgReadBool(Section, L"Dump_Info", 0);
|
||||
_MemDump = CfgReadBool(Section, L"Dump_Memory", 0);
|
||||
_RegDump = CfgReadBool(Section, L"Dump_Regs", 0);
|
||||
|
||||
set_default_filenames();
|
||||
set_default_filenames();
|
||||
|
||||
CfgReadStr(Section,L"Access_Log_Filename",AccessLogFileName, L"logs/SPU2Log.txt");
|
||||
CfgReadStr(Section,L"WaveLog_Filename", WaveLogFileName, L"logs/SPU2log.wav");
|
||||
CfgReadStr(Section,L"DMA4Log_Filename", DMA4LogFileName, L"logs/SPU2dma4.dat");
|
||||
CfgReadStr(Section,L"DMA7Log_Filename", DMA7LogFileName, L"logs/SPU2dma7.dat");
|
||||
CfgReadStr(Section, L"Access_Log_Filename", AccessLogFileName, L"logs/SPU2Log.txt");
|
||||
CfgReadStr(Section, L"WaveLog_Filename", WaveLogFileName, L"logs/SPU2log.wav");
|
||||
CfgReadStr(Section, L"DMA4Log_Filename", DMA4LogFileName, L"logs/SPU2dma4.dat");
|
||||
CfgReadStr(Section, L"DMA7Log_Filename", DMA7LogFileName, L"logs/SPU2dma7.dat");
|
||||
|
||||
CfgReadStr(Section,L"Info_Dump_Filename",CoresDumpFileName, L"logs/SPU2Cores.txt");
|
||||
CfgReadStr(Section,L"Mem_Dump_Filename", MemDumpFileName, L"logs/SPU2mem.dat");
|
||||
CfgReadStr(Section,L"Reg_Dump_Filename", RegDumpFileName, L"logs/SPU2regs.dat");
|
||||
CfgReadStr(Section, L"Info_Dump_Filename", CoresDumpFileName, L"logs/SPU2Cores.txt");
|
||||
CfgReadStr(Section, L"Mem_Dump_Filename", MemDumpFileName, L"logs/SPU2mem.dat");
|
||||
CfgReadStr(Section, L"Reg_Dump_Filename", RegDumpFileName, L"logs/SPU2regs.dat");
|
||||
}
|
||||
|
||||
|
||||
void WriteSettings()
|
||||
{
|
||||
CfgWriteBool(Section,L"Global_Enable",DebugEnabled);
|
||||
CfgWriteBool(Section, L"Global_Enable", DebugEnabled);
|
||||
|
||||
CfgWriteBool(Section,L"Show_Messages", _MsgToConsole);
|
||||
CfgWriteBool(Section,L"Show_Messages_Key_On_Off", _MsgKeyOnOff);
|
||||
CfgWriteBool(Section,L"Show_Messages_Voice_Off", _MsgVoiceOff);
|
||||
CfgWriteBool(Section,L"Show_Messages_DMA_Transfer",_MsgDMA);
|
||||
CfgWriteBool(Section,L"Show_Messages_AutoDMA", _MsgAutoDMA);
|
||||
CfgWriteBool(Section,L"Show_Messages_Overruns", _MsgOverruns);
|
||||
CfgWriteBool(Section,L"Show_Messages_CacheStats", _MsgCache);
|
||||
CfgWriteBool(Section, L"Show_Messages", _MsgToConsole);
|
||||
CfgWriteBool(Section, L"Show_Messages_Key_On_Off", _MsgKeyOnOff);
|
||||
CfgWriteBool(Section, L"Show_Messages_Voice_Off", _MsgVoiceOff);
|
||||
CfgWriteBool(Section, L"Show_Messages_DMA_Transfer", _MsgDMA);
|
||||
CfgWriteBool(Section, L"Show_Messages_AutoDMA", _MsgAutoDMA);
|
||||
CfgWriteBool(Section, L"Show_Messages_Overruns", _MsgOverruns);
|
||||
CfgWriteBool(Section, L"Show_Messages_CacheStats", _MsgCache);
|
||||
|
||||
CfgWriteBool(Section,L"Log_Register_Access",_AccessLog);
|
||||
CfgWriteBool(Section,L"Log_DMA_Transfers", _DMALog);
|
||||
CfgWriteBool(Section,L"Log_WAVE_Output", _WaveLog);
|
||||
CfgWriteBool(Section, L"Log_Register_Access", _AccessLog);
|
||||
CfgWriteBool(Section, L"Log_DMA_Transfers", _DMALog);
|
||||
CfgWriteBool(Section, L"Log_WAVE_Output", _WaveLog);
|
||||
|
||||
CfgWriteBool(Section,L"Dump_Info", _CoresDump);
|
||||
CfgWriteBool(Section,L"Dump_Memory",_MemDump);
|
||||
CfgWriteBool(Section,L"Dump_Regs", _RegDump);
|
||||
CfgWriteBool(Section, L"Dump_Info", _CoresDump);
|
||||
CfgWriteBool(Section, L"Dump_Memory", _MemDump);
|
||||
CfgWriteBool(Section, L"Dump_Regs", _RegDump);
|
||||
|
||||
set_default_filenames();
|
||||
CfgWriteStr(Section,L"Access_Log_Filename",AccessLogFileName);
|
||||
CfgWriteStr(Section,L"WaveLog_Filename", WaveLogFileName);
|
||||
CfgWriteStr(Section,L"DMA4Log_Filename", DMA4LogFileName);
|
||||
CfgWriteStr(Section,L"DMA7Log_Filename", DMA7LogFileName);
|
||||
|
||||
CfgWriteStr(Section,L"Info_Dump_Filename",CoresDumpFileName);
|
||||
CfgWriteStr(Section,L"Mem_Dump_Filename", MemDumpFileName);
|
||||
CfgWriteStr(Section,L"Reg_Dump_Filename", RegDumpFileName);
|
||||
set_default_filenames();
|
||||
CfgWriteStr(Section, L"Access_Log_Filename", AccessLogFileName);
|
||||
CfgWriteStr(Section, L"WaveLog_Filename", WaveLogFileName);
|
||||
CfgWriteStr(Section, L"DMA4Log_Filename", DMA4LogFileName);
|
||||
CfgWriteStr(Section, L"DMA7Log_Filename", DMA7LogFileName);
|
||||
|
||||
CfgWriteStr(Section, L"Info_Dump_Filename", CoresDumpFileName);
|
||||
CfgWriteStr(Section, L"Mem_Dump_Filename", MemDumpFileName);
|
||||
CfgWriteStr(Section, L"Reg_Dump_Filename", RegDumpFileName);
|
||||
}
|
||||
|
||||
#ifdef __unix__
|
||||
|
@ -169,26 +169,26 @@ void DisplayDialog()
|
|||
GtkWidget *log_access_check, *log_dma_check, *log_wave_check;
|
||||
GtkWidget *dump_core_check, *dump_mem_check, *dump_reg_check;
|
||||
|
||||
ReadSettings();
|
||||
ReadSettings();
|
||||
|
||||
// Create the widgets
|
||||
dialog = gtk_dialog_new_with_buttons (
|
||||
"Spu2-X Config",
|
||||
NULL, // parent window
|
||||
(GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
|
||||
"OK", GTK_RESPONSE_ACCEPT,
|
||||
"Cancel", GTK_RESPONSE_REJECT,
|
||||
NULL);
|
||||
dialog = gtk_dialog_new_with_buttons(
|
||||
"Spu2-X Config",
|
||||
NULL, // parent window
|
||||
(GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
|
||||
"OK", GTK_RESPONSE_ACCEPT,
|
||||
"Cancel", GTK_RESPONSE_REJECT,
|
||||
NULL);
|
||||
|
||||
main_box = gtk_hbox_new(false, 5);
|
||||
main_frame = gtk_frame_new ("Spu2-X Config");
|
||||
gtk_container_add (GTK_CONTAINER(main_frame), main_box);
|
||||
main_frame = gtk_frame_new("Spu2-X Config");
|
||||
gtk_container_add(GTK_CONTAINER(main_frame), main_box);
|
||||
|
||||
// Message Section
|
||||
|
||||
msg_box = gtk_vbox_new(false, 5);
|
||||
msg_box = gtk_vbox_new(false, 5);
|
||||
|
||||
msg_console_check = gtk_check_button_new_with_label("Show In Console");
|
||||
msg_console_check = gtk_check_button_new_with_label("Show In Console");
|
||||
msg_key_check = gtk_check_button_new_with_label("KeyOn/Off Events");
|
||||
msg_voice_check = gtk_check_button_new_with_label("Voice Stop Events");
|
||||
msg_dma_check = gtk_check_button_new_with_label("DMA Operations");
|
||||
|
@ -196,13 +196,13 @@ void DisplayDialog()
|
|||
msg_overrun_check = gtk_check_button_new_with_label("Buffer Over/Underruns");
|
||||
msg_cache_check = gtk_check_button_new_with_label("ADPCM Cache Statistics");
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(msg_box), msg_console_check);
|
||||
gtk_container_add(GTK_CONTAINER(msg_box), msg_key_check);
|
||||
gtk_container_add(GTK_CONTAINER(msg_box), msg_voice_check);
|
||||
gtk_container_add(GTK_CONTAINER(msg_box), msg_dma_check);
|
||||
gtk_container_add(GTK_CONTAINER(msg_box), msg_autodma_check);
|
||||
gtk_container_add(GTK_CONTAINER(msg_box), msg_overrun_check);
|
||||
gtk_container_add(GTK_CONTAINER(msg_box), msg_cache_check);
|
||||
gtk_container_add(GTK_CONTAINER(msg_box), msg_console_check);
|
||||
gtk_container_add(GTK_CONTAINER(msg_box), msg_key_check);
|
||||
gtk_container_add(GTK_CONTAINER(msg_box), msg_voice_check);
|
||||
gtk_container_add(GTK_CONTAINER(msg_box), msg_dma_check);
|
||||
gtk_container_add(GTK_CONTAINER(msg_box), msg_autodma_check);
|
||||
gtk_container_add(GTK_CONTAINER(msg_box), msg_overrun_check);
|
||||
gtk_container_add(GTK_CONTAINER(msg_box), msg_cache_check);
|
||||
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(msg_console_check), _MsgToConsole);
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(msg_key_check), _MsgKeyOnOff);
|
||||
|
@ -212,26 +212,26 @@ void DisplayDialog()
|
|||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(msg_overrun_check), _MsgOverruns);
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(msg_cache_check), _MsgCache);
|
||||
|
||||
msg_frame = gtk_frame_new ("Message/Log Options");
|
||||
gtk_container_add (GTK_CONTAINER(msg_frame), msg_box);
|
||||
msg_frame = gtk_frame_new("Message/Log Options");
|
||||
gtk_container_add(GTK_CONTAINER(msg_frame), msg_box);
|
||||
|
||||
// Log Section
|
||||
log_box = gtk_vbox_new(false, 5);
|
||||
log_box = gtk_vbox_new(false, 5);
|
||||
|
||||
log_access_check = gtk_check_button_new_with_label("Log Register/DMA Actions");
|
||||
log_dma_check = gtk_check_button_new_with_label("Log DMA Writes");
|
||||
log_wave_check = gtk_check_button_new_with_label("Log Audio Output");
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(log_box), log_access_check);
|
||||
gtk_container_add(GTK_CONTAINER(log_box), log_dma_check);
|
||||
gtk_container_add(GTK_CONTAINER(log_box), log_wave_check);
|
||||
gtk_container_add(GTK_CONTAINER(log_box), log_access_check);
|
||||
gtk_container_add(GTK_CONTAINER(log_box), log_dma_check);
|
||||
gtk_container_add(GTK_CONTAINER(log_box), log_wave_check);
|
||||
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(log_access_check), _AccessLog);
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(log_dma_check), _DMALog);
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(log_wave_check), _WaveLog);
|
||||
|
||||
log_frame = gtk_frame_new ("Log Options");
|
||||
gtk_container_add (GTK_CONTAINER(log_frame), log_box);
|
||||
log_frame = gtk_frame_new("Log Options");
|
||||
gtk_container_add(GTK_CONTAINER(log_frame), log_box);
|
||||
|
||||
// Dump Section
|
||||
dump_box = gtk_vbox_new(false, 5);
|
||||
|
@ -240,56 +240,54 @@ void DisplayDialog()
|
|||
dump_mem_check = gtk_check_button_new_with_label("Dump Memory Contents");
|
||||
dump_reg_check = gtk_check_button_new_with_label("Dump Register Data");
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(dump_box), dump_core_check);
|
||||
gtk_container_add(GTK_CONTAINER(dump_box), dump_mem_check);
|
||||
gtk_container_add(GTK_CONTAINER(dump_box), dump_reg_check);
|
||||
gtk_container_add(GTK_CONTAINER(dump_box), dump_core_check);
|
||||
gtk_container_add(GTK_CONTAINER(dump_box), dump_mem_check);
|
||||
gtk_container_add(GTK_CONTAINER(dump_box), dump_reg_check);
|
||||
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dump_core_check), _CoresDump);
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dump_mem_check), _MemDump);
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dump_reg_check), _RegDump);
|
||||
|
||||
dump_frame = gtk_frame_new ("Dumps (on close)");
|
||||
gtk_container_add (GTK_CONTAINER(dump_frame), dump_box);
|
||||
dump_frame = gtk_frame_new("Dumps (on close)");
|
||||
gtk_container_add(GTK_CONTAINER(dump_frame), dump_box);
|
||||
|
||||
// Add everything
|
||||
|
||||
gtk_container_add (GTK_CONTAINER(main_box), msg_frame);
|
||||
gtk_container_add (GTK_CONTAINER(main_box), log_frame);
|
||||
gtk_container_add (GTK_CONTAINER(main_box), dump_frame);
|
||||
gtk_container_add(GTK_CONTAINER(main_box), msg_frame);
|
||||
gtk_container_add(GTK_CONTAINER(main_box), log_frame);
|
||||
gtk_container_add(GTK_CONTAINER(main_box), dump_frame);
|
||||
|
||||
// Add all our widgets, and show everything we've added to the dialog.
|
||||
gtk_container_add (GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), main_frame);
|
||||
gtk_widget_show_all (dialog);
|
||||
gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), main_frame);
|
||||
gtk_widget_show_all(dialog);
|
||||
|
||||
return_value = gtk_dialog_run (GTK_DIALOG (dialog));
|
||||
return_value = gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
|
||||
if (return_value == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
_MsgToConsole = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(msg_console_check));
|
||||
_MsgKeyOnOff = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(msg_key_check));
|
||||
_MsgVoiceOff = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(msg_voice_check));
|
||||
_MsgDMA = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(msg_dma_check));
|
||||
_MsgAutoDMA = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(msg_autodma_check));
|
||||
_MsgOverruns = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(msg_overrun_check));
|
||||
_MsgCache = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(msg_cache_check));
|
||||
if (return_value == GTK_RESPONSE_ACCEPT) {
|
||||
_MsgToConsole = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(msg_console_check));
|
||||
_MsgKeyOnOff = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(msg_key_check));
|
||||
_MsgVoiceOff = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(msg_voice_check));
|
||||
_MsgDMA = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(msg_dma_check));
|
||||
_MsgAutoDMA = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(msg_autodma_check));
|
||||
_MsgOverruns = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(msg_overrun_check));
|
||||
_MsgCache = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(msg_cache_check));
|
||||
|
||||
_AccessLog = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(log_access_check));
|
||||
_DMALog = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(log_dma_check));
|
||||
_WaveLog = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(log_wave_check));
|
||||
_AccessLog = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(log_access_check));
|
||||
_DMALog = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(log_dma_check));
|
||||
_WaveLog = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(log_wave_check));
|
||||
|
||||
_CoresDump = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dump_core_check));
|
||||
_MemDump = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dump_mem_check));
|
||||
_RegDump = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dump_reg_check));
|
||||
_CoresDump = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dump_core_check));
|
||||
_MemDump = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dump_mem_check));
|
||||
_RegDump = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dump_reg_check));
|
||||
}
|
||||
|
||||
gtk_widget_destroy (dialog);
|
||||
gtk_widget_destroy(dialog);
|
||||
|
||||
WriteSettings();
|
||||
}
|
||||
#else
|
||||
void DisplayDialog()
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -26,150 +26,147 @@
|
|||
|
||||
namespace SoundtouchCfg
|
||||
{
|
||||
// Timestretch Slider Bounds, Min/Max
|
||||
static const int SequenceLen_Min = 20;
|
||||
static const int SequenceLen_Max = 100;
|
||||
// Timestretch Slider Bounds, Min/Max
|
||||
static const int SequenceLen_Min = 20;
|
||||
static const int SequenceLen_Max = 100;
|
||||
|
||||
static const int SeekWindow_Min = 10;
|
||||
static const int SeekWindow_Max = 30;
|
||||
static const int SeekWindow_Min = 10;
|
||||
static const int SeekWindow_Max = 30;
|
||||
|
||||
static const int Overlap_Min = 5;
|
||||
static const int Overlap_Max = 15;
|
||||
static const int Overlap_Min = 5;
|
||||
static const int Overlap_Max = 15;
|
||||
|
||||
static int SequenceLenMS = 30;
|
||||
static int SeekWindowMS = 20;
|
||||
static int OverlapMS = 10;
|
||||
static int SequenceLenMS = 30;
|
||||
static int SeekWindowMS = 20;
|
||||
static int OverlapMS = 10;
|
||||
|
||||
static void ClampValues()
|
||||
{
|
||||
Clampify( SequenceLenMS, SequenceLen_Min, SequenceLen_Max );
|
||||
Clampify( SeekWindowMS, SeekWindow_Min, SeekWindow_Max );
|
||||
Clampify( OverlapMS, Overlap_Min, Overlap_Max );
|
||||
}
|
||||
static void ClampValues()
|
||||
{
|
||||
Clampify(SequenceLenMS, SequenceLen_Min, SequenceLen_Max);
|
||||
Clampify(SeekWindowMS, SeekWindow_Min, SeekWindow_Max);
|
||||
Clampify(OverlapMS, Overlap_Min, Overlap_Max);
|
||||
}
|
||||
|
||||
void ApplySettings( soundtouch::SoundTouch& sndtouch )
|
||||
{
|
||||
sndtouch.setSetting( SETTING_SEQUENCE_MS, SequenceLenMS );
|
||||
sndtouch.setSetting( SETTING_SEEKWINDOW_MS, SeekWindowMS );
|
||||
sndtouch.setSetting( SETTING_OVERLAP_MS, OverlapMS );
|
||||
}
|
||||
void ApplySettings(soundtouch::SoundTouch &sndtouch)
|
||||
{
|
||||
sndtouch.setSetting(SETTING_SEQUENCE_MS, SequenceLenMS);
|
||||
sndtouch.setSetting(SETTING_SEEKWINDOW_MS, SeekWindowMS);
|
||||
sndtouch.setSetting(SETTING_OVERLAP_MS, OverlapMS);
|
||||
}
|
||||
|
||||
void ReadSettings()
|
||||
{
|
||||
SequenceLenMS = CfgReadInt( L"SOUNDTOUCH", L"SequenceLengthMS", 30 );
|
||||
SeekWindowMS = CfgReadInt( L"SOUNDTOUCH", L"SeekWindowMS", 20 );
|
||||
OverlapMS = CfgReadInt( L"SOUNDTOUCH", L"OverlapMS", 10 );
|
||||
void ReadSettings()
|
||||
{
|
||||
SequenceLenMS = CfgReadInt(L"SOUNDTOUCH", L"SequenceLengthMS", 30);
|
||||
SeekWindowMS = CfgReadInt(L"SOUNDTOUCH", L"SeekWindowMS", 20);
|
||||
OverlapMS = CfgReadInt(L"SOUNDTOUCH", L"OverlapMS", 10);
|
||||
|
||||
ClampValues();
|
||||
WriteSettings();
|
||||
}
|
||||
ClampValues();
|
||||
WriteSettings();
|
||||
}
|
||||
|
||||
void WriteSettings()
|
||||
{
|
||||
CfgWriteInt( L"SOUNDTOUCH", L"SequenceLengthMS", SequenceLenMS );
|
||||
CfgWriteInt( L"SOUNDTOUCH", L"SeekWindowMS", SeekWindowMS );
|
||||
CfgWriteInt( L"SOUNDTOUCH", L"OverlapMS", OverlapMS );
|
||||
}
|
||||
void WriteSettings()
|
||||
{
|
||||
CfgWriteInt(L"SOUNDTOUCH", L"SequenceLengthMS", SequenceLenMS);
|
||||
CfgWriteInt(L"SOUNDTOUCH", L"SeekWindowMS", SeekWindowMS);
|
||||
CfgWriteInt(L"SOUNDTOUCH", L"OverlapMS", OverlapMS);
|
||||
}
|
||||
|
||||
#ifdef __unix__
|
||||
static GtkWidget *seq_label, *seek_label, *over_label;
|
||||
static GtkWidget *seq_slide, *seek_slide, *over_slide;
|
||||
static GtkWidget *seq_label, *seek_label, *over_label;
|
||||
static GtkWidget *seq_slide, *seek_slide, *over_slide;
|
||||
|
||||
|
||||
void restore_defaults()
|
||||
{
|
||||
gtk_range_set_value(GTK_RANGE(seq_slide), 30);
|
||||
gtk_range_set_value(GTK_RANGE(seek_slide), 20);
|
||||
gtk_range_set_value(GTK_RANGE(over_slide), 10);
|
||||
}
|
||||
void restore_defaults()
|
||||
{
|
||||
gtk_range_set_value(GTK_RANGE(seq_slide), 30);
|
||||
gtk_range_set_value(GTK_RANGE(seek_slide), 20);
|
||||
gtk_range_set_value(GTK_RANGE(over_slide), 10);
|
||||
}
|
||||
|
||||
|
||||
void DisplayDialog()
|
||||
{
|
||||
int return_value;
|
||||
GtkWidget *dialog, *main_label, *main_frame, *main_box;
|
||||
GtkWidget *default_button;
|
||||
void DisplayDialog()
|
||||
{
|
||||
int return_value;
|
||||
GtkWidget *dialog, *main_label, *main_frame, *main_box;
|
||||
GtkWidget *default_button;
|
||||
|
||||
ReadSettings();
|
||||
ReadSettings();
|
||||
|
||||
/* Create the widgets */
|
||||
dialog = gtk_dialog_new_with_buttons (
|
||||
"Advanced Settings",
|
||||
NULL, /* parent window*/
|
||||
(GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
|
||||
"OK", GTK_RESPONSE_ACCEPT,
|
||||
"Cancel", GTK_RESPONSE_REJECT,
|
||||
NULL);
|
||||
/* Create the widgets */
|
||||
dialog = gtk_dialog_new_with_buttons(
|
||||
"Advanced Settings",
|
||||
NULL, /* parent window*/
|
||||
(GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
|
||||
"OK", GTK_RESPONSE_ACCEPT,
|
||||
"Cancel", GTK_RESPONSE_REJECT,
|
||||
NULL);
|
||||
|
||||
main_label = gtk_label_new ("These are advanced configuration options fine tuning time stretching behavior. Larger values are better for slowdown, while smaller values are better for speedup (more then 60 fps.). All options are in microseconds.");
|
||||
gtk_label_set_line_wrap (GTK_LABEL(main_label), true);
|
||||
main_label = gtk_label_new("These are advanced configuration options fine tuning time stretching behavior. Larger values are better for slowdown, while smaller values are better for speedup (more then 60 fps.). All options are in microseconds.");
|
||||
gtk_label_set_line_wrap(GTK_LABEL(main_label), true);
|
||||
|
||||
default_button = gtk_button_new_with_label("Reset to Defaults");
|
||||
default_button = gtk_button_new_with_label("Reset to Defaults");
|
||||
|
||||
seq_label = gtk_label_new("Sequence Length");
|
||||
seq_label = gtk_label_new("Sequence Length");
|
||||
#if GTK_MAJOR_VERSION < 3
|
||||
seq_slide = gtk_hscale_new_with_range(SequenceLen_Min, SequenceLen_Max, 2);
|
||||
seq_slide = gtk_hscale_new_with_range(SequenceLen_Min, SequenceLen_Max, 2);
|
||||
#else
|
||||
seq_slide = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, SequenceLen_Min, SequenceLen_Max, 2);
|
||||
seq_slide = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, SequenceLen_Min, SequenceLen_Max, 2);
|
||||
#endif
|
||||
gtk_range_set_value(GTK_RANGE(seq_slide), SequenceLenMS);
|
||||
gtk_range_set_value(GTK_RANGE(seq_slide), SequenceLenMS);
|
||||
|
||||
seek_label = gtk_label_new("Seek Window Size");
|
||||
seek_label = gtk_label_new("Seek Window Size");
|
||||
#if GTK_MAJOR_VERSION < 3
|
||||
seek_slide = gtk_hscale_new_with_range(SeekWindow_Min, SeekWindow_Max, 1);
|
||||
seek_slide = gtk_hscale_new_with_range(SeekWindow_Min, SeekWindow_Max, 1);
|
||||
#else
|
||||
seek_slide = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, SeekWindow_Min, SeekWindow_Max, 1);
|
||||
seek_slide = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, SeekWindow_Min, SeekWindow_Max, 1);
|
||||
#endif
|
||||
gtk_range_set_value(GTK_RANGE(seek_slide), SeekWindowMS);
|
||||
gtk_range_set_value(GTK_RANGE(seek_slide), SeekWindowMS);
|
||||
|
||||
over_label = gtk_label_new("Overlap");
|
||||
over_label = gtk_label_new("Overlap");
|
||||
#if GTK_MAJOR_VERSION < 3
|
||||
over_slide = gtk_hscale_new_with_range(Overlap_Min, Overlap_Max, 1);
|
||||
over_slide = gtk_hscale_new_with_range(Overlap_Min, Overlap_Max, 1);
|
||||
#else
|
||||
over_slide = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, Overlap_Min, Overlap_Max, 1);
|
||||
over_slide = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, Overlap_Min, Overlap_Max, 1);
|
||||
#endif
|
||||
gtk_range_set_value(GTK_RANGE(over_slide), OverlapMS);
|
||||
gtk_range_set_value(GTK_RANGE(over_slide), OverlapMS);
|
||||
|
||||
main_box = gtk_vbox_new(false, 5);
|
||||
main_frame = gtk_frame_new ("Spu2-X Config");
|
||||
main_box = gtk_vbox_new(false, 5);
|
||||
main_frame = gtk_frame_new("Spu2-X Config");
|
||||
|
||||
gtk_container_add(GTK_CONTAINER (main_box), default_button);
|
||||
gtk_container_add(GTK_CONTAINER (main_box), seq_label);
|
||||
gtk_container_add(GTK_CONTAINER (main_box), seq_slide);
|
||||
gtk_container_add(GTK_CONTAINER (main_box), seek_label);
|
||||
gtk_container_add(GTK_CONTAINER (main_box), seek_slide);
|
||||
gtk_container_add(GTK_CONTAINER (main_box), over_label);
|
||||
gtk_container_add(GTK_CONTAINER (main_box), over_slide);
|
||||
gtk_container_add(GTK_CONTAINER(main_frame), main_box);
|
||||
gtk_container_add(GTK_CONTAINER(main_box), default_button);
|
||||
gtk_container_add(GTK_CONTAINER(main_box), seq_label);
|
||||
gtk_container_add(GTK_CONTAINER(main_box), seq_slide);
|
||||
gtk_container_add(GTK_CONTAINER(main_box), seek_label);
|
||||
gtk_container_add(GTK_CONTAINER(main_box), seek_slide);
|
||||
gtk_container_add(GTK_CONTAINER(main_box), over_label);
|
||||
gtk_container_add(GTK_CONTAINER(main_box), over_slide);
|
||||
gtk_container_add(GTK_CONTAINER(main_frame), main_box);
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), main_label);
|
||||
gtk_container_add (GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), main_frame);
|
||||
gtk_widget_show_all (dialog);
|
||||
gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), main_label);
|
||||
gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), main_frame);
|
||||
gtk_widget_show_all(dialog);
|
||||
|
||||
g_signal_connect_swapped(default_button, "clicked", G_CALLBACK(restore_defaults), default_button);
|
||||
g_signal_connect_swapped(default_button, "clicked", G_CALLBACK(restore_defaults), default_button);
|
||||
|
||||
return_value = gtk_dialog_run (GTK_DIALOG (dialog));
|
||||
return_value = gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
|
||||
if (return_value == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
SequenceLenMS = gtk_range_get_value(GTK_RANGE(seq_slide));;
|
||||
SeekWindowMS = gtk_range_get_value(GTK_RANGE(seek_slide));;
|
||||
OverlapMS = gtk_range_get_value(GTK_RANGE(over_slide));;
|
||||
}
|
||||
|
||||
gtk_widget_destroy (dialog);
|
||||
|
||||
WriteSettings();
|
||||
}
|
||||
#else
|
||||
void DisplayDialog()
|
||||
{
|
||||
|
||||
if (return_value == GTK_RESPONSE_ACCEPT) {
|
||||
SequenceLenMS = gtk_range_get_value(GTK_RANGE(seq_slide));
|
||||
SeekWindowMS = gtk_range_get_value(GTK_RANGE(seek_slide));
|
||||
OverlapMS = gtk_range_get_value(GTK_RANGE(over_slide));
|
||||
}
|
||||
|
||||
void restore_defaults()
|
||||
{
|
||||
|
||||
}
|
||||
gtk_widget_destroy(dialog);
|
||||
|
||||
WriteSettings();
|
||||
}
|
||||
#else
|
||||
void DisplayDialog()
|
||||
{
|
||||
}
|
||||
|
||||
void restore_defaults()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// To be continued...
|
||||
// To be continued...
|
||||
|
||||
#include "Dialogs.h"
|
||||
#include <cstring>
|
||||
|
@ -32,34 +32,35 @@ void SysMessage(const char *fmt, ...)
|
|||
vsprintf(msg, fmt, list);
|
||||
va_end(list);
|
||||
|
||||
if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0;
|
||||
if (msg[strlen(msg) - 1] == '\n')
|
||||
msg[strlen(msg) - 1] = 0;
|
||||
|
||||
GtkWidget *dialog;
|
||||
dialog = gtk_message_dialog_new (NULL,
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_INFO,
|
||||
GTK_BUTTONS_OK,
|
||||
"%s", msg);
|
||||
gtk_dialog_run (GTK_DIALOG (dialog));
|
||||
gtk_widget_destroy (dialog);
|
||||
dialog = gtk_message_dialog_new(NULL,
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_INFO,
|
||||
GTK_BUTTONS_OK,
|
||||
"%s", msg);
|
||||
gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
void SysMessage(const wchar_t *fmt, ...)
|
||||
{
|
||||
va_list list;
|
||||
va_start(list,fmt);
|
||||
wxString msg;
|
||||
msg.PrintfV( fmt, list );
|
||||
va_end(list);
|
||||
va_list list;
|
||||
va_start(list, fmt);
|
||||
wxString msg;
|
||||
msg.PrintfV(fmt, list);
|
||||
va_end(list);
|
||||
|
||||
GtkWidget *dialog;
|
||||
dialog = gtk_message_dialog_new (NULL,
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_INFO,
|
||||
GTK_BUTTONS_OK,
|
||||
"%s", msg.ToUTF8().data());
|
||||
gtk_dialog_run (GTK_DIALOG (dialog));
|
||||
gtk_widget_destroy (dialog);
|
||||
dialog = gtk_message_dialog_new(NULL,
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_INFO,
|
||||
GTK_BUTTONS_OK,
|
||||
"%s", msg.ToUTF8().data());
|
||||
gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -67,8 +68,7 @@ void DspUpdate()
|
|||
{
|
||||
}
|
||||
|
||||
s32 DspLoadLibrary(wchar_t* fileName, int modnum)
|
||||
s32 DspLoadLibrary(wchar_t *fileName, int modnum)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,23 +23,23 @@
|
|||
|
||||
namespace DebugConfig
|
||||
{
|
||||
extern void ReadSettings();
|
||||
extern void WriteSettings();
|
||||
extern void DisplayDialog();
|
||||
extern void ReadSettings();
|
||||
extern void WriteSettings();
|
||||
extern void DisplayDialog();
|
||||
}
|
||||
|
||||
extern void CfgSetSettingsDir(const char* dir);
|
||||
extern void CfgSetLogDir(const char* dir);
|
||||
extern void CfgSetSettingsDir(const char *dir);
|
||||
extern void CfgSetLogDir(const char *dir);
|
||||
|
||||
extern void CfgWriteBool(const wchar_t* Section, const wchar_t* Name, bool Value);
|
||||
extern void CfgWriteInt(const wchar_t* Section, const wchar_t* Name, int Value);
|
||||
extern void CfgWriteFloat(const wchar_t* Section, const wchar_t* Name, float Value);
|
||||
extern void CfgWriteStr(const wchar_t* Section, const wchar_t* Name, const wxString& Data);
|
||||
extern void CfgWriteBool(const wchar_t *Section, const wchar_t *Name, bool Value);
|
||||
extern void CfgWriteInt(const wchar_t *Section, const wchar_t *Name, int Value);
|
||||
extern void CfgWriteFloat(const wchar_t *Section, const wchar_t *Name, float Value);
|
||||
extern void CfgWriteStr(const wchar_t *Section, const wchar_t *Name, const wxString &Data);
|
||||
|
||||
extern bool CfgReadBool(const wchar_t *Section,const wchar_t* Name, bool Default);
|
||||
extern void CfgReadStr(const wchar_t* Section, const wchar_t* Name, wxString& Data, const wchar_t* Default);
|
||||
extern bool CfgReadBool(const wchar_t *Section, const wchar_t *Name, bool Default);
|
||||
extern void CfgReadStr(const wchar_t *Section, const wchar_t *Name, wxString &Data, const wchar_t *Default);
|
||||
//extern void CfgReadStr(const wchar_t* Section, const wchar_t* Name, wchar_t* Data, int DataSize, const wchar_t* Default);
|
||||
extern int CfgReadInt(const wchar_t* Section, const wchar_t* Name,int Default) ;
|
||||
extern float CfgReadFloat(const wchar_t* Section, const wchar_t* Name, float Default);
|
||||
extern int CfgReadInt(const wchar_t *Section, const wchar_t *Name, int Default);
|
||||
extern float CfgReadFloat(const wchar_t *Section, const wchar_t *Name, float Default);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -20,75 +20,75 @@
|
|||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
template< typename FloatType > __forceinline
|
||||
LowPassFilter<FloatType>::LowPassFilter( FloatType freq, FloatType srate )
|
||||
template <typename FloatType>
|
||||
__forceinline LowPassFilter<FloatType>::LowPassFilter(FloatType freq, FloatType srate)
|
||||
{
|
||||
typedef FloatType FT;
|
||||
typedef FloatType FT;
|
||||
|
||||
FloatType omega = (FT)2.0 * freq / srate;
|
||||
static const FloatType g = (FT)1.0;
|
||||
FloatType omega = (FT)2.0 * freq / srate;
|
||||
static const FloatType g = (FT)1.0;
|
||||
|
||||
// calculating coefficients:
|
||||
// calculating coefficients:
|
||||
|
||||
FloatType k,p,q,a;
|
||||
FloatType a0,a1,a2,a3,a4;
|
||||
FloatType k, p, q, a;
|
||||
FloatType a0, a1, a2, a3, a4;
|
||||
|
||||
k = ((FT)4.0*g-(FT)3.0)/(g+(FT)1.0);
|
||||
p = (FT)1.0-(FT)0.25*k;
|
||||
p *= p;
|
||||
k = ((FT)4.0 * g - (FT)3.0) / (g + (FT)1.0);
|
||||
p = (FT)1.0 - (FT)0.25 * k;
|
||||
p *= p;
|
||||
|
||||
// LP:
|
||||
a = (FT)1.0/(tan((FT)0.5*omega)*((FT)1.0+p));
|
||||
p = (FT)1.0+a;
|
||||
q = (FT)1.0-a;
|
||||
// LP:
|
||||
a = (FT)1.0 / (tan((FT)0.5 * omega) * ((FT)1.0 + p));
|
||||
p = (FT)1.0 + a;
|
||||
q = (FT)1.0 - a;
|
||||
|
||||
a0 = (FT)1.0/(k+p*p*p*p);
|
||||
a1 = (FT)4.0*(k+p*p*p*q);
|
||||
a2 = (FT)6.0*(k+p*p*q*q);
|
||||
a3 = (FT)4.0*(k+p*q*q*q);
|
||||
a4 = (k+q*q*q*q);
|
||||
p = a0*(k+(FT)1.0);
|
||||
a0 = (FT)1.0 / (k + p * p * p * p);
|
||||
a1 = (FT)4.0 * (k + p * p * p * q);
|
||||
a2 = (FT)6.0 * (k + p * p * q * q);
|
||||
a3 = (FT)4.0 * (k + p * q * q * q);
|
||||
a4 = (k + q * q * q * q);
|
||||
p = a0 * (k + (FT)1.0);
|
||||
|
||||
coef[0] = p;
|
||||
coef[1] = (FT)4.0*p;
|
||||
coef[2] = (FT)6.0*p;
|
||||
coef[3] = (FT)4.0*p;
|
||||
coef[4] = p;
|
||||
coef[5] = -a1*a0;
|
||||
coef[6] = -a2*a0;
|
||||
coef[7] = -a3*a0;
|
||||
coef[8] = -a4*a0;
|
||||
coef[0] = p;
|
||||
coef[1] = (FT)4.0 * p;
|
||||
coef[2] = (FT)6.0 * p;
|
||||
coef[3] = (FT)4.0 * p;
|
||||
coef[4] = p;
|
||||
coef[5] = -a1 * a0;
|
||||
coef[6] = -a2 * a0;
|
||||
coef[7] = -a3 * a0;
|
||||
coef[8] = -a4 * a0;
|
||||
}
|
||||
|
||||
// Processes a single sample into the LPF.
|
||||
template< typename FloatType > __forceinline
|
||||
FloatType LowPassFilter<FloatType>::sample( FloatType inval )
|
||||
template <typename FloatType>
|
||||
__forceinline FloatType LowPassFilter<FloatType>::sample(FloatType inval)
|
||||
{
|
||||
const FloatType out = (coef[0]*inval) + d[0];
|
||||
d[0] = (coef[1]*inval) + (coef[5]*out) + d[1];
|
||||
d[1] = (coef[2]*inval) + (coef[6]*out) + d[2];
|
||||
d[2] = (coef[3]*inval) + (coef[7]*out) + d[3];
|
||||
d[3] = (coef[4]*inval) + (coef[8]*out);
|
||||
const FloatType out = (coef[0] * inval) + d[0];
|
||||
d[0] = (coef[1] * inval) + (coef[5] * out) + d[1];
|
||||
d[1] = (coef[2] * inval) + (coef[6] * out) + d[2];
|
||||
d[2] = (coef[3] * inval) + (coef[7] * out) + d[3];
|
||||
d[3] = (coef[4] * inval) + (coef[8] * out);
|
||||
|
||||
return out;
|
||||
return out;
|
||||
}
|
||||
|
||||
LowPassFilter32::LowPassFilter32( float freq, float srate ) :
|
||||
impl_lpf( freq, srate )
|
||||
LowPassFilter32::LowPassFilter32(float freq, float srate)
|
||||
: impl_lpf(freq, srate)
|
||||
{
|
||||
}
|
||||
|
||||
LowPassFilter64::LowPassFilter64( double freq, double srate ) :
|
||||
impl_lpf( freq, srate )
|
||||
LowPassFilter64::LowPassFilter64(double freq, double srate)
|
||||
: impl_lpf(freq, srate)
|
||||
{
|
||||
}
|
||||
|
||||
float LowPassFilter32::sample( float inval )
|
||||
float LowPassFilter32::sample(float inval)
|
||||
{
|
||||
return impl_lpf.sample( inval );
|
||||
return impl_lpf.sample(inval);
|
||||
}
|
||||
|
||||
double LowPassFilter64::sample( double inval )
|
||||
double LowPassFilter64::sample(double inval)
|
||||
{
|
||||
return impl_lpf.sample( inval );
|
||||
return impl_lpf.sample(inval);
|
||||
}
|
||||
|
|
|
@ -17,28 +17,28 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
template< typename FloatType >
|
||||
template <typename FloatType>
|
||||
struct LowPassFilter
|
||||
{
|
||||
FloatType coef[9];
|
||||
FloatType d[4];
|
||||
FloatType coef[9];
|
||||
FloatType d[4];
|
||||
|
||||
LowPassFilter( FloatType freq, FloatType srate );
|
||||
FloatType sample( FloatType inval );
|
||||
LowPassFilter(FloatType freq, FloatType srate);
|
||||
FloatType sample(FloatType inval);
|
||||
};
|
||||
|
||||
struct LowPassFilter32
|
||||
{
|
||||
LowPassFilter<float> impl_lpf;
|
||||
LowPassFilter<float> impl_lpf;
|
||||
|
||||
LowPassFilter32( float freq, float srate );
|
||||
float sample( float inval );
|
||||
LowPassFilter32(float freq, float srate);
|
||||
float sample(float inval);
|
||||
};
|
||||
|
||||
struct LowPassFilter64
|
||||
{
|
||||
LowPassFilter<double> impl_lpf;
|
||||
LowPassFilter<double> impl_lpf;
|
||||
|
||||
LowPassFilter64( double freq, double srate );
|
||||
double sample( double inval );
|
||||
LowPassFilter64(double freq, double srate);
|
||||
double sample(double inval);
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -24,115 +24,112 @@ extern float VolumeAdjustFR;
|
|||
|
||||
struct StereoOut32
|
||||
{
|
||||
static StereoOut32 Empty;
|
||||
static StereoOut32 Empty;
|
||||
|
||||
s32 Left;
|
||||
s32 Right;
|
||||
s32 Left;
|
||||
s32 Right;
|
||||
|
||||
StereoOut32() :
|
||||
Left( 0 ),
|
||||
Right( 0 )
|
||||
{
|
||||
}
|
||||
StereoOut32()
|
||||
: Left(0)
|
||||
, Right(0)
|
||||
{
|
||||
}
|
||||
|
||||
StereoOut32( s32 left, s32 right ) :
|
||||
Left( left ),
|
||||
Right( right )
|
||||
{
|
||||
}
|
||||
StereoOut32(s32 left, s32 right)
|
||||
: Left(left)
|
||||
, Right(right)
|
||||
{
|
||||
}
|
||||
|
||||
StereoOut32( const StereoOut16& src );
|
||||
explicit StereoOut32( const StereoOutFloat& src );
|
||||
StereoOut32(const StereoOut16 &src);
|
||||
explicit StereoOut32(const StereoOutFloat &src);
|
||||
|
||||
StereoOut16 DownSample() const;
|
||||
StereoOut16 DownSample() const;
|
||||
|
||||
StereoOut32 operator*( const int& factor ) const
|
||||
{
|
||||
return StereoOut32(
|
||||
Left * factor,
|
||||
Right * factor
|
||||
);
|
||||
}
|
||||
StereoOut32 operator*(const int &factor) const
|
||||
{
|
||||
return StereoOut32(
|
||||
Left * factor,
|
||||
Right * factor);
|
||||
}
|
||||
|
||||
StereoOut32& operator*=( const int& factor )
|
||||
{
|
||||
Left *= factor;
|
||||
Right *= factor;
|
||||
return *this;
|
||||
}
|
||||
StereoOut32 &operator*=(const int &factor)
|
||||
{
|
||||
Left *= factor;
|
||||
Right *= factor;
|
||||
return *this;
|
||||
}
|
||||
|
||||
StereoOut32 operator+( const StereoOut32& right ) const
|
||||
{
|
||||
return StereoOut32(
|
||||
Left + right.Left,
|
||||
Right + right.Right
|
||||
);
|
||||
}
|
||||
StereoOut32 operator+(const StereoOut32 &right) const
|
||||
{
|
||||
return StereoOut32(
|
||||
Left + right.Left,
|
||||
Right + right.Right);
|
||||
}
|
||||
|
||||
StereoOut32 operator/( int src ) const
|
||||
{
|
||||
return StereoOut32( Left / src, Right / src );
|
||||
}
|
||||
StereoOut32 operator/(int src) const
|
||||
{
|
||||
return StereoOut32(Left / src, Right / src);
|
||||
}
|
||||
|
||||
void ResampleFrom( const StereoOut32& src )
|
||||
{
|
||||
this->Left = src.Left << 2;
|
||||
this->Right = src.Right << 2;
|
||||
}
|
||||
void ResampleFrom(const StereoOut32 &src)
|
||||
{
|
||||
this->Left = src.Left << 2;
|
||||
this->Right = src.Right << 2;
|
||||
}
|
||||
|
||||
void AdjustFrom(const StereoOut32& src)
|
||||
{
|
||||
ResampleFrom(src);
|
||||
void AdjustFrom(const StereoOut32 &src)
|
||||
{
|
||||
ResampleFrom(src);
|
||||
|
||||
Left = (s32) (Left * VolumeAdjustFL);
|
||||
Right = (s32) (Right * VolumeAdjustFR);
|
||||
}
|
||||
Left = (s32)(Left * VolumeAdjustFL);
|
||||
Right = (s32)(Right * VolumeAdjustFR);
|
||||
}
|
||||
};
|
||||
|
||||
struct FrequencyResponseFilter
|
||||
{
|
||||
static FrequencyResponseFilter Empty;
|
||||
static FrequencyResponseFilter Empty;
|
||||
|
||||
StereoOut32 History_One_In;
|
||||
StereoOut32 History_One_Out;
|
||||
StereoOut32 History_Two_In;
|
||||
StereoOut32 History_Two_Out;
|
||||
StereoOut32 History_One_In;
|
||||
StereoOut32 History_One_Out;
|
||||
StereoOut32 History_Two_In;
|
||||
StereoOut32 History_Two_Out;
|
||||
|
||||
s32 lx1;
|
||||
s32 lx2;
|
||||
s32 ly1;
|
||||
s32 ly2;
|
||||
s32 lx1;
|
||||
s32 lx2;
|
||||
s32 ly1;
|
||||
s32 ly2;
|
||||
|
||||
float la0, la1, la2, lb1, lb2;
|
||||
float ha0, ha1, ha2, hb1, hb2;
|
||||
float la0, la1, la2, lb1, lb2;
|
||||
float ha0, ha1, ha2, hb1, hb2;
|
||||
|
||||
FrequencyResponseFilter() :
|
||||
History_One_In( 0, 0 ),
|
||||
History_One_Out( 0, 0 ),
|
||||
History_Two_In( 0, 0 ),
|
||||
History_Two_Out( 0, 0 ),
|
||||
lx1 ( 0 ),
|
||||
lx2 ( 0 ),
|
||||
ly1 ( 0 ),
|
||||
ly2 ( 0 ),
|
||||
|
||||
la0 ( 1.00320890889339290000f ),
|
||||
la1 ( -1.97516434134506300000f ),
|
||||
la2 ( 0.97243484967313087000f ),
|
||||
lb1 ( -1.97525280404731810000f ),
|
||||
lb2 ( 0.97555529586426892000f ),
|
||||
FrequencyResponseFilter()
|
||||
: History_One_In(0, 0)
|
||||
, History_One_Out(0, 0)
|
||||
, History_Two_In(0, 0)
|
||||
, History_Two_Out(0, 0)
|
||||
, lx1(0)
|
||||
, lx2(0)
|
||||
, ly1(0)
|
||||
, ly2(0)
|
||||
|
||||
ha0 ( 1.52690772687271160000f ),
|
||||
ha1 ( -1.62653918974914990000f ), //-1.72 = "common equilizer curve" --____--
|
||||
ha2 ( 0.57997976029249387000f ),
|
||||
hb1 ( -0.80955590379048203000f ),
|
||||
hb2 ( 0.28990420120653748000f )
|
||||
{
|
||||
}
|
||||
, la0(1.00320890889339290000f)
|
||||
, la1(-1.97516434134506300000f)
|
||||
, la2(0.97243484967313087000f)
|
||||
, lb1(-1.97525280404731810000f)
|
||||
, lb2(0.97555529586426892000f)
|
||||
|
||||
, ha0(1.52690772687271160000f)
|
||||
, ha1(-1.62653918974914990000f) //-1.72 = "common equilizer curve" --____--
|
||||
, ha2(0.57997976029249387000f)
|
||||
, hb1(-0.80955590379048203000f)
|
||||
, hb2(0.28990420120653748000f)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
extern void Mix();
|
||||
extern s32 clamp_mix( s32 x, u8 bitshift=0 );
|
||||
extern void Mix();
|
||||
extern s32 clamp_mix(s32 x, u8 bitshift = 0);
|
||||
|
||||
extern StereoOut32 clamp_mix( const StereoOut32& sample, u8 bitshift=0 );
|
||||
extern StereoOut32 clamp_mix(const StereoOut32 &sample, u8 bitshift = 0);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -28,42 +28,62 @@
|
|||
#ifdef _MSC_VER
|
||||
#define EXPORT_C_(type) extern "C" type CALLBACK
|
||||
#else
|
||||
#define EXPORT_C_(type) extern "C" __attribute__((stdcall,externally_visible,visibility("default"))) type
|
||||
#define EXPORT_C_(type) extern "C" __attribute__((stdcall, externally_visible, visibility("default"))) type
|
||||
#endif
|
||||
|
||||
// We have our own versions that have the DLLExport attribute configured:
|
||||
|
||||
EXPORT_C_(s32) SPU2init();
|
||||
EXPORT_C_(void) SPU2reset();
|
||||
EXPORT_C_(s32) SPU2open(void *pDsp);
|
||||
EXPORT_C_(void) SPU2close();
|
||||
EXPORT_C_(void) SPU2shutdown();
|
||||
EXPORT_C_(void) SPU2write(u32 mem, u16 value);
|
||||
EXPORT_C_(u16) SPU2read(u32 mem);
|
||||
EXPORT_C_(s32)
|
||||
SPU2init();
|
||||
EXPORT_C_(void)
|
||||
SPU2reset();
|
||||
EXPORT_C_(s32)
|
||||
SPU2open(void *pDsp);
|
||||
EXPORT_C_(void)
|
||||
SPU2close();
|
||||
EXPORT_C_(void)
|
||||
SPU2shutdown();
|
||||
EXPORT_C_(void)
|
||||
SPU2write(u32 mem, u16 value);
|
||||
EXPORT_C_(u16)
|
||||
SPU2read(u32 mem);
|
||||
|
||||
#ifdef ENABLE_NEW_IOPDMA_SPU2
|
||||
EXPORT_C_(s32) SPU2dmaRead(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed);
|
||||
EXPORT_C_(s32) SPU2dmaWrite(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed);
|
||||
EXPORT_C_(void) SPU2dmaInterrupt(s32 channel);
|
||||
EXPORT_C_(s32)
|
||||
SPU2dmaRead(s32 channel, u32 *data, u32 bytesLeft, u32 *bytesProcessed);
|
||||
EXPORT_C_(s32)
|
||||
SPU2dmaWrite(s32 channel, u32 *data, u32 bytesLeft, u32 *bytesProcessed);
|
||||
EXPORT_C_(void)
|
||||
SPU2dmaInterrupt(s32 channel);
|
||||
|
||||
// dma irq callbacks not needed anymore, they are handled by the dmac
|
||||
EXPORT_C_(void) SPU2irqCallback(void (*SPU2callback)());
|
||||
EXPORT_C_(void)
|
||||
SPU2irqCallback(void (*SPU2callback)());
|
||||
#else
|
||||
// These defines are useless and gcc-4.6 complain about redefinition
|
||||
// so we remove them on linux
|
||||
#ifndef __POSIX__
|
||||
EXPORT_C_(void) SPU2readDMA4Mem(u16 *pMem, u32 size);
|
||||
EXPORT_C_(void) SPU2writeDMA4Mem(u16 *pMem, u32 size);
|
||||
EXPORT_C_(void) SPU2interruptDMA4();
|
||||
EXPORT_C_(void) SPU2readDMA7Mem(u16* pMem, u32 size);
|
||||
EXPORT_C_(void) SPU2writeDMA7Mem(u16 *pMem, u32 size);
|
||||
EXPORT_C_(void) SPU2interruptDMA7();
|
||||
EXPORT_C_(void)
|
||||
SPU2readDMA4Mem(u16 *pMem, u32 size);
|
||||
EXPORT_C_(void)
|
||||
SPU2writeDMA4Mem(u16 *pMem, u32 size);
|
||||
EXPORT_C_(void)
|
||||
SPU2interruptDMA4();
|
||||
EXPORT_C_(void)
|
||||
SPU2readDMA7Mem(u16 *pMem, u32 size);
|
||||
EXPORT_C_(void)
|
||||
SPU2writeDMA7Mem(u16 *pMem, u32 size);
|
||||
EXPORT_C_(void)
|
||||
SPU2interruptDMA7();
|
||||
|
||||
// all addresses passed by dma will be pointers to the array starting at baseaddr
|
||||
// This function is necessary to successfully save and reload the spu2 state
|
||||
EXPORT_C_(u32) SPU2ReadMemAddr(int core);
|
||||
EXPORT_C_(void) SPU2WriteMemAddr(int core,u32 value);
|
||||
EXPORT_C_(void) SPU2irqCallback(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)());
|
||||
EXPORT_C_(u32)
|
||||
SPU2ReadMemAddr(int core);
|
||||
EXPORT_C_(void)
|
||||
SPU2WriteMemAddr(int core, u32 value);
|
||||
EXPORT_C_(void)
|
||||
SPU2irqCallback(void (*SPU2callback)(), void (*DMA4callback)(), void (*DMA7callback)());
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -71,25 +91,32 @@ EXPORT_C_(void) SPU2irqCallback(void (*SPU2callback)(),void (*DMA4callback)(),vo
|
|||
// if start is 1, starts recording spu2 data, else stops
|
||||
// returns a non zero value if successful
|
||||
// for now, pData is not used
|
||||
EXPORT_C_(int) SPU2setupRecording(int start, void* pData);
|
||||
EXPORT_C_(int)
|
||||
SPU2setupRecording(int start, void *pData);
|
||||
|
||||
EXPORT_C_(void) SPU2setClockPtr(u32* ptr);
|
||||
EXPORT_C_(void)
|
||||
SPU2setClockPtr(u32 *ptr);
|
||||
|
||||
EXPORT_C_(void) SPU2async(u32 cycles);
|
||||
EXPORT_C_(s32) SPU2freeze(int mode, freezeData *data);
|
||||
EXPORT_C_(void) SPU2configure();
|
||||
EXPORT_C_(void) SPU2about();
|
||||
EXPORT_C_(s32) SPU2test();
|
||||
EXPORT_C_(void)
|
||||
SPU2async(u32 cycles);
|
||||
EXPORT_C_(s32)
|
||||
SPU2freeze(int mode, freezeData *data);
|
||||
EXPORT_C_(void)
|
||||
SPU2configure();
|
||||
EXPORT_C_(void)
|
||||
SPU2about();
|
||||
EXPORT_C_(s32)
|
||||
SPU2test();
|
||||
|
||||
#include "Spu2replay.h"
|
||||
|
||||
extern u8 callirq;
|
||||
|
||||
extern void (* _irqcallback)();
|
||||
extern void (*_irqcallback)();
|
||||
|
||||
#ifndef ENABLE_NEW_IOPDMA_SPU2
|
||||
extern void (* dma4callback)();
|
||||
extern void (* dma7callback)();
|
||||
extern void (*dma4callback)();
|
||||
extern void (*dma7callback)();
|
||||
|
||||
extern s16 *input_data;
|
||||
extern u32 input_data_ptr;
|
||||
|
@ -99,11 +126,11 @@ extern double srate_pv;
|
|||
|
||||
extern int recording;
|
||||
extern u32 lClocks;
|
||||
extern u32* cyclePtr;
|
||||
extern u32 *cyclePtr;
|
||||
|
||||
extern void SPU2writeLog( const char* action, u32 rmem, u16 value );
|
||||
extern void SPU2writeLog(const char *action, u32 rmem, u16 value);
|
||||
extern void TimeUpdate(u32 cClocks);
|
||||
extern void SPU2_FastWrite( u32 rmem, u16 value );
|
||||
extern void SPU2_FastWrite(u32 rmem, u16 value);
|
||||
|
||||
extern void LowPassFilterInit();
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include "Global.h"
|
||||
#include "Dma.h"
|
||||
|
||||
#include "PS2E-spu2.h" // required for ENABLE_NEW_IOPDMA_SPU2 define
|
||||
#include "PS2E-spu2.h" // required for ENABLE_NEW_IOPDMA_SPU2 define
|
||||
|
||||
// Core 0 Input is "SPDIF mode" - Source audio is AC3 compressed.
|
||||
|
||||
|
@ -31,148 +31,147 @@
|
|||
//
|
||||
StereoOut32 V_Core::ReadInput_HiFi()
|
||||
{
|
||||
if (psxmode)ConLog("ReadInput_HiFi!!!!!\n");
|
||||
InputPosRead &= ~1;
|
||||
//
|
||||
//#ifdef PCM24_S1_INTERLEAVE
|
||||
// StereoOut32 retval(
|
||||
// *((s32*)(ADMATempBuffer+(InputPosRead<<1))),
|
||||
// *((s32*)(ADMATempBuffer+(InputPosRead<<1)+2))
|
||||
// );
|
||||
//#else
|
||||
// StereoOut32 retval(
|
||||
// (s32&)(ADMATempBuffer[InputPosRead]),
|
||||
// (s32&)(ADMATempBuffer[InputPosRead+0x200])
|
||||
// );
|
||||
//#endif
|
||||
if (psxmode)
|
||||
ConLog("ReadInput_HiFi!!!!!\n");
|
||||
InputPosRead &= ~1;
|
||||
//
|
||||
//#ifdef PCM24_S1_INTERLEAVE
|
||||
// StereoOut32 retval(
|
||||
// *((s32*)(ADMATempBuffer+(InputPosRead<<1))),
|
||||
// *((s32*)(ADMATempBuffer+(InputPosRead<<1)+2))
|
||||
// );
|
||||
//#else
|
||||
// StereoOut32 retval(
|
||||
// (s32&)(ADMATempBuffer[InputPosRead]),
|
||||
// (s32&)(ADMATempBuffer[InputPosRead+0x200])
|
||||
// );
|
||||
//#endif
|
||||
|
||||
StereoOut32 retval(
|
||||
(s32&)(*GetMemPtr(0x2000 + (Index<<10) + InputPosRead)),
|
||||
(s32&)(*GetMemPtr(0x2200 + (Index<<10) + InputPosRead))
|
||||
);
|
||||
StereoOut32 retval(
|
||||
(s32 &)(*GetMemPtr(0x2000 + (Index << 10) + InputPosRead)),
|
||||
(s32 &)(*GetMemPtr(0x2200 + (Index << 10) + InputPosRead)));
|
||||
|
||||
if( Index == 1 )
|
||||
{
|
||||
// CDDA Mode:
|
||||
// give 30 bit data (SndOut downsamples the rest of the way)
|
||||
// HACKFIX: 28 bits seems better according to rama. I should take some time and do some
|
||||
// bitcounting on this one. --air
|
||||
retval.Left >>= 4;
|
||||
retval.Right >>= 4;
|
||||
}
|
||||
if (Index == 1) {
|
||||
// CDDA Mode:
|
||||
// give 30 bit data (SndOut downsamples the rest of the way)
|
||||
// HACKFIX: 28 bits seems better according to rama. I should take some time and do some
|
||||
// bitcounting on this one. --air
|
||||
retval.Left >>= 4;
|
||||
retval.Right >>= 4;
|
||||
}
|
||||
|
||||
InputPosRead += 2;
|
||||
InputPosRead += 2;
|
||||
|
||||
// Why does CDDA mode check for InputPos == 0x100? In the old code, SPDIF mode did not but CDDA did.
|
||||
// One of these seems wrong, they should be the same. Since standard ADMA checks too I'm assuming that as default. -- air
|
||||
// Why does CDDA mode check for InputPos == 0x100? In the old code, SPDIF mode did not but CDDA did.
|
||||
// One of these seems wrong, they should be the same. Since standard ADMA checks too I'm assuming that as default. -- air
|
||||
|
||||
if( (InputPosRead==0x100) || (InputPosRead>=0x200) )
|
||||
{
|
||||
if ((InputPosRead == 0x100) || (InputPosRead >= 0x200)) {
|
||||
#ifdef ENABLE_NEW_IOPDMA_SPU2
|
||||
// WARNING: Assumes this to be in the same thread as the dmas
|
||||
AutoDmaFree += 0x200;
|
||||
// WARNING: Assumes this to be in the same thread as the dmas
|
||||
AutoDmaFree += 0x200;
|
||||
#else
|
||||
AdmaInProgress = 0;
|
||||
if(InputDataLeft >= 0x200)
|
||||
{
|
||||
AdmaInProgress = 0;
|
||||
if (InputDataLeft >= 0x200) {
|
||||
#ifdef PCM24_S1_INTERLEAVE
|
||||
AutoDMAReadBuffer(1);
|
||||
AutoDMAReadBuffer(1);
|
||||
#else
|
||||
AutoDMAReadBuffer(0);
|
||||
AutoDMAReadBuffer(0);
|
||||
#endif
|
||||
AdmaInProgress = 1;
|
||||
AdmaInProgress = 1;
|
||||
|
||||
TSA = (Index<<10) + InputPosRead;
|
||||
TSA = (Index << 10) + InputPosRead;
|
||||
|
||||
if (InputDataLeft < 0x200)
|
||||
{
|
||||
FileLog("[%10d] %s AutoDMA%c block end.\n", (Index==1) ? "CDDA" : "SPDIF", Cycles, GetDmaIndexChar());
|
||||
if (InputDataLeft < 0x200) {
|
||||
FileLog("[%10d] %s AutoDMA%c block end.\n", (Index == 1) ? "CDDA" : "SPDIF", Cycles, GetDmaIndexChar());
|
||||
|
||||
if( IsDevBuild )
|
||||
{
|
||||
if(InputDataLeft > 0)
|
||||
{
|
||||
if(MsgAutoDMA()) ConLog("WARNING: adma buffer didn't finish with a whole block!!\n");
|
||||
}
|
||||
}
|
||||
InputDataLeft = 0;
|
||||
// Hack, kinda. We call the interrupt early here, since PCSX2 doesn't like them delayed.
|
||||
//DMAICounter = 1;
|
||||
if(Index == 0) { if(dma4callback) dma4callback(); }
|
||||
else { if(dma7callback) dma7callback(); }
|
||||
}
|
||||
}
|
||||
if (IsDevBuild) {
|
||||
if (InputDataLeft > 0) {
|
||||
if (MsgAutoDMA())
|
||||
ConLog("WARNING: adma buffer didn't finish with a whole block!!\n");
|
||||
}
|
||||
}
|
||||
InputDataLeft = 0;
|
||||
// Hack, kinda. We call the interrupt early here, since PCSX2 doesn't like them delayed.
|
||||
//DMAICounter = 1;
|
||||
if (Index == 0) {
|
||||
if (dma4callback)
|
||||
dma4callback();
|
||||
} else {
|
||||
if (dma7callback)
|
||||
dma7callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
InputPosRead &= 0x1ff;
|
||||
}
|
||||
return retval;
|
||||
InputPosRead &= 0x1ff;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
StereoOut32 V_Core::ReadInput()
|
||||
{
|
||||
StereoOut32 retval;
|
||||
StereoOut32 retval;
|
||||
|
||||
if( (Index!=1) || ((PlayMode&2)==0) )
|
||||
{
|
||||
for (int i=0; i<2; i++)
|
||||
if (Cores[i].IRQEnable && 0x2000 + (Index << 10) + InputPosRead == (Cores[i].IRQA & 0xfffffdff))
|
||||
SetIrqCall(i);
|
||||
if ((Index != 1) || ((PlayMode & 2) == 0)) {
|
||||
for (int i = 0; i < 2; i++)
|
||||
if (Cores[i].IRQEnable && 0x2000 + (Index << 10) + InputPosRead == (Cores[i].IRQA & 0xfffffdff))
|
||||
SetIrqCall(i);
|
||||
|
||||
//retval = StereoOut32(
|
||||
// (s32)ADMATempBuffer[InputPosRead],
|
||||
// (s32)ADMATempBuffer[InputPosRead+0x200]
|
||||
//);
|
||||
retval = StereoOut32(
|
||||
(s32)(*GetMemPtr(0x2000 + (Index<<10) + InputPosRead)),
|
||||
(s32)(*GetMemPtr(0x2200 + (Index<<10) + InputPosRead))
|
||||
);
|
||||
}
|
||||
//retval = StereoOut32(
|
||||
// (s32)ADMATempBuffer[InputPosRead],
|
||||
// (s32)ADMATempBuffer[InputPosRead+0x200]
|
||||
//);
|
||||
retval = StereoOut32(
|
||||
(s32)(*GetMemPtr(0x2000 + (Index << 10) + InputPosRead)),
|
||||
(s32)(*GetMemPtr(0x2200 + (Index << 10) + InputPosRead)));
|
||||
}
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
DebugCores[Index].admaWaveformL[InputPosRead%0x100]=retval.Left;
|
||||
DebugCores[Index].admaWaveformR[InputPosRead%0x100]=retval.Right;
|
||||
DebugCores[Index].admaWaveformL[InputPosRead % 0x100] = retval.Left;
|
||||
DebugCores[Index].admaWaveformR[InputPosRead % 0x100] = retval.Right;
|
||||
#endif
|
||||
|
||||
InputPosRead++;
|
||||
InputPosRead++;
|
||||
|
||||
if (AutoDMACtrl & (Index + 1) && (InputPosRead == 0x100 || InputPosRead == 0x200))
|
||||
{
|
||||
if (AutoDMACtrl & (Index + 1) && (InputPosRead == 0x100 || InputPosRead == 0x200)) {
|
||||
#ifdef ENABLE_NEW_IOPDMA_SPU2
|
||||
// WARNING: Assumes this to be in the same thread as the dmas
|
||||
AutoDmaFree += 0x200;
|
||||
// WARNING: Assumes this to be in the same thread as the dmas
|
||||
AutoDmaFree += 0x200;
|
||||
#else
|
||||
AdmaInProgress = 0;
|
||||
if(InputDataLeft >= 0x200)
|
||||
{
|
||||
//u8 k=InputDataLeft>=InputDataProgress;
|
||||
AdmaInProgress = 0;
|
||||
if (InputDataLeft >= 0x200) {
|
||||
//u8 k=InputDataLeft>=InputDataProgress;
|
||||
|
||||
AutoDMAReadBuffer(0);
|
||||
AutoDMAReadBuffer(0);
|
||||
|
||||
AdmaInProgress = 1;
|
||||
TSA = (Index<<10) + InputPosRead;
|
||||
AdmaInProgress = 1;
|
||||
TSA = (Index << 10) + InputPosRead;
|
||||
|
||||
if (InputDataLeft < 0x200)
|
||||
{
|
||||
AutoDMACtrl |= ~3;
|
||||
if (InputDataLeft < 0x200) {
|
||||
AutoDMACtrl |= ~3;
|
||||
|
||||
if( IsDevBuild )
|
||||
{
|
||||
FileLog("[%10d] AutoDMA%c block end.\n",Cycles, GetDmaIndexChar());
|
||||
if(InputDataLeft>0)
|
||||
{
|
||||
if(MsgAutoDMA()) ConLog("WARNING: adma buffer didn't finish with a whole block!!\n");
|
||||
}
|
||||
}
|
||||
if (IsDevBuild) {
|
||||
FileLog("[%10d] AutoDMA%c block end.\n", Cycles, GetDmaIndexChar());
|
||||
if (InputDataLeft > 0) {
|
||||
if (MsgAutoDMA())
|
||||
ConLog("WARNING: adma buffer didn't finish with a whole block!!\n");
|
||||
}
|
||||
}
|
||||
|
||||
InputDataLeft = 0;
|
||||
// Hack, kinda. We call the interrupt early here, since PCSX2 doesn't like them delayed.
|
||||
//DMAICounter = 1;
|
||||
if(Index == 0) { if(dma4callback) dma4callback(); }
|
||||
else { if(dma7callback) dma7callback(); }
|
||||
}
|
||||
}
|
||||
InputDataLeft = 0;
|
||||
// Hack, kinda. We call the interrupt early here, since PCSX2 doesn't like them delayed.
|
||||
//DMAICounter = 1;
|
||||
if (Index == 0) {
|
||||
if (dma4callback)
|
||||
dma4callback();
|
||||
} else {
|
||||
if (dma7callback)
|
||||
dma7callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
InputPosRead &= 0x1ff;
|
||||
return retval;
|
||||
}
|
||||
InputPosRead &= 0x1ff;
|
||||
return retval;
|
||||
}
|
||||
|
|
|
@ -17,238 +17,280 @@
|
|||
|
||||
#include "Global.h"
|
||||
|
||||
const char *ParamNames[8]={"VOLL","VOLR","PITCH","ADSR1","ADSR2","ENVX","VOLXL","VOLXR"};
|
||||
const char *AddressNames[6]={"SSAH","SSAL","LSAH","LSAL","NAXH","NAXL"};
|
||||
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_( const char* action, int level, const char *RName, u32 mem, u32 core, u16 value )
|
||||
__forceinline void _RegLog_(const char *action, int level, const char *RName, u32 mem, u32 core, u16 value)
|
||||
{
|
||||
if( level > 1 )
|
||||
FileLog("[%10d] SPU2 %s mem %08x (core %d, register %s) value %04x\n",
|
||||
Cycles, action, mem, core, RName, value);
|
||||
if (level > 1)
|
||||
FileLog("[%10d] SPU2 %s mem %08x (core %d, register %s) value %04x\n",
|
||||
Cycles, action, mem, core, RName, value);
|
||||
}
|
||||
|
||||
#define RegLog( lev, rname, mem, core, val ) _RegLog_( action, lev, rname, mem, core, val )
|
||||
#define RegLog(lev, rname, mem, core, val) _RegLog_(action, lev, rname, mem, core, val)
|
||||
|
||||
void SPU2writeLog( const char* action, u32 rmem, u16 value )
|
||||
void SPU2writeLog(const char *action, u32 rmem, u16 value)
|
||||
{
|
||||
if( !IsDevBuild ) return;
|
||||
if (!IsDevBuild)
|
||||
return;
|
||||
|
||||
//u32 vx=0, vc=0;
|
||||
u32 core=0, omem, mem;
|
||||
omem=mem=rmem & 0x7FF; //FFFF;
|
||||
if (mem & 0x400) { omem^=0x400; core=1; }
|
||||
//u32 vx=0, vc=0;
|
||||
u32 core = 0, omem, mem;
|
||||
omem = mem = rmem & 0x7FF; //FFFF;
|
||||
if (mem & 0x400) {
|
||||
omem ^= 0x400;
|
||||
core = 1;
|
||||
}
|
||||
|
||||
if( omem < 0x0180 ) // Voice Params (VP)
|
||||
{
|
||||
const u32 voice = (omem & 0x1F0) >> 4;
|
||||
const u32 param = (omem & 0xF) >> 1;
|
||||
char dest[192];
|
||||
sprintf( dest, "Voice %d %s", voice,ParamNames[param] );
|
||||
RegLog( 2, dest, rmem, core, value );
|
||||
}
|
||||
else if ((omem >= 0x01C0) && (omem < 0x02E0)) // Voice Addressing Params (VA)
|
||||
{
|
||||
const u32 voice = ((omem-0x01C0) / 12);
|
||||
const u32 address = ((omem-0x01C0) % 12)>>1;
|
||||
if (omem < 0x0180) // Voice Params (VP)
|
||||
{
|
||||
const u32 voice = (omem & 0x1F0) >> 4;
|
||||
const u32 param = (omem & 0xF) >> 1;
|
||||
char dest[192];
|
||||
sprintf(dest, "Voice %d %s", voice, ParamNames[param]);
|
||||
RegLog(2, dest, rmem, core, value);
|
||||
} else if ((omem >= 0x01C0) && (omem < 0x02E0)) // Voice Addressing Params (VA)
|
||||
{
|
||||
const u32 voice = ((omem - 0x01C0) / 12);
|
||||
const u32 address = ((omem - 0x01C0) % 12) >> 1;
|
||||
|
||||
char dest[192];
|
||||
sprintf( dest, "Voice %d %s", voice, AddressNames[address] );
|
||||
RegLog( 2, dest, rmem, core, value );
|
||||
}
|
||||
else if ((mem >= 0x0760) && (mem < 0x07b0))
|
||||
{
|
||||
omem=mem; core=0;
|
||||
if (mem >= 0x0788) {omem-=0x28; core=1;}
|
||||
switch(omem)
|
||||
{
|
||||
case REG_P_EVOLL: RegLog(2,"EVOLL",rmem,core,value); break;
|
||||
case REG_P_EVOLR: RegLog(2,"EVOLR",rmem,core,value); break;
|
||||
case REG_P_AVOLL: if (core) { RegLog(2,"AVOLL",rmem,core,value); } break;
|
||||
case REG_P_AVOLR: if (core) { RegLog(2,"AVOLR",rmem,core,value); } break;
|
||||
case REG_P_BVOLL: RegLog(2,"BVOLL",rmem,core,value); break;
|
||||
case REG_P_BVOLR: RegLog(2,"BVOLR",rmem,core,value); break;
|
||||
case REG_P_MVOLXL: RegLog(2,"MVOLXL",rmem,core,value); break;
|
||||
case REG_P_MVOLXR: RegLog(2,"MVOLXR",rmem,core,value); break;
|
||||
case R_IIR_ALPHA: RegLog(2,"IIR_ALPHA",rmem,core,value); break;
|
||||
case R_ACC_COEF_A: RegLog(2,"ACC_COEF_A",rmem,core,value); break;
|
||||
case R_ACC_COEF_B: RegLog(2,"ACC_COEF_B",rmem,core,value); break;
|
||||
case R_ACC_COEF_C: RegLog(2,"ACC_COEF_C",rmem,core,value); break;
|
||||
case R_ACC_COEF_D: RegLog(2,"ACC_COEF_D",rmem,core,value); break;
|
||||
case R_IIR_COEF: RegLog(2,"IIR_COEF",rmem,core,value); break;
|
||||
case R_FB_ALPHA: RegLog(2,"FB_ALPHA",rmem,core,value); break;
|
||||
case R_FB_X: RegLog(2,"FB_X",rmem,core,value); break;
|
||||
case R_IN_COEF_L: RegLog(2,"IN_COEF_L",rmem,core,value); break;
|
||||
case R_IN_COEF_R: RegLog(2,"IN_COEF_R",rmem,core,value); break;
|
||||
char dest[192];
|
||||
sprintf(dest, "Voice %d %s", voice, AddressNames[address]);
|
||||
RegLog(2, dest, rmem, core, value);
|
||||
} else if ((mem >= 0x0760) && (mem < 0x07b0)) {
|
||||
omem = mem;
|
||||
core = 0;
|
||||
if (mem >= 0x0788) {
|
||||
omem -= 0x28;
|
||||
core = 1;
|
||||
}
|
||||
switch (omem) {
|
||||
case REG_P_EVOLL:
|
||||
RegLog(2, "EVOLL", rmem, core, value);
|
||||
break;
|
||||
case REG_P_EVOLR:
|
||||
RegLog(2, "EVOLR", rmem, core, value);
|
||||
break;
|
||||
case REG_P_AVOLL:
|
||||
if (core) {
|
||||
RegLog(2, "AVOLL", rmem, core, value);
|
||||
}
|
||||
break;
|
||||
case REG_P_AVOLR:
|
||||
if (core) {
|
||||
RegLog(2, "AVOLR", rmem, core, value);
|
||||
}
|
||||
break;
|
||||
case REG_P_BVOLL:
|
||||
RegLog(2, "BVOLL", rmem, core, value);
|
||||
break;
|
||||
case REG_P_BVOLR:
|
||||
RegLog(2, "BVOLR", rmem, core, value);
|
||||
break;
|
||||
case REG_P_MVOLXL:
|
||||
RegLog(2, "MVOLXL", rmem, core, value);
|
||||
break;
|
||||
case REG_P_MVOLXR:
|
||||
RegLog(2, "MVOLXR", rmem, core, value);
|
||||
break;
|
||||
case R_IIR_ALPHA:
|
||||
RegLog(2, "IIR_ALPHA", rmem, core, value);
|
||||
break;
|
||||
case R_ACC_COEF_A:
|
||||
RegLog(2, "ACC_COEF_A", rmem, core, value);
|
||||
break;
|
||||
case R_ACC_COEF_B:
|
||||
RegLog(2, "ACC_COEF_B", rmem, core, value);
|
||||
break;
|
||||
case R_ACC_COEF_C:
|
||||
RegLog(2, "ACC_COEF_C", rmem, core, value);
|
||||
break;
|
||||
case R_ACC_COEF_D:
|
||||
RegLog(2, "ACC_COEF_D", rmem, core, value);
|
||||
break;
|
||||
case R_IIR_COEF:
|
||||
RegLog(2, "IIR_COEF", rmem, core, value);
|
||||
break;
|
||||
case R_FB_ALPHA:
|
||||
RegLog(2, "FB_ALPHA", rmem, core, value);
|
||||
break;
|
||||
case R_FB_X:
|
||||
RegLog(2, "FB_X", rmem, core, value);
|
||||
break;
|
||||
case R_IN_COEF_L:
|
||||
RegLog(2, "IN_COEF_L", rmem, core, value);
|
||||
break;
|
||||
case R_IN_COEF_R:
|
||||
RegLog(2, "IN_COEF_R", rmem, core, value);
|
||||
break;
|
||||
}
|
||||
} else if ((mem >= 0x07C0) && (mem < 0x07CE)) {
|
||||
switch (mem) {
|
||||
case SPDIF_OUT:
|
||||
RegLog(2, "SPDIF_OUT", rmem, -1, value);
|
||||
break;
|
||||
case SPDIF_IRQINFO:
|
||||
RegLog(2, "SPDIF_IRQINFO", rmem, -1, value);
|
||||
break;
|
||||
case 0x7c4:
|
||||
if (Spdif.Unknown1 != value)
|
||||
ConLog("* SPU2-X: SPDIF Unknown Register 1 set to %04x\n", value);
|
||||
RegLog(2, "SPDIF_UNKNOWN1", rmem, -1, value);
|
||||
break;
|
||||
case SPDIF_MODE:
|
||||
if (Spdif.Mode != value)
|
||||
ConLog("* SPU2-X: SPDIF Mode set to %04x\n", value);
|
||||
RegLog(2, "SPDIF_MODE", rmem, -1, value);
|
||||
break;
|
||||
case SPDIF_MEDIA:
|
||||
if (Spdif.Media != value)
|
||||
ConLog("* SPU2-X: SPDIF Media set to %04x\n", value);
|
||||
RegLog(2, "SPDIF_MEDIA", rmem, -1, value);
|
||||
break;
|
||||
case 0x7ca:
|
||||
if (Spdif.Unknown2 != value)
|
||||
ConLog("* SPU2-X: SPDIF Unknown Register 2 set to %04x\n", value);
|
||||
RegLog(2, "SPDIF_UNKNOWN2", rmem, -1, value);
|
||||
break;
|
||||
case SPDIF_PROTECT:
|
||||
if (Spdif.Protection != value)
|
||||
ConLog("* SPU2-X: SPDIF Copy set to %04x\n", value);
|
||||
RegLog(2, "SPDIF_PROTECT", rmem, -1, value);
|
||||
break;
|
||||
}
|
||||
UpdateSpdifMode();
|
||||
} else {
|
||||
switch (omem) {
|
||||
case REG_C_ATTR:
|
||||
RegLog(4, "ATTR", rmem, core, value);
|
||||
break;
|
||||
case REG_S_PMON:
|
||||
RegLog(1, "PMON0", rmem, core, value);
|
||||
break;
|
||||
case (REG_S_PMON + 2):
|
||||
RegLog(1, "PMON1", rmem, core, value);
|
||||
break;
|
||||
case REG_S_NON:
|
||||
RegLog(1, "NON0", rmem, core, value);
|
||||
break;
|
||||
case (REG_S_NON + 2):
|
||||
RegLog(1, "NON1", rmem, core, value);
|
||||
break;
|
||||
case REG_S_VMIXL:
|
||||
RegLog(1, "VMIXL0", rmem, core, value);
|
||||
case (REG_S_VMIXL + 2):
|
||||
RegLog(1, "VMIXL1", rmem, core, value);
|
||||
break;
|
||||
case REG_S_VMIXEL:
|
||||
RegLog(1, "VMIXEL0", rmem, core, value);
|
||||
break;
|
||||
case (REG_S_VMIXEL + 2):
|
||||
RegLog(1, "VMIXEL1", rmem, core, value);
|
||||
break;
|
||||
case REG_S_VMIXR:
|
||||
RegLog(1, "VMIXR0", rmem, core, value);
|
||||
break;
|
||||
case (REG_S_VMIXR + 2):
|
||||
RegLog(1, "VMIXR1", rmem, core, value);
|
||||
break;
|
||||
case REG_S_VMIXER:
|
||||
RegLog(1, "VMIXER0", rmem, core, value);
|
||||
break;
|
||||
case (REG_S_VMIXER + 2):
|
||||
RegLog(1, "VMIXER1", rmem, core, value);
|
||||
break;
|
||||
case REG_P_MMIX:
|
||||
RegLog(1, "MMIX", rmem, core, value);
|
||||
break;
|
||||
case REG_A_IRQA:
|
||||
RegLog(2, "IRQAH", rmem, core, value);
|
||||
break;
|
||||
case (REG_A_IRQA + 2):
|
||||
RegLog(2, "IRQAL", rmem, core, value);
|
||||
break;
|
||||
case (REG_S_KON + 2):
|
||||
RegLog(1, "KON1", rmem, core, value);
|
||||
break;
|
||||
case REG_S_KON:
|
||||
RegLog(1, "KON0", rmem, core, value);
|
||||
break;
|
||||
case (REG_S_KOFF + 2):
|
||||
RegLog(1, "KOFF1", rmem, core, value);
|
||||
break;
|
||||
case REG_S_KOFF:
|
||||
RegLog(1, "KOFF0", rmem, core, value);
|
||||
break;
|
||||
case REG_A_TSA:
|
||||
RegLog(2, "TSAH", rmem, core, value);
|
||||
break;
|
||||
case (REG_A_TSA + 2):
|
||||
RegLog(2, "TSAL", rmem, core, value);
|
||||
break;
|
||||
case REG_S_ENDX:
|
||||
//ConLog("* SPU2-X: Core %d ENDX cleared!\n",core);
|
||||
RegLog(2, "ENDX0", rmem, core, value);
|
||||
break;
|
||||
case (REG_S_ENDX + 2):
|
||||
//ConLog("* SPU2-X: Core %d ENDX cleared!\n",core);
|
||||
RegLog(2, "ENDX1", rmem, core, value);
|
||||
break;
|
||||
case REG_P_MVOLL:
|
||||
RegLog(1, "MVOLL", rmem, core, value);
|
||||
break;
|
||||
case REG_P_MVOLR:
|
||||
RegLog(1, "MVOLR", rmem, core, value);
|
||||
break;
|
||||
case REG_S_ADMAS:
|
||||
RegLog(3, "ADMAS", rmem, core, value);
|
||||
//ConLog("* SPU2-X: Core %d AutoDMAControl set to %d\n",core,value);
|
||||
break;
|
||||
case REG_P_STATX:
|
||||
RegLog(3, "STATX", rmem, core, value);
|
||||
break;
|
||||
case REG_A_ESA:
|
||||
RegLog(2, "ESAH", rmem, core, value);
|
||||
break;
|
||||
case (REG_A_ESA + 2):
|
||||
RegLog(2, "ESAL", rmem, core, value);
|
||||
break;
|
||||
case REG_A_EEA:
|
||||
RegLog(2, "EEAH", rmem, core, value);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
else if ((mem>=0x07C0) && (mem<0x07CE))
|
||||
{
|
||||
switch(mem)
|
||||
{
|
||||
case SPDIF_OUT:
|
||||
RegLog(2,"SPDIF_OUT",rmem,-1,value);
|
||||
break;
|
||||
case SPDIF_IRQINFO:
|
||||
RegLog(2,"SPDIF_IRQINFO",rmem,-1,value);
|
||||
break;
|
||||
case 0x7c4:
|
||||
if(Spdif.Unknown1 != value) ConLog("* SPU2-X: SPDIF Unknown Register 1 set to %04x\n",value);
|
||||
RegLog(2,"SPDIF_UNKNOWN1",rmem,-1,value);
|
||||
break;
|
||||
case SPDIF_MODE:
|
||||
if(Spdif.Mode != value) ConLog("* SPU2-X: SPDIF Mode set to %04x\n",value);
|
||||
RegLog(2,"SPDIF_MODE",rmem,-1,value);
|
||||
break;
|
||||
case SPDIF_MEDIA:
|
||||
if(Spdif.Media != value) ConLog("* SPU2-X: SPDIF Media set to %04x\n",value);
|
||||
RegLog(2,"SPDIF_MEDIA",rmem,-1,value);
|
||||
break;
|
||||
case 0x7ca:
|
||||
if(Spdif.Unknown2 != value) ConLog("* SPU2-X: SPDIF Unknown Register 2 set to %04x\n",value);
|
||||
RegLog(2,"SPDIF_UNKNOWN2",rmem,-1,value);
|
||||
break;
|
||||
case SPDIF_PROTECT:
|
||||
if(Spdif.Protection != value) ConLog("* SPU2-X: SPDIF Copy set to %04x\n",value);
|
||||
RegLog(2,"SPDIF_PROTECT",rmem,-1,value);
|
||||
break;
|
||||
}
|
||||
UpdateSpdifMode();
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(omem)
|
||||
{
|
||||
case REG_C_ATTR:
|
||||
RegLog(4,"ATTR",rmem,core,value);
|
||||
break;
|
||||
case REG_S_PMON:
|
||||
RegLog(1,"PMON0",rmem,core,value);
|
||||
break;
|
||||
case (REG_S_PMON + 2):
|
||||
RegLog(1,"PMON1",rmem,core,value);
|
||||
break;
|
||||
case REG_S_NON:
|
||||
RegLog(1,"NON0",rmem,core,value);
|
||||
break;
|
||||
case (REG_S_NON + 2):
|
||||
RegLog(1,"NON1",rmem,core,value);
|
||||
break;
|
||||
case REG_S_VMIXL:
|
||||
RegLog(1,"VMIXL0",rmem,core,value);
|
||||
case (REG_S_VMIXL + 2):
|
||||
RegLog(1,"VMIXL1",rmem,core,value);
|
||||
break;
|
||||
case REG_S_VMIXEL:
|
||||
RegLog(1,"VMIXEL0",rmem,core,value);
|
||||
break;
|
||||
case (REG_S_VMIXEL + 2):
|
||||
RegLog(1,"VMIXEL1",rmem,core,value);
|
||||
break;
|
||||
case REG_S_VMIXR:
|
||||
RegLog(1,"VMIXR0",rmem,core,value);
|
||||
break;
|
||||
case (REG_S_VMIXR + 2):
|
||||
RegLog(1,"VMIXR1",rmem,core,value);
|
||||
break;
|
||||
case REG_S_VMIXER:
|
||||
RegLog(1,"VMIXER0",rmem,core,value);
|
||||
break;
|
||||
case (REG_S_VMIXER + 2):
|
||||
RegLog(1,"VMIXER1",rmem,core,value);
|
||||
break;
|
||||
case REG_P_MMIX:
|
||||
RegLog(1,"MMIX",rmem,core,value);
|
||||
break;
|
||||
case REG_A_IRQA:
|
||||
RegLog(2,"IRQAH",rmem,core,value);
|
||||
break;
|
||||
case (REG_A_IRQA + 2):
|
||||
RegLog(2,"IRQAL",rmem,core,value);
|
||||
break;
|
||||
case (REG_S_KON + 2):
|
||||
RegLog(1,"KON1",rmem,core,value);
|
||||
break;
|
||||
case REG_S_KON:
|
||||
RegLog(1,"KON0",rmem,core,value);
|
||||
break;
|
||||
case (REG_S_KOFF + 2):
|
||||
RegLog(1,"KOFF1",rmem,core,value);
|
||||
break;
|
||||
case REG_S_KOFF:
|
||||
RegLog(1,"KOFF0",rmem,core,value);
|
||||
break;
|
||||
case REG_A_TSA:
|
||||
RegLog(2,"TSAH",rmem,core,value);
|
||||
break;
|
||||
case (REG_A_TSA + 2):
|
||||
RegLog(2,"TSAL",rmem,core,value);
|
||||
break;
|
||||
case REG_S_ENDX:
|
||||
//ConLog("* SPU2-X: Core %d ENDX cleared!\n",core);
|
||||
RegLog(2,"ENDX0",rmem,core,value);
|
||||
break;
|
||||
case (REG_S_ENDX + 2):
|
||||
//ConLog("* SPU2-X: Core %d ENDX cleared!\n",core);
|
||||
RegLog(2,"ENDX1",rmem,core,value);
|
||||
break;
|
||||
case REG_P_MVOLL:
|
||||
RegLog(1,"MVOLL",rmem,core,value);
|
||||
break;
|
||||
case REG_P_MVOLR:
|
||||
RegLog(1,"MVOLR",rmem,core,value);
|
||||
break;
|
||||
case REG_S_ADMAS:
|
||||
RegLog(3,"ADMAS",rmem,core,value);
|
||||
//ConLog("* SPU2-X: Core %d AutoDMAControl set to %d\n",core,value);
|
||||
break;
|
||||
case REG_P_STATX:
|
||||
RegLog(3,"STATX",rmem,core,value);
|
||||
break;
|
||||
case REG_A_ESA:
|
||||
RegLog(2,"ESAH",rmem,core,value);
|
||||
break;
|
||||
case (REG_A_ESA + 2):
|
||||
RegLog(2,"ESAL",rmem,core,value);
|
||||
break;
|
||||
case REG_A_EEA:
|
||||
RegLog(2,"EEAH",rmem,core,value);
|
||||
break;
|
||||
#define LOG_REVB_REG(n, t) \
|
||||
case R_##n: \
|
||||
RegLog(2, t "H", mem, core, value); \
|
||||
break; \
|
||||
case (R_##n + 2): \
|
||||
RegLog(2, t "L", mem, core, value); \
|
||||
break;
|
||||
|
||||
#define LOG_REVB_REG(n,t) \
|
||||
case R_##n: \
|
||||
RegLog(2,t "H",mem,core,value); \
|
||||
break; \
|
||||
case (R_##n + 2): \
|
||||
RegLog(2,t "L",mem,core,value); \
|
||||
break;
|
||||
LOG_REVB_REG(FB_SRC_A, "FB_SRC_A")
|
||||
LOG_REVB_REG(FB_SRC_B, "FB_SRC_B")
|
||||
LOG_REVB_REG(IIR_SRC_A0, "IIR_SRC_A0")
|
||||
LOG_REVB_REG(IIR_SRC_A1, "IIR_SRC_A1")
|
||||
LOG_REVB_REG(IIR_SRC_B1, "IIR_SRC_B1")
|
||||
LOG_REVB_REG(IIR_SRC_B0, "IIR_SRC_B0")
|
||||
LOG_REVB_REG(IIR_DEST_A0, "IIR_DEST_A0")
|
||||
LOG_REVB_REG(IIR_DEST_A1, "IIR_DEST_A1")
|
||||
LOG_REVB_REG(IIR_DEST_B0, "IIR_DEST_B0")
|
||||
LOG_REVB_REG(IIR_DEST_B1, "IIR_DEST_B1")
|
||||
LOG_REVB_REG(ACC_SRC_A0, "ACC_SRC_A0")
|
||||
LOG_REVB_REG(ACC_SRC_A1, "ACC_SRC_A1")
|
||||
LOG_REVB_REG(ACC_SRC_B0, "ACC_SRC_B0")
|
||||
LOG_REVB_REG(ACC_SRC_B1, "ACC_SRC_B1")
|
||||
LOG_REVB_REG(ACC_SRC_C0, "ACC_SRC_C0")
|
||||
LOG_REVB_REG(ACC_SRC_C1, "ACC_SRC_C1")
|
||||
LOG_REVB_REG(ACC_SRC_D0, "ACC_SRC_D0")
|
||||
LOG_REVB_REG(ACC_SRC_D1, "ACC_SRC_D1")
|
||||
LOG_REVB_REG(MIX_DEST_A0, "MIX_DEST_A0")
|
||||
LOG_REVB_REG(MIX_DEST_A1, "MIX_DEST_A1")
|
||||
LOG_REVB_REG(MIX_DEST_B0, "MIX_DEST_B0")
|
||||
LOG_REVB_REG(MIX_DEST_B1, "MIX_DEST_B1")
|
||||
|
||||
LOG_REVB_REG(FB_SRC_A,"FB_SRC_A")
|
||||
LOG_REVB_REG(FB_SRC_B,"FB_SRC_B")
|
||||
LOG_REVB_REG(IIR_SRC_A0,"IIR_SRC_A0")
|
||||
LOG_REVB_REG(IIR_SRC_A1,"IIR_SRC_A1")
|
||||
LOG_REVB_REG(IIR_SRC_B1,"IIR_SRC_B1")
|
||||
LOG_REVB_REG(IIR_SRC_B0,"IIR_SRC_B0")
|
||||
LOG_REVB_REG(IIR_DEST_A0,"IIR_DEST_A0")
|
||||
LOG_REVB_REG(IIR_DEST_A1,"IIR_DEST_A1")
|
||||
LOG_REVB_REG(IIR_DEST_B0,"IIR_DEST_B0")
|
||||
LOG_REVB_REG(IIR_DEST_B1,"IIR_DEST_B1")
|
||||
LOG_REVB_REG(ACC_SRC_A0,"ACC_SRC_A0")
|
||||
LOG_REVB_REG(ACC_SRC_A1,"ACC_SRC_A1")
|
||||
LOG_REVB_REG(ACC_SRC_B0,"ACC_SRC_B0")
|
||||
LOG_REVB_REG(ACC_SRC_B1,"ACC_SRC_B1")
|
||||
LOG_REVB_REG(ACC_SRC_C0,"ACC_SRC_C0")
|
||||
LOG_REVB_REG(ACC_SRC_C1,"ACC_SRC_C1")
|
||||
LOG_REVB_REG(ACC_SRC_D0,"ACC_SRC_D0")
|
||||
LOG_REVB_REG(ACC_SRC_D1,"ACC_SRC_D1")
|
||||
LOG_REVB_REG(MIX_DEST_A0,"MIX_DEST_A0")
|
||||
LOG_REVB_REG(MIX_DEST_A1,"MIX_DEST_A1")
|
||||
LOG_REVB_REG(MIX_DEST_B0,"MIX_DEST_B0")
|
||||
LOG_REVB_REG(MIX_DEST_B1,"MIX_DEST_B1")
|
||||
|
||||
default:
|
||||
RegLog(2,"UNKNOWN",rmem,core,value); spu2Ru16(mem) = value;
|
||||
}
|
||||
}
|
||||
default:
|
||||
RegLog(2, "UNKNOWN", rmem, core, value);
|
||||
spu2Ru16(mem) = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,287 +17,287 @@
|
|||
|
||||
#include "Global.h"
|
||||
|
||||
#define PCORE(c,p) \
|
||||
U16P(Cores[c].p)
|
||||
#define PCORE(c, p) \
|
||||
U16P(Cores[c].p)
|
||||
|
||||
#define PVCP(c,v,p) \
|
||||
PCORE(c,Voices[v].p)
|
||||
#define PVCP(c, v, p) \
|
||||
PCORE(c, Voices[v].p)
|
||||
|
||||
#define PVC(c,v) \
|
||||
PVCP(c,v,Volume.Left.Reg_VOL), \
|
||||
PVCP(c,v,Volume.Right.Reg_VOL), \
|
||||
PVCP(c,v,Pitch), \
|
||||
PVCP(c,v,ADSR.regADSR1), \
|
||||
PVCP(c,v,ADSR.regADSR2), \
|
||||
PVCP(c,v,ADSR.Value)+1, \
|
||||
PVCP(c,v,Volume.Left.Value)+1, \
|
||||
PVCP(c,v,Volume.Right.Value)+1
|
||||
#define PVC(c, v) \
|
||||
PVCP(c, v, Volume.Left.Reg_VOL) \
|
||||
, \
|
||||
PVCP(c, v, Volume.Right.Reg_VOL), \
|
||||
PVCP(c, v, Pitch), \
|
||||
PVCP(c, v, ADSR.regADSR1), \
|
||||
PVCP(c, v, ADSR.regADSR2), \
|
||||
PVCP(c, v, ADSR.Value) + 1, \
|
||||
PVCP(c, v, Volume.Left.Value) + 1, \
|
||||
PVCP(c, v, Volume.Right.Value) + 1
|
||||
|
||||
#define PVCA(c,v) \
|
||||
PVCP(c,v,StartA)+1, \
|
||||
PVCP(c,v,StartA), \
|
||||
PVCP(c,v,LoopStartA)+1, \
|
||||
PVCP(c,v,LoopStartA), \
|
||||
PVCP(c,v,NextA)+1, \
|
||||
PVCP(c,v,NextA)
|
||||
#define PVCA(c, v) \
|
||||
PVCP(c, v, StartA) + 1, \
|
||||
PVCP(c, v, StartA), \
|
||||
PVCP(c, v, LoopStartA) + 1, \
|
||||
PVCP(c, v, LoopStartA), \
|
||||
PVCP(c, v, NextA) + 1, \
|
||||
PVCP(c, v, NextA)
|
||||
|
||||
#define PRAW(a) \
|
||||
((u16*)NULL)
|
||||
((u16 *)NULL)
|
||||
|
||||
#define PREVB_REG(c,n) \
|
||||
PCORE(c,Revb.n)+1, \
|
||||
PCORE(c,Revb.n)
|
||||
#define PREVB_REG(c, n) \
|
||||
PCORE(c, Revb.n) + 1, \
|
||||
PCORE(c, Revb.n)
|
||||
|
||||
u16* regtable[0x401];
|
||||
u16 *regtable[0x401];
|
||||
|
||||
u16 const* const regtable_original[0x401] =
|
||||
{
|
||||
// Voice Params: 8 params, 24 voices = 0x180 bytes
|
||||
PVC(0, 0),PVC(0, 1),PVC(0, 2),PVC(0, 3),PVC(0, 4),PVC(0, 5),
|
||||
PVC(0, 6),PVC(0, 7),PVC(0, 8),PVC(0, 9),PVC(0,10),PVC(0,11),
|
||||
PVC(0,12),PVC(0,13),PVC(0,14),PVC(0,15),PVC(0,16),PVC(0,17),
|
||||
PVC(0,18),PVC(0,19),PVC(0,20),PVC(0,21),PVC(0,22),PVC(0,23),
|
||||
u16 const *const regtable_original[0x401] =
|
||||
{
|
||||
// Voice Params: 8 params, 24 voices = 0x180 bytes
|
||||
PVC(0, 0), PVC(0, 1), PVC(0, 2), PVC(0, 3), PVC(0, 4), PVC(0, 5),
|
||||
PVC(0, 6), PVC(0, 7), PVC(0, 8), PVC(0, 9), PVC(0, 10), PVC(0, 11),
|
||||
PVC(0, 12), PVC(0, 13), PVC(0, 14), PVC(0, 15), PVC(0, 16), PVC(0, 17),
|
||||
PVC(0, 18), PVC(0, 19), PVC(0, 20), PVC(0, 21), PVC(0, 22), PVC(0, 23),
|
||||
|
||||
PCORE(0,Regs.PMON),
|
||||
PCORE(0,Regs.PMON)+1,
|
||||
PCORE(0,Regs.NON),
|
||||
PCORE(0,Regs.NON)+1,
|
||||
PCORE(0,Regs.VMIXL),
|
||||
PCORE(0,Regs.VMIXL)+1,
|
||||
PCORE(0,Regs.VMIXEL),
|
||||
PCORE(0,Regs.VMIXEL)+1,
|
||||
PCORE(0,Regs.VMIXR),
|
||||
PCORE(0,Regs.VMIXR)+1,
|
||||
PCORE(0,Regs.VMIXER),
|
||||
PCORE(0,Regs.VMIXER)+1,
|
||||
PCORE(0, Regs.PMON),
|
||||
PCORE(0, Regs.PMON) + 1,
|
||||
PCORE(0, Regs.NON),
|
||||
PCORE(0, Regs.NON) + 1,
|
||||
PCORE(0, Regs.VMIXL),
|
||||
PCORE(0, Regs.VMIXL) + 1,
|
||||
PCORE(0, Regs.VMIXEL),
|
||||
PCORE(0, Regs.VMIXEL) + 1,
|
||||
PCORE(0, Regs.VMIXR),
|
||||
PCORE(0, Regs.VMIXR) + 1,
|
||||
PCORE(0, Regs.VMIXER),
|
||||
PCORE(0, Regs.VMIXER) + 1,
|
||||
|
||||
PCORE(0,Regs.MMIX),
|
||||
PCORE(0,Regs.ATTR),
|
||||
PCORE(0, Regs.MMIX),
|
||||
PCORE(0, Regs.ATTR),
|
||||
|
||||
PCORE(0,IRQA)+1,
|
||||
PCORE(0,IRQA),
|
||||
PCORE(0, IRQA) + 1,
|
||||
PCORE(0, IRQA),
|
||||
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
|
||||
PCORE(0,TSA)+1,
|
||||
PCORE(0,TSA),
|
||||
PCORE(0, TSA) + 1,
|
||||
PCORE(0, TSA),
|
||||
|
||||
PRAW(REG__1AC), PRAW(REG__1AE),
|
||||
PRAW(REG__1AC), PRAW(REG__1AE),
|
||||
|
||||
PCORE(0,AutoDMACtrl),
|
||||
PCORE(0, AutoDMACtrl),
|
||||
|
||||
PRAW(0x1b2), PRAW(0x1b4), PRAW(0x1b6), PRAW(0x1b8), PRAW(0x1ba), PRAW(0x1bc), PRAW(0x1be), // unknown
|
||||
PRAW(0x1b2), PRAW(0x1b4), PRAW(0x1b6), PRAW(0x1b8), PRAW(0x1ba), PRAW(0x1bc), PRAW(0x1be), // unknown
|
||||
|
||||
// Voice Addresses
|
||||
PVCA(0, 0),PVCA(0, 1),PVCA(0, 2),PVCA(0, 3),PVCA(0, 4),PVCA(0, 5),
|
||||
PVCA(0, 6),PVCA(0, 7),PVCA(0, 8),PVCA(0, 9),PVCA(0,10),PVCA(0,11),
|
||||
PVCA(0,12),PVCA(0,13),PVCA(0,14),PVCA(0,15),PVCA(0,16),PVCA(0,17),
|
||||
PVCA(0,18),PVCA(0,19),PVCA(0,20),PVCA(0,21),PVCA(0,22),PVCA(0,23),
|
||||
// Voice Addresses
|
||||
PVCA(0, 0), PVCA(0, 1), PVCA(0, 2), PVCA(0, 3), PVCA(0, 4), PVCA(0, 5),
|
||||
PVCA(0, 6), PVCA(0, 7), PVCA(0, 8), PVCA(0, 9), PVCA(0, 10), PVCA(0, 11),
|
||||
PVCA(0, 12), PVCA(0, 13), PVCA(0, 14), PVCA(0, 15), PVCA(0, 16), PVCA(0, 17),
|
||||
PVCA(0, 18), PVCA(0, 19), PVCA(0, 20), PVCA(0, 21), PVCA(0, 22), PVCA(0, 23),
|
||||
|
||||
PCORE(0,ExtEffectsStartA)+1,
|
||||
PCORE(0,ExtEffectsStartA),
|
||||
PCORE(0, ExtEffectsStartA) + 1,
|
||||
PCORE(0, ExtEffectsStartA),
|
||||
|
||||
PREVB_REG(0,FB_SRC_A),
|
||||
PREVB_REG(0,FB_SRC_B),
|
||||
PREVB_REG(0,IIR_DEST_A0),
|
||||
PREVB_REG(0,IIR_DEST_A1),
|
||||
PREVB_REG(0,ACC_SRC_A0),
|
||||
PREVB_REG(0,ACC_SRC_A1),
|
||||
PREVB_REG(0,ACC_SRC_B0),
|
||||
PREVB_REG(0,ACC_SRC_B1),
|
||||
PREVB_REG(0,IIR_SRC_A0),
|
||||
PREVB_REG(0,IIR_SRC_A1),
|
||||
PREVB_REG(0,IIR_DEST_B0),
|
||||
PREVB_REG(0,IIR_DEST_B1),
|
||||
PREVB_REG(0,ACC_SRC_C0),
|
||||
PREVB_REG(0,ACC_SRC_C1),
|
||||
PREVB_REG(0,ACC_SRC_D0),
|
||||
PREVB_REG(0,ACC_SRC_D1),
|
||||
PREVB_REG(0,IIR_SRC_B0),
|
||||
PREVB_REG(0,IIR_SRC_B1),
|
||||
PREVB_REG(0,MIX_DEST_A0),
|
||||
PREVB_REG(0,MIX_DEST_A1),
|
||||
PREVB_REG(0,MIX_DEST_B0),
|
||||
PREVB_REG(0,MIX_DEST_B1),
|
||||
PREVB_REG(0, FB_SRC_A),
|
||||
PREVB_REG(0, FB_SRC_B),
|
||||
PREVB_REG(0, IIR_DEST_A0),
|
||||
PREVB_REG(0, IIR_DEST_A1),
|
||||
PREVB_REG(0, ACC_SRC_A0),
|
||||
PREVB_REG(0, ACC_SRC_A1),
|
||||
PREVB_REG(0, ACC_SRC_B0),
|
||||
PREVB_REG(0, ACC_SRC_B1),
|
||||
PREVB_REG(0, IIR_SRC_A0),
|
||||
PREVB_REG(0, IIR_SRC_A1),
|
||||
PREVB_REG(0, IIR_DEST_B0),
|
||||
PREVB_REG(0, IIR_DEST_B1),
|
||||
PREVB_REG(0, ACC_SRC_C0),
|
||||
PREVB_REG(0, ACC_SRC_C1),
|
||||
PREVB_REG(0, ACC_SRC_D0),
|
||||
PREVB_REG(0, ACC_SRC_D1),
|
||||
PREVB_REG(0, IIR_SRC_B0),
|
||||
PREVB_REG(0, IIR_SRC_B1),
|
||||
PREVB_REG(0, MIX_DEST_A0),
|
||||
PREVB_REG(0, MIX_DEST_A1),
|
||||
PREVB_REG(0, MIX_DEST_B0),
|
||||
PREVB_REG(0, MIX_DEST_B1),
|
||||
|
||||
PCORE(0,ExtEffectsEndA)+1,
|
||||
PCORE(0,ExtEffectsEndA),
|
||||
PCORE(0, ExtEffectsEndA) + 1,
|
||||
PCORE(0, ExtEffectsEndA),
|
||||
|
||||
PCORE(0,Regs.ENDX),
|
||||
PCORE(0,Regs.ENDX)+1,
|
||||
PCORE(0,Regs.STATX),
|
||||
PCORE(0, Regs.ENDX),
|
||||
PCORE(0, Regs.ENDX) + 1,
|
||||
PCORE(0, Regs.STATX),
|
||||
|
||||
//0x346 here
|
||||
PRAW(0x346),
|
||||
PRAW(0x348),PRAW(0x34A),PRAW(0x34C),PRAW(0x34E),
|
||||
PRAW(0x350),PRAW(0x352),PRAW(0x354),PRAW(0x356),
|
||||
PRAW(0x358),PRAW(0x35A),PRAW(0x35C),PRAW(0x35E),
|
||||
PRAW(0x360),PRAW(0x362),PRAW(0x364),PRAW(0x366),
|
||||
PRAW(0x368),PRAW(0x36A),PRAW(0x36C),PRAW(0x36E),
|
||||
PRAW(0x370),PRAW(0x372),PRAW(0x374),PRAW(0x376),
|
||||
PRAW(0x378),PRAW(0x37A),PRAW(0x37C),PRAW(0x37E),
|
||||
PRAW(0x380),PRAW(0x382),PRAW(0x384),PRAW(0x386),
|
||||
PRAW(0x388),PRAW(0x38A),PRAW(0x38C),PRAW(0x38E),
|
||||
PRAW(0x390),PRAW(0x392),PRAW(0x394),PRAW(0x396),
|
||||
PRAW(0x398),PRAW(0x39A),PRAW(0x39C),PRAW(0x39E),
|
||||
PRAW(0x3A0),PRAW(0x3A2),PRAW(0x3A4),PRAW(0x3A6),
|
||||
PRAW(0x3A8),PRAW(0x3AA),PRAW(0x3AC),PRAW(0x3AE),
|
||||
PRAW(0x3B0),PRAW(0x3B2),PRAW(0x3B4),PRAW(0x3B6),
|
||||
PRAW(0x3B8),PRAW(0x3BA),PRAW(0x3BC),PRAW(0x3BE),
|
||||
PRAW(0x3C0),PRAW(0x3C2),PRAW(0x3C4),PRAW(0x3C6),
|
||||
PRAW(0x3C8),PRAW(0x3CA),PRAW(0x3CC),PRAW(0x3CE),
|
||||
PRAW(0x3D0),PRAW(0x3D2),PRAW(0x3D4),PRAW(0x3D6),
|
||||
PRAW(0x3D8),PRAW(0x3DA),PRAW(0x3DC),PRAW(0x3DE),
|
||||
PRAW(0x3E0),PRAW(0x3E2),PRAW(0x3E4),PRAW(0x3E6),
|
||||
PRAW(0x3E8),PRAW(0x3EA),PRAW(0x3EC),PRAW(0x3EE),
|
||||
PRAW(0x3F0),PRAW(0x3F2),PRAW(0x3F4),PRAW(0x3F6),
|
||||
PRAW(0x3F8),PRAW(0x3FA),PRAW(0x3FC),PRAW(0x3FE),
|
||||
//0x346 here
|
||||
PRAW(0x346),
|
||||
PRAW(0x348), PRAW(0x34A), PRAW(0x34C), PRAW(0x34E),
|
||||
PRAW(0x350), PRAW(0x352), PRAW(0x354), PRAW(0x356),
|
||||
PRAW(0x358), PRAW(0x35A), PRAW(0x35C), PRAW(0x35E),
|
||||
PRAW(0x360), PRAW(0x362), PRAW(0x364), PRAW(0x366),
|
||||
PRAW(0x368), PRAW(0x36A), PRAW(0x36C), PRAW(0x36E),
|
||||
PRAW(0x370), PRAW(0x372), PRAW(0x374), PRAW(0x376),
|
||||
PRAW(0x378), PRAW(0x37A), PRAW(0x37C), PRAW(0x37E),
|
||||
PRAW(0x380), PRAW(0x382), PRAW(0x384), PRAW(0x386),
|
||||
PRAW(0x388), PRAW(0x38A), PRAW(0x38C), PRAW(0x38E),
|
||||
PRAW(0x390), PRAW(0x392), PRAW(0x394), PRAW(0x396),
|
||||
PRAW(0x398), PRAW(0x39A), PRAW(0x39C), PRAW(0x39E),
|
||||
PRAW(0x3A0), PRAW(0x3A2), PRAW(0x3A4), PRAW(0x3A6),
|
||||
PRAW(0x3A8), PRAW(0x3AA), PRAW(0x3AC), PRAW(0x3AE),
|
||||
PRAW(0x3B0), PRAW(0x3B2), PRAW(0x3B4), PRAW(0x3B6),
|
||||
PRAW(0x3B8), PRAW(0x3BA), PRAW(0x3BC), PRAW(0x3BE),
|
||||
PRAW(0x3C0), PRAW(0x3C2), PRAW(0x3C4), PRAW(0x3C6),
|
||||
PRAW(0x3C8), PRAW(0x3CA), PRAW(0x3CC), PRAW(0x3CE),
|
||||
PRAW(0x3D0), PRAW(0x3D2), PRAW(0x3D4), PRAW(0x3D6),
|
||||
PRAW(0x3D8), PRAW(0x3DA), PRAW(0x3DC), PRAW(0x3DE),
|
||||
PRAW(0x3E0), PRAW(0x3E2), PRAW(0x3E4), PRAW(0x3E6),
|
||||
PRAW(0x3E8), PRAW(0x3EA), PRAW(0x3EC), PRAW(0x3EE),
|
||||
PRAW(0x3F0), PRAW(0x3F2), PRAW(0x3F4), PRAW(0x3F6),
|
||||
PRAW(0x3F8), PRAW(0x3FA), PRAW(0x3FC), PRAW(0x3FE),
|
||||
|
||||
//AND... we reached 0x400!
|
||||
// Voice Params: 8 params, 24 voices = 0x180 bytes
|
||||
PVC(1, 0),PVC(1, 1),PVC(1, 2),PVC(1, 3),PVC(1, 4),PVC(1, 5),
|
||||
PVC(1, 6),PVC(1, 7),PVC(1, 8),PVC(1, 9),PVC(1,10),PVC(1,11),
|
||||
PVC(1,12),PVC(1,13),PVC(1,14),PVC(1,15),PVC(1,16),PVC(1,17),
|
||||
PVC(1,18),PVC(1,19),PVC(1,20),PVC(1,21),PVC(1,22),PVC(1,23),
|
||||
//AND... we reached 0x400!
|
||||
// Voice Params: 8 params, 24 voices = 0x180 bytes
|
||||
PVC(1, 0), PVC(1, 1), PVC(1, 2), PVC(1, 3), PVC(1, 4), PVC(1, 5),
|
||||
PVC(1, 6), PVC(1, 7), PVC(1, 8), PVC(1, 9), PVC(1, 10), PVC(1, 11),
|
||||
PVC(1, 12), PVC(1, 13), PVC(1, 14), PVC(1, 15), PVC(1, 16), PVC(1, 17),
|
||||
PVC(1, 18), PVC(1, 19), PVC(1, 20), PVC(1, 21), PVC(1, 22), PVC(1, 23),
|
||||
|
||||
PCORE(1,Regs.PMON),
|
||||
PCORE(1,Regs.PMON)+1,
|
||||
PCORE(1,Regs.NON),
|
||||
PCORE(1,Regs.NON)+1,
|
||||
PCORE(1,Regs.VMIXL),
|
||||
PCORE(1,Regs.VMIXL)+1,
|
||||
PCORE(1,Regs.VMIXEL),
|
||||
PCORE(1,Regs.VMIXEL)+1,
|
||||
PCORE(1,Regs.VMIXR),
|
||||
PCORE(1,Regs.VMIXR)+1,
|
||||
PCORE(1,Regs.VMIXER),
|
||||
PCORE(1,Regs.VMIXER)+1,
|
||||
PCORE(1,Regs.MMIX),
|
||||
PCORE(1, Regs.PMON),
|
||||
PCORE(1, Regs.PMON) + 1,
|
||||
PCORE(1, Regs.NON),
|
||||
PCORE(1, Regs.NON) + 1,
|
||||
PCORE(1, Regs.VMIXL),
|
||||
PCORE(1, Regs.VMIXL) + 1,
|
||||
PCORE(1, Regs.VMIXEL),
|
||||
PCORE(1, Regs.VMIXEL) + 1,
|
||||
PCORE(1, Regs.VMIXR),
|
||||
PCORE(1, Regs.VMIXR) + 1,
|
||||
PCORE(1, Regs.VMIXER),
|
||||
PCORE(1, Regs.VMIXER) + 1,
|
||||
PCORE(1, Regs.MMIX),
|
||||
|
||||
PCORE(1,Regs.ATTR),
|
||||
PCORE(1, Regs.ATTR),
|
||||
|
||||
PCORE(1,IRQA)+1,
|
||||
PCORE(1,IRQA),
|
||||
PCORE(1, IRQA) + 1,
|
||||
PCORE(1, IRQA),
|
||||
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
|
||||
PCORE(1,TSA)+1,
|
||||
PCORE(1,TSA),
|
||||
PCORE(1, TSA) + 1,
|
||||
PCORE(1, TSA),
|
||||
|
||||
PRAW(0x5ac), PRAW(0x5ae),
|
||||
PRAW(0x5ac), PRAW(0x5ae),
|
||||
|
||||
PCORE(1,AutoDMACtrl),
|
||||
PCORE(1, AutoDMACtrl),
|
||||
|
||||
PRAW(0x5b2), PRAW(0x5b4), PRAW(0x5b6), PRAW(0x5b8), PRAW(0x5ba), PRAW(0x5bc), PRAW(0x5be), // unknown
|
||||
PRAW(0x5b2), PRAW(0x5b4), PRAW(0x5b6), PRAW(0x5b8), PRAW(0x5ba), PRAW(0x5bc), PRAW(0x5be), // unknown
|
||||
|
||||
// Voice Addresses
|
||||
PVCA(1, 0),PVCA(1, 1),PVCA(1, 2),PVCA(1, 3),PVCA(1, 4),PVCA(1, 5),
|
||||
PVCA(1, 6),PVCA(1, 7),PVCA(1, 8),PVCA(1, 9),PVCA(1,10),PVCA(1,11),
|
||||
PVCA(1,12),PVCA(1,13),PVCA(1,14),PVCA(1,15),PVCA(1,16),PVCA(1,17),
|
||||
PVCA(1,18),PVCA(1,19),PVCA(1,20),PVCA(1,21),PVCA(1,22),PVCA(1,23),
|
||||
// Voice Addresses
|
||||
PVCA(1, 0), PVCA(1, 1), PVCA(1, 2), PVCA(1, 3), PVCA(1, 4), PVCA(1, 5),
|
||||
PVCA(1, 6), PVCA(1, 7), PVCA(1, 8), PVCA(1, 9), PVCA(1, 10), PVCA(1, 11),
|
||||
PVCA(1, 12), PVCA(1, 13), PVCA(1, 14), PVCA(1, 15), PVCA(1, 16), PVCA(1, 17),
|
||||
PVCA(1, 18), PVCA(1, 19), PVCA(1, 20), PVCA(1, 21), PVCA(1, 22), PVCA(1, 23),
|
||||
|
||||
PCORE(1,ExtEffectsStartA)+1,
|
||||
PCORE(1,ExtEffectsStartA),
|
||||
PCORE(1, ExtEffectsStartA) + 1,
|
||||
PCORE(1, ExtEffectsStartA),
|
||||
|
||||
PREVB_REG(1,FB_SRC_A),
|
||||
PREVB_REG(1,FB_SRC_B),
|
||||
PREVB_REG(1,IIR_DEST_A0),
|
||||
PREVB_REG(1,IIR_DEST_A1),
|
||||
PREVB_REG(1,ACC_SRC_A0),
|
||||
PREVB_REG(1,ACC_SRC_A1),
|
||||
PREVB_REG(1,ACC_SRC_B0),
|
||||
PREVB_REG(1,ACC_SRC_B1),
|
||||
PREVB_REG(1,IIR_SRC_A0),
|
||||
PREVB_REG(1,IIR_SRC_A1),
|
||||
PREVB_REG(1,IIR_DEST_B0),
|
||||
PREVB_REG(1,IIR_DEST_B1),
|
||||
PREVB_REG(1,ACC_SRC_C0),
|
||||
PREVB_REG(1,ACC_SRC_C1),
|
||||
PREVB_REG(1,ACC_SRC_D0),
|
||||
PREVB_REG(1,ACC_SRC_D1),
|
||||
PREVB_REG(1,IIR_SRC_B0),
|
||||
PREVB_REG(1,IIR_SRC_B1),
|
||||
PREVB_REG(1,MIX_DEST_A0),
|
||||
PREVB_REG(1,MIX_DEST_A1),
|
||||
PREVB_REG(1,MIX_DEST_B0),
|
||||
PREVB_REG(1,MIX_DEST_B1),
|
||||
PREVB_REG(1, FB_SRC_A),
|
||||
PREVB_REG(1, FB_SRC_B),
|
||||
PREVB_REG(1, IIR_DEST_A0),
|
||||
PREVB_REG(1, IIR_DEST_A1),
|
||||
PREVB_REG(1, ACC_SRC_A0),
|
||||
PREVB_REG(1, ACC_SRC_A1),
|
||||
PREVB_REG(1, ACC_SRC_B0),
|
||||
PREVB_REG(1, ACC_SRC_B1),
|
||||
PREVB_REG(1, IIR_SRC_A0),
|
||||
PREVB_REG(1, IIR_SRC_A1),
|
||||
PREVB_REG(1, IIR_DEST_B0),
|
||||
PREVB_REG(1, IIR_DEST_B1),
|
||||
PREVB_REG(1, ACC_SRC_C0),
|
||||
PREVB_REG(1, ACC_SRC_C1),
|
||||
PREVB_REG(1, ACC_SRC_D0),
|
||||
PREVB_REG(1, ACC_SRC_D1),
|
||||
PREVB_REG(1, IIR_SRC_B0),
|
||||
PREVB_REG(1, IIR_SRC_B1),
|
||||
PREVB_REG(1, MIX_DEST_A0),
|
||||
PREVB_REG(1, MIX_DEST_A1),
|
||||
PREVB_REG(1, MIX_DEST_B0),
|
||||
PREVB_REG(1, MIX_DEST_B1),
|
||||
|
||||
PCORE(1,ExtEffectsEndA)+1,
|
||||
PCORE(1,ExtEffectsEndA),
|
||||
PCORE(1, ExtEffectsEndA) + 1,
|
||||
PCORE(1, ExtEffectsEndA),
|
||||
|
||||
PCORE(1,Regs.ENDX),
|
||||
PCORE(1,Regs.ENDX)+1,
|
||||
PCORE(1,Regs.STATX),
|
||||
PCORE(1, Regs.ENDX),
|
||||
PCORE(1, Regs.ENDX) + 1,
|
||||
PCORE(1, Regs.STATX),
|
||||
|
||||
PRAW(0x746),
|
||||
PRAW(0x748),PRAW(0x74A),PRAW(0x74C),PRAW(0x74E),
|
||||
PRAW(0x750),PRAW(0x752),PRAW(0x754),PRAW(0x756),
|
||||
PRAW(0x758),PRAW(0x75A),PRAW(0x75C),PRAW(0x75E),
|
||||
PRAW(0x746),
|
||||
PRAW(0x748), PRAW(0x74A), PRAW(0x74C), PRAW(0x74E),
|
||||
PRAW(0x750), PRAW(0x752), PRAW(0x754), PRAW(0x756),
|
||||
PRAW(0x758), PRAW(0x75A), PRAW(0x75C), PRAW(0x75E),
|
||||
|
||||
//0x760: weird area
|
||||
PCORE(0,MasterVol.Left.Reg_VOL),
|
||||
PCORE(0,MasterVol.Right.Reg_VOL),
|
||||
PCORE(0,FxVol.Left)+1,
|
||||
PCORE(0,FxVol.Right)+1,
|
||||
PCORE(0,ExtVol.Left)+1,
|
||||
PCORE(0,ExtVol.Right)+1,
|
||||
PCORE(0,InpVol.Left)+1,
|
||||
PCORE(0,InpVol.Right)+1,
|
||||
PCORE(0,MasterVol.Left.Value)+1,
|
||||
PCORE(0,MasterVol.Right.Value)+1,
|
||||
PCORE(0,Revb.IIR_ALPHA),
|
||||
PCORE(0,Revb.ACC_COEF_A),
|
||||
PCORE(0,Revb.ACC_COEF_B),
|
||||
PCORE(0,Revb.ACC_COEF_C),
|
||||
PCORE(0,Revb.ACC_COEF_D),
|
||||
PCORE(0,Revb.IIR_COEF),
|
||||
PCORE(0,Revb.FB_ALPHA),
|
||||
PCORE(0,Revb.FB_X),
|
||||
PCORE(0,Revb.IN_COEF_L),
|
||||
PCORE(0,Revb.IN_COEF_R),
|
||||
//0x760: weird area
|
||||
PCORE(0, MasterVol.Left.Reg_VOL),
|
||||
PCORE(0, MasterVol.Right.Reg_VOL),
|
||||
PCORE(0, FxVol.Left) + 1,
|
||||
PCORE(0, FxVol.Right) + 1,
|
||||
PCORE(0, ExtVol.Left) + 1,
|
||||
PCORE(0, ExtVol.Right) + 1,
|
||||
PCORE(0, InpVol.Left) + 1,
|
||||
PCORE(0, InpVol.Right) + 1,
|
||||
PCORE(0, MasterVol.Left.Value) + 1,
|
||||
PCORE(0, MasterVol.Right.Value) + 1,
|
||||
PCORE(0, Revb.IIR_ALPHA),
|
||||
PCORE(0, Revb.ACC_COEF_A),
|
||||
PCORE(0, Revb.ACC_COEF_B),
|
||||
PCORE(0, Revb.ACC_COEF_C),
|
||||
PCORE(0, Revb.ACC_COEF_D),
|
||||
PCORE(0, Revb.IIR_COEF),
|
||||
PCORE(0, Revb.FB_ALPHA),
|
||||
PCORE(0, Revb.FB_X),
|
||||
PCORE(0, Revb.IN_COEF_L),
|
||||
PCORE(0, Revb.IN_COEF_R),
|
||||
|
||||
PCORE(1,MasterVol.Left.Reg_VOL),
|
||||
PCORE(1,MasterVol.Right.Reg_VOL),
|
||||
PCORE(1,FxVol.Left)+1,
|
||||
PCORE(1,FxVol.Right)+1,
|
||||
PCORE(1,ExtVol.Left)+1,
|
||||
PCORE(1,ExtVol.Right)+1,
|
||||
PCORE(1,InpVol.Left)+1,
|
||||
PCORE(1,InpVol.Right)+1,
|
||||
PCORE(1,MasterVol.Left.Value)+1,
|
||||
PCORE(1,MasterVol.Right.Value)+1,
|
||||
PCORE(1,Revb.IIR_ALPHA),
|
||||
PCORE(1,Revb.ACC_COEF_A),
|
||||
PCORE(1,Revb.ACC_COEF_B),
|
||||
PCORE(1,Revb.ACC_COEF_C),
|
||||
PCORE(1,Revb.ACC_COEF_D),
|
||||
PCORE(1,Revb.IIR_COEF),
|
||||
PCORE(1,Revb.FB_ALPHA),
|
||||
PCORE(1,Revb.FB_X),
|
||||
PCORE(1,Revb.IN_COEF_L),
|
||||
PCORE(1,Revb.IN_COEF_R),
|
||||
PCORE(1, MasterVol.Left.Reg_VOL),
|
||||
PCORE(1, MasterVol.Right.Reg_VOL),
|
||||
PCORE(1, FxVol.Left) + 1,
|
||||
PCORE(1, FxVol.Right) + 1,
|
||||
PCORE(1, ExtVol.Left) + 1,
|
||||
PCORE(1, ExtVol.Right) + 1,
|
||||
PCORE(1, InpVol.Left) + 1,
|
||||
PCORE(1, InpVol.Right) + 1,
|
||||
PCORE(1, MasterVol.Left.Value) + 1,
|
||||
PCORE(1, MasterVol.Right.Value) + 1,
|
||||
PCORE(1, Revb.IIR_ALPHA),
|
||||
PCORE(1, Revb.ACC_COEF_A),
|
||||
PCORE(1, Revb.ACC_COEF_B),
|
||||
PCORE(1, Revb.ACC_COEF_C),
|
||||
PCORE(1, Revb.ACC_COEF_D),
|
||||
PCORE(1, Revb.IIR_COEF),
|
||||
PCORE(1, Revb.FB_ALPHA),
|
||||
PCORE(1, Revb.FB_X),
|
||||
PCORE(1, Revb.IN_COEF_L),
|
||||
PCORE(1, Revb.IN_COEF_R),
|
||||
|
||||
PRAW(0x7B0),PRAW(0x7B2),PRAW(0x7B4),PRAW(0x7B6),
|
||||
PRAW(0x7B8),PRAW(0x7BA),PRAW(0x7BC),PRAW(0x7BE),
|
||||
PRAW(0x7B0), PRAW(0x7B2), PRAW(0x7B4), PRAW(0x7B6),
|
||||
PRAW(0x7B8), PRAW(0x7BA), PRAW(0x7BC), PRAW(0x7BE),
|
||||
|
||||
// SPDIF interface
|
||||
U16P(Spdif.Out),
|
||||
U16P(Spdif.Info),
|
||||
U16P(Spdif.Unknown1),
|
||||
U16P(Spdif.Mode),
|
||||
U16P(Spdif.Media),
|
||||
U16P(Spdif.Unknown2),
|
||||
U16P(Spdif.Protection),
|
||||
// SPDIF interface
|
||||
U16P(Spdif.Out),
|
||||
U16P(Spdif.Info),
|
||||
U16P(Spdif.Unknown1),
|
||||
U16P(Spdif.Mode),
|
||||
U16P(Spdif.Media),
|
||||
U16P(Spdif.Unknown2),
|
||||
U16P(Spdif.Protection),
|
||||
|
||||
PRAW(0x7CE),
|
||||
PRAW(0x7D0),PRAW(0x7D2),PRAW(0x7D4),PRAW(0x7D6),
|
||||
PRAW(0x7D8),PRAW(0x7DA),PRAW(0x7DC),PRAW(0x7DE),
|
||||
PRAW(0x7E0),PRAW(0x7E2),PRAW(0x7E4),PRAW(0x7E6),
|
||||
PRAW(0x7E8),PRAW(0x7EA),PRAW(0x7EC),PRAW(0x7EE),
|
||||
PRAW(0x7F0),PRAW(0x7F2),PRAW(0x7F4),PRAW(0x7F6),
|
||||
PRAW(0x7F8),PRAW(0x7FA),PRAW(0x7FC),PRAW(0x7FE),
|
||||
PRAW(0x7CE),
|
||||
PRAW(0x7D0), PRAW(0x7D2), PRAW(0x7D4), PRAW(0x7D6),
|
||||
PRAW(0x7D8), PRAW(0x7DA), PRAW(0x7DC), PRAW(0x7DE),
|
||||
PRAW(0x7E0), PRAW(0x7E2), PRAW(0x7E4), PRAW(0x7E6),
|
||||
PRAW(0x7E8), PRAW(0x7EA), PRAW(0x7EC), PRAW(0x7EE),
|
||||
PRAW(0x7F0), PRAW(0x7F2), PRAW(0x7F4), PRAW(0x7F6),
|
||||
PRAW(0x7F8), PRAW(0x7FA), PRAW(0x7FC), PRAW(0x7FE),
|
||||
|
||||
NULL
|
||||
};
|
||||
NULL};
|
||||
|
|
|
@ -24,38 +24,37 @@
|
|||
//static LowPassFilter64 lowpass_left( 11000, SampleRate );
|
||||
//static LowPassFilter64 lowpass_right( 11000, SampleRate );
|
||||
|
||||
__forceinline s32 V_Core::RevbGetIndexer( s32 offset )
|
||||
__forceinline s32 V_Core::RevbGetIndexer(s32 offset)
|
||||
{
|
||||
u32 pos = ReverbX + offset;
|
||||
u32 pos = ReverbX + offset;
|
||||
|
||||
// Fast and simple single step wrapping, made possible by the preparation of the
|
||||
// effects buffer addresses.
|
||||
// Fast and simple single step wrapping, made possible by the preparation of the
|
||||
// effects buffer addresses.
|
||||
|
||||
if( pos > EffectsEndA )
|
||||
{
|
||||
pos -= EffectsEndA+1;
|
||||
pos += EffectsStartA;
|
||||
}
|
||||
if (pos > EffectsEndA) {
|
||||
pos -= EffectsEndA + 1;
|
||||
pos += EffectsStartA;
|
||||
}
|
||||
|
||||
assert(pos >= EffectsStartA && pos <= EffectsEndA);
|
||||
return pos;
|
||||
assert(pos >= EffectsStartA && pos <= EffectsEndA);
|
||||
return pos;
|
||||
}
|
||||
|
||||
void V_Core::Reverb_AdvanceBuffer()
|
||||
{
|
||||
if( RevBuffers.NeedsUpdated )
|
||||
UpdateEffectsBufferSize();
|
||||
if (RevBuffers.NeedsUpdated)
|
||||
UpdateEffectsBufferSize();
|
||||
|
||||
if( (Cycles & 1) && (EffectsBufferSize > 0) )
|
||||
{
|
||||
ReverbX += 1;
|
||||
if( ReverbX >= (u32)EffectsBufferSize ) ReverbX = 0;
|
||||
}
|
||||
if ((Cycles & 1) && (EffectsBufferSize > 0)) {
|
||||
ReverbX += 1;
|
||||
if (ReverbX >= (u32)EffectsBufferSize)
|
||||
ReverbX = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
StereoOut32 V_Core::DoReverb( const StereoOut32& Input )
|
||||
StereoOut32 V_Core::DoReverb(const StereoOut32 &Input)
|
||||
{
|
||||
#if 0
|
||||
static const s32 downcoeffs[8] =
|
||||
|
@ -64,222 +63,208 @@ StereoOut32 V_Core::DoReverb( const StereoOut32& Input )
|
|||
15243, 10895, 5344, 1283
|
||||
};
|
||||
#else
|
||||
// 2/3 of the above
|
||||
static const s32 downcoeffs[8] =
|
||||
{
|
||||
855, 3562, 7263, 10163,
|
||||
10163, 7263, 3562, 855
|
||||
};
|
||||
// 2/3 of the above
|
||||
static const s32 downcoeffs[8] =
|
||||
{
|
||||
855, 3562, 7263, 10163,
|
||||
10163, 7263, 3562, 855};
|
||||
#endif
|
||||
|
||||
downbuf[dbpos] = Input;
|
||||
dbpos = (dbpos+1) & 7;
|
||||
downbuf[dbpos] = Input;
|
||||
dbpos = (dbpos + 1) & 7;
|
||||
|
||||
// Reverb processing occurs at 24khz, so we skip processing every other sample,
|
||||
// and use the previous calculation for this core instead.
|
||||
// Reverb processing occurs at 24khz, so we skip processing every other sample,
|
||||
// and use the previous calculation for this core instead.
|
||||
|
||||
if( (Cycles&1) == 0 )
|
||||
{
|
||||
// Important: Factor silence into the upsampler here, otherwise the reverb engine
|
||||
// develops a nasty feedback loop.
|
||||
if ((Cycles & 1) == 0) {
|
||||
// Important: Factor silence into the upsampler here, otherwise the reverb engine
|
||||
// develops a nasty feedback loop.
|
||||
|
||||
upbuf[ubpos] = StereoOut32::Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( EffectsBufferSize <= 0 )
|
||||
{
|
||||
ubpos = (ubpos+1) & 7;
|
||||
return StereoOut32::Empty;
|
||||
}
|
||||
upbuf[ubpos] = StereoOut32::Empty;
|
||||
} else {
|
||||
if (EffectsBufferSize <= 0) {
|
||||
ubpos = (ubpos + 1) & 7;
|
||||
return StereoOut32::Empty;
|
||||
}
|
||||
|
||||
// Advance the current reverb buffer pointer, and cache the read/write addresses we'll be
|
||||
// needing for this session of reverb.
|
||||
// Advance the current reverb buffer pointer, and cache the read/write addresses we'll be
|
||||
// needing for this session of reverb.
|
||||
|
||||
const u32 src_a0 = RevbGetIndexer( RevBuffers.IIR_SRC_A0 );
|
||||
const u32 src_a1 = RevbGetIndexer( RevBuffers.IIR_SRC_A1 );
|
||||
const u32 src_b0 = RevbGetIndexer( RevBuffers.IIR_SRC_B0 );
|
||||
const u32 src_b1 = RevbGetIndexer( RevBuffers.IIR_SRC_B1 );
|
||||
const u32 src_a0 = RevbGetIndexer(RevBuffers.IIR_SRC_A0);
|
||||
const u32 src_a1 = RevbGetIndexer(RevBuffers.IIR_SRC_A1);
|
||||
const u32 src_b0 = RevbGetIndexer(RevBuffers.IIR_SRC_B0);
|
||||
const u32 src_b1 = RevbGetIndexer(RevBuffers.IIR_SRC_B1);
|
||||
|
||||
const u32 dest_a0 = RevbGetIndexer( RevBuffers.IIR_DEST_A0 );
|
||||
const u32 dest_a1 = RevbGetIndexer( RevBuffers.IIR_DEST_A1 );
|
||||
const u32 dest_b0 = RevbGetIndexer( RevBuffers.IIR_DEST_B0 );
|
||||
const u32 dest_b1 = RevbGetIndexer( RevBuffers.IIR_DEST_B1 );
|
||||
const u32 dest_a0 = RevbGetIndexer(RevBuffers.IIR_DEST_A0);
|
||||
const u32 dest_a1 = RevbGetIndexer(RevBuffers.IIR_DEST_A1);
|
||||
const u32 dest_b0 = RevbGetIndexer(RevBuffers.IIR_DEST_B0);
|
||||
const u32 dest_b1 = RevbGetIndexer(RevBuffers.IIR_DEST_B1);
|
||||
|
||||
const u32 dest2_a0 = RevbGetIndexer( RevBuffers.IIR_DEST_A0 + 1 );
|
||||
const u32 dest2_a1 = RevbGetIndexer( RevBuffers.IIR_DEST_A1 + 1 );
|
||||
const u32 dest2_b0 = RevbGetIndexer( RevBuffers.IIR_DEST_B0 + 1 );
|
||||
const u32 dest2_b1 = RevbGetIndexer( RevBuffers.IIR_DEST_B1 + 1 );
|
||||
const u32 dest2_a0 = RevbGetIndexer(RevBuffers.IIR_DEST_A0 + 1);
|
||||
const u32 dest2_a1 = RevbGetIndexer(RevBuffers.IIR_DEST_A1 + 1);
|
||||
const u32 dest2_b0 = RevbGetIndexer(RevBuffers.IIR_DEST_B0 + 1);
|
||||
const u32 dest2_b1 = RevbGetIndexer(RevBuffers.IIR_DEST_B1 + 1);
|
||||
|
||||
const u32 acc_src_a0 = RevbGetIndexer( RevBuffers.ACC_SRC_A0 );
|
||||
const u32 acc_src_b0 = RevbGetIndexer( RevBuffers.ACC_SRC_B0 );
|
||||
const u32 acc_src_c0 = RevbGetIndexer( RevBuffers.ACC_SRC_C0 );
|
||||
const u32 acc_src_d0 = RevbGetIndexer( RevBuffers.ACC_SRC_D0 );
|
||||
const u32 acc_src_a0 = RevbGetIndexer(RevBuffers.ACC_SRC_A0);
|
||||
const u32 acc_src_b0 = RevbGetIndexer(RevBuffers.ACC_SRC_B0);
|
||||
const u32 acc_src_c0 = RevbGetIndexer(RevBuffers.ACC_SRC_C0);
|
||||
const u32 acc_src_d0 = RevbGetIndexer(RevBuffers.ACC_SRC_D0);
|
||||
|
||||
const u32 acc_src_a1 = RevbGetIndexer( RevBuffers.ACC_SRC_A1 );
|
||||
const u32 acc_src_b1 = RevbGetIndexer( RevBuffers.ACC_SRC_B1 );
|
||||
const u32 acc_src_c1 = RevbGetIndexer( RevBuffers.ACC_SRC_C1 );
|
||||
const u32 acc_src_d1 = RevbGetIndexer( RevBuffers.ACC_SRC_D1 );
|
||||
const u32 acc_src_a1 = RevbGetIndexer(RevBuffers.ACC_SRC_A1);
|
||||
const u32 acc_src_b1 = RevbGetIndexer(RevBuffers.ACC_SRC_B1);
|
||||
const u32 acc_src_c1 = RevbGetIndexer(RevBuffers.ACC_SRC_C1);
|
||||
const u32 acc_src_d1 = RevbGetIndexer(RevBuffers.ACC_SRC_D1);
|
||||
|
||||
const u32 fb_src_a0 = RevbGetIndexer( RevBuffers.FB_SRC_A0 );
|
||||
const u32 fb_src_a1 = RevbGetIndexer( RevBuffers.FB_SRC_A1 );
|
||||
const u32 fb_src_b0 = RevbGetIndexer( RevBuffers.FB_SRC_B0 );
|
||||
const u32 fb_src_b1 = RevbGetIndexer( RevBuffers.FB_SRC_B1 );
|
||||
const u32 fb_src_a0 = RevbGetIndexer(RevBuffers.FB_SRC_A0);
|
||||
const u32 fb_src_a1 = RevbGetIndexer(RevBuffers.FB_SRC_A1);
|
||||
const u32 fb_src_b0 = RevbGetIndexer(RevBuffers.FB_SRC_B0);
|
||||
const u32 fb_src_b1 = RevbGetIndexer(RevBuffers.FB_SRC_B1);
|
||||
|
||||
const u32 mix_dest_a0 = RevbGetIndexer( RevBuffers.MIX_DEST_A0 );
|
||||
const u32 mix_dest_a1 = RevbGetIndexer( RevBuffers.MIX_DEST_A1 );
|
||||
const u32 mix_dest_b0 = RevbGetIndexer( RevBuffers.MIX_DEST_B0 );
|
||||
const u32 mix_dest_b1 = RevbGetIndexer( RevBuffers.MIX_DEST_B1 );
|
||||
const u32 mix_dest_a0 = RevbGetIndexer(RevBuffers.MIX_DEST_A0);
|
||||
const u32 mix_dest_a1 = RevbGetIndexer(RevBuffers.MIX_DEST_A1);
|
||||
const u32 mix_dest_b0 = RevbGetIndexer(RevBuffers.MIX_DEST_B0);
|
||||
const u32 mix_dest_b1 = RevbGetIndexer(RevBuffers.MIX_DEST_B1);
|
||||
|
||||
// -----------------------------------------
|
||||
// Optimized IRQ Testing !
|
||||
// -----------------------------------------
|
||||
// -----------------------------------------
|
||||
// Optimized IRQ Testing !
|
||||
// -----------------------------------------
|
||||
|
||||
// This test is enhanced by using the reverb effects area begin/end test as a
|
||||
// shortcut, since all buffer addresses are within that area. If the IRQA isn't
|
||||
// within that zone then the "bulk" of the test is skipped, so this should only
|
||||
// be a slowdown on a few evil games.
|
||||
// This test is enhanced by using the reverb effects area begin/end test as a
|
||||
// shortcut, since all buffer addresses are within that area. If the IRQA isn't
|
||||
// within that zone then the "bulk" of the test is skipped, so this should only
|
||||
// be a slowdown on a few evil games.
|
||||
|
||||
for( int i=0; i<2; i++ )
|
||||
{
|
||||
if( Cores[i].IRQEnable && ((Cores[i].IRQA >= EffectsStartA) && (Cores[i].IRQA <= EffectsEndA)) )
|
||||
{
|
||||
if( (Cores[i].IRQA == src_a0) || (Cores[i].IRQA == src_a1) ||
|
||||
(Cores[i].IRQA == src_b0) || (Cores[i].IRQA == src_b1) ||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (Cores[i].IRQEnable && ((Cores[i].IRQA >= EffectsStartA) && (Cores[i].IRQA <= EffectsEndA))) {
|
||||
if ((Cores[i].IRQA == src_a0) || (Cores[i].IRQA == src_a1) ||
|
||||
(Cores[i].IRQA == src_b0) || (Cores[i].IRQA == src_b1) ||
|
||||
|
||||
(Cores[i].IRQA == dest_a0) || (Cores[i].IRQA == dest_a1) ||
|
||||
(Cores[i].IRQA == dest_b0) || (Cores[i].IRQA == dest_b1) ||
|
||||
(Cores[i].IRQA == dest_a0) || (Cores[i].IRQA == dest_a1) ||
|
||||
(Cores[i].IRQA == dest_b0) || (Cores[i].IRQA == dest_b1) ||
|
||||
|
||||
(Cores[i].IRQA == dest2_a0) || (Cores[i].IRQA == dest2_a1) ||
|
||||
(Cores[i].IRQA == dest2_b0) || (Cores[i].IRQA == dest2_b1) ||
|
||||
(Cores[i].IRQA == dest2_a0) || (Cores[i].IRQA == dest2_a1) ||
|
||||
(Cores[i].IRQA == dest2_b0) || (Cores[i].IRQA == dest2_b1) ||
|
||||
|
||||
(Cores[i].IRQA == acc_src_a0) || (Cores[i].IRQA == acc_src_a1) ||
|
||||
(Cores[i].IRQA == acc_src_b0) || (Cores[i].IRQA == acc_src_b1) ||
|
||||
(Cores[i].IRQA == acc_src_c0) || (Cores[i].IRQA == acc_src_c1) ||
|
||||
(Cores[i].IRQA == acc_src_d0) || (Cores[i].IRQA == acc_src_d1) ||
|
||||
(Cores[i].IRQA == acc_src_a0) || (Cores[i].IRQA == acc_src_a1) ||
|
||||
(Cores[i].IRQA == acc_src_b0) || (Cores[i].IRQA == acc_src_b1) ||
|
||||
(Cores[i].IRQA == acc_src_c0) || (Cores[i].IRQA == acc_src_c1) ||
|
||||
(Cores[i].IRQA == acc_src_d0) || (Cores[i].IRQA == acc_src_d1) ||
|
||||
|
||||
(Cores[i].IRQA == fb_src_a0) || (Cores[i].IRQA == fb_src_a1) ||
|
||||
(Cores[i].IRQA == fb_src_b0) || (Cores[i].IRQA == fb_src_b1) ||
|
||||
(Cores[i].IRQA == fb_src_a0) || (Cores[i].IRQA == fb_src_a1) ||
|
||||
(Cores[i].IRQA == fb_src_b0) || (Cores[i].IRQA == fb_src_b1) ||
|
||||
|
||||
(Cores[i].IRQA == mix_dest_a0) || (Cores[i].IRQA == mix_dest_a1) ||
|
||||
(Cores[i].IRQA == mix_dest_b0) || (Cores[i].IRQA == mix_dest_b1) )
|
||||
{
|
||||
//printf("Core %d IRQ Called (Reverb). IRQA = %x\n",i,addr);
|
||||
SetIrqCall(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
(Cores[i].IRQA == mix_dest_a0) || (Cores[i].IRQA == mix_dest_a1) ||
|
||||
(Cores[i].IRQA == mix_dest_b0) || (Cores[i].IRQA == mix_dest_b1)) {
|
||||
//printf("Core %d IRQ Called (Reverb). IRQA = %x\n",i,addr);
|
||||
SetIrqCall(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
// Begin Reverb Processing !
|
||||
// -----------------------------------------
|
||||
// -----------------------------------------
|
||||
// Begin Reverb Processing !
|
||||
// -----------------------------------------
|
||||
|
||||
StereoOut32 INPUT_SAMPLE;
|
||||
StereoOut32 INPUT_SAMPLE;
|
||||
|
||||
for( int x=0; x<8; ++x )
|
||||
{
|
||||
INPUT_SAMPLE.Left += (downbuf[(dbpos+x)&7].Left * downcoeffs[x]);
|
||||
INPUT_SAMPLE.Right += (downbuf[(dbpos+x)&7].Right * downcoeffs[x]);
|
||||
}
|
||||
for (int x = 0; x < 8; ++x) {
|
||||
INPUT_SAMPLE.Left += (downbuf[(dbpos + x) & 7].Left * downcoeffs[x]);
|
||||
INPUT_SAMPLE.Right += (downbuf[(dbpos + x) & 7].Right * downcoeffs[x]);
|
||||
}
|
||||
|
||||
INPUT_SAMPLE.Left >>= 16;
|
||||
INPUT_SAMPLE.Right >>= 16;
|
||||
INPUT_SAMPLE.Left >>= 16;
|
||||
INPUT_SAMPLE.Right >>= 16;
|
||||
|
||||
s32 input_L = INPUT_SAMPLE.Left * Revb.IN_COEF_L;
|
||||
s32 input_R = INPUT_SAMPLE.Right * Revb.IN_COEF_R;
|
||||
s32 input_L = INPUT_SAMPLE.Left * Revb.IN_COEF_L;
|
||||
s32 input_R = INPUT_SAMPLE.Right * Revb.IN_COEF_R;
|
||||
|
||||
const s32 IIR_INPUT_A0 = clamp_mix((((s32)_spu2mem[src_a0] * Revb.IIR_COEF) + input_L)>>15);
|
||||
const s32 IIR_INPUT_A1 = clamp_mix((((s32)_spu2mem[src_a1] * Revb.IIR_COEF) + input_L)>>15);
|
||||
const s32 IIR_INPUT_B0 = clamp_mix((((s32)_spu2mem[src_b0] * Revb.IIR_COEF) + input_R)>>15);
|
||||
const s32 IIR_INPUT_B1 = clamp_mix((((s32)_spu2mem[src_b1] * Revb.IIR_COEF) + input_R)>>15);
|
||||
const s32 IIR_INPUT_A0 = clamp_mix((((s32)_spu2mem[src_a0] * Revb.IIR_COEF) + input_L) >> 15);
|
||||
const s32 IIR_INPUT_A1 = clamp_mix((((s32)_spu2mem[src_a1] * Revb.IIR_COEF) + input_L) >> 15);
|
||||
const s32 IIR_INPUT_B0 = clamp_mix((((s32)_spu2mem[src_b0] * Revb.IIR_COEF) + input_R) >> 15);
|
||||
const s32 IIR_INPUT_B1 = clamp_mix((((s32)_spu2mem[src_b1] * Revb.IIR_COEF) + input_R) >> 15);
|
||||
|
||||
const s32 src_dest_a0 = _spu2mem[dest_a0];
|
||||
const s32 src_dest_a1 = _spu2mem[dest_a1];
|
||||
const s32 src_dest_b0 = _spu2mem[dest_b0];
|
||||
const s32 src_dest_b1 = _spu2mem[dest_b1];
|
||||
const s32 src_dest_a0 = _spu2mem[dest_a0];
|
||||
const s32 src_dest_a1 = _spu2mem[dest_a1];
|
||||
const s32 src_dest_b0 = _spu2mem[dest_b0];
|
||||
const s32 src_dest_b1 = _spu2mem[dest_b1];
|
||||
|
||||
// This section differs from Neill's doc as it uses single-mul interpolation instead
|
||||
// of 0x8000-val inversion. (same result, faster)
|
||||
const s32 IIR_A0 = src_dest_a0 + (((IIR_INPUT_A0 - src_dest_a0) * Revb.IIR_ALPHA)>>15);
|
||||
const s32 IIR_A1 = src_dest_a1 + (((IIR_INPUT_A1 - src_dest_a1) * Revb.IIR_ALPHA)>>15);
|
||||
const s32 IIR_B0 = src_dest_b0 + (((IIR_INPUT_B0 - src_dest_b0) * Revb.IIR_ALPHA)>>15);
|
||||
const s32 IIR_B1 = src_dest_b1 + (((IIR_INPUT_B1 - src_dest_b1) * Revb.IIR_ALPHA)>>15);
|
||||
_spu2mem[dest2_a0] = clamp_mix( IIR_A0 );
|
||||
_spu2mem[dest2_a1] = clamp_mix( IIR_A1 );
|
||||
_spu2mem[dest2_b0] = clamp_mix( IIR_B0 );
|
||||
_spu2mem[dest2_b1] = clamp_mix( IIR_B1 );
|
||||
// This section differs from Neill's doc as it uses single-mul interpolation instead
|
||||
// of 0x8000-val inversion. (same result, faster)
|
||||
const s32 IIR_A0 = src_dest_a0 + (((IIR_INPUT_A0 - src_dest_a0) * Revb.IIR_ALPHA) >> 15);
|
||||
const s32 IIR_A1 = src_dest_a1 + (((IIR_INPUT_A1 - src_dest_a1) * Revb.IIR_ALPHA) >> 15);
|
||||
const s32 IIR_B0 = src_dest_b0 + (((IIR_INPUT_B0 - src_dest_b0) * Revb.IIR_ALPHA) >> 15);
|
||||
const s32 IIR_B1 = src_dest_b1 + (((IIR_INPUT_B1 - src_dest_b1) * Revb.IIR_ALPHA) >> 15);
|
||||
_spu2mem[dest2_a0] = clamp_mix(IIR_A0);
|
||||
_spu2mem[dest2_a1] = clamp_mix(IIR_A1);
|
||||
_spu2mem[dest2_b0] = clamp_mix(IIR_B0);
|
||||
_spu2mem[dest2_b1] = clamp_mix(IIR_B1);
|
||||
|
||||
const s32 ACC0 = clamp_mix(
|
||||
((_spu2mem[acc_src_a0] * Revb.ACC_COEF_A) >> 15) +
|
||||
((_spu2mem[acc_src_b0] * Revb.ACC_COEF_B) >> 15) +
|
||||
((_spu2mem[acc_src_c0] * Revb.ACC_COEF_C) >> 15) +
|
||||
((_spu2mem[acc_src_d0] * Revb.ACC_COEF_D) >> 15)
|
||||
);
|
||||
const s32 ACC0 = clamp_mix(
|
||||
((_spu2mem[acc_src_a0] * Revb.ACC_COEF_A) >> 15) +
|
||||
((_spu2mem[acc_src_b0] * Revb.ACC_COEF_B) >> 15) +
|
||||
((_spu2mem[acc_src_c0] * Revb.ACC_COEF_C) >> 15) +
|
||||
((_spu2mem[acc_src_d0] * Revb.ACC_COEF_D) >> 15));
|
||||
|
||||
const s32 ACC1 = clamp_mix(
|
||||
((_spu2mem[acc_src_a1] * Revb.ACC_COEF_A) >> 15) +
|
||||
((_spu2mem[acc_src_b1] * Revb.ACC_COEF_B) >> 15) +
|
||||
((_spu2mem[acc_src_c1] * Revb.ACC_COEF_C) >> 15) +
|
||||
((_spu2mem[acc_src_d1] * Revb.ACC_COEF_D) >> 15)
|
||||
);
|
||||
const s32 ACC1 = clamp_mix(
|
||||
((_spu2mem[acc_src_a1] * Revb.ACC_COEF_A) >> 15) +
|
||||
((_spu2mem[acc_src_b1] * Revb.ACC_COEF_B) >> 15) +
|
||||
((_spu2mem[acc_src_c1] * Revb.ACC_COEF_C) >> 15) +
|
||||
((_spu2mem[acc_src_d1] * Revb.ACC_COEF_D) >> 15));
|
||||
|
||||
// The following code differs from Neill's doc as it uses the more natural single-mul
|
||||
// interpolative, instead of the funky ^0x8000 stuff. (better result, faster)
|
||||
// The following code differs from Neill's doc as it uses the more natural single-mul
|
||||
// interpolative, instead of the funky ^0x8000 stuff. (better result, faster)
|
||||
|
||||
const s32 FB_A0 = _spu2mem[fb_src_a0];
|
||||
const s32 FB_A1 = _spu2mem[fb_src_a1];
|
||||
const s32 FB_B0 = _spu2mem[fb_src_b0];
|
||||
const s32 FB_B1 = _spu2mem[fb_src_b1];
|
||||
const s32 FB_A0 = _spu2mem[fb_src_a0];
|
||||
const s32 FB_A1 = _spu2mem[fb_src_a1];
|
||||
const s32 FB_B0 = _spu2mem[fb_src_b0];
|
||||
const s32 FB_B1 = _spu2mem[fb_src_b1];
|
||||
|
||||
const s32 mix_a0 = clamp_mix(ACC0 - ((FB_A0 * Revb.FB_ALPHA) >> 15));
|
||||
const s32 mix_a1 = clamp_mix(ACC1 - ((FB_A1 * Revb.FB_ALPHA) >> 15));
|
||||
const s32 mix_b0 = clamp_mix(FB_A0 + (((ACC0 - FB_A0) * Revb.FB_ALPHA - FB_B0 * Revb.FB_X) >> 15));
|
||||
const s32 mix_b1 = clamp_mix(FB_A1 + (((ACC1 - FB_A1) * Revb.FB_ALPHA - FB_B1 * Revb.FB_X) >> 15));
|
||||
const s32 mix_a0 = clamp_mix(ACC0 - ((FB_A0 * Revb.FB_ALPHA) >> 15));
|
||||
const s32 mix_a1 = clamp_mix(ACC1 - ((FB_A1 * Revb.FB_ALPHA) >> 15));
|
||||
const s32 mix_b0 = clamp_mix(FB_A0 + (((ACC0 - FB_A0) * Revb.FB_ALPHA - FB_B0 * Revb.FB_X) >> 15));
|
||||
const s32 mix_b1 = clamp_mix(FB_A1 + (((ACC1 - FB_A1) * Revb.FB_ALPHA - FB_B1 * Revb.FB_X) >> 15));
|
||||
|
||||
_spu2mem[mix_dest_a0] = mix_a0;
|
||||
_spu2mem[mix_dest_a1] = mix_a1;
|
||||
_spu2mem[mix_dest_b0] = mix_b0;
|
||||
_spu2mem[mix_dest_b1] = mix_b1;
|
||||
_spu2mem[mix_dest_a0] = mix_a0;
|
||||
_spu2mem[mix_dest_a1] = mix_a1;
|
||||
_spu2mem[mix_dest_b0] = mix_b0;
|
||||
_spu2mem[mix_dest_b1] = mix_b1;
|
||||
|
||||
upbuf[ubpos] = clamp_mix( StereoOut32(
|
||||
mix_a0 + mix_b0, // left
|
||||
mix_a1 + mix_b1 // right
|
||||
) );
|
||||
}
|
||||
upbuf[ubpos] = clamp_mix(StereoOut32(
|
||||
mix_a0 + mix_b0, // left
|
||||
mix_a1 + mix_b1 // right
|
||||
));
|
||||
}
|
||||
|
||||
StereoOut32 retval;
|
||||
StereoOut32 retval;
|
||||
|
||||
//for( int x=0; x<8; ++x )
|
||||
//{
|
||||
// retval.Left += (upbuf[(ubpos+x)&7].Left*downcoeffs[x]);
|
||||
// retval.Right += (upbuf[(ubpos+x)&7].Right*downcoeffs[x]);
|
||||
//}
|
||||
//for( int x=0; x<8; ++x )
|
||||
//{
|
||||
// retval.Left += (upbuf[(ubpos+x)&7].Left*downcoeffs[x]);
|
||||
// retval.Right += (upbuf[(ubpos+x)&7].Right*downcoeffs[x]);
|
||||
//}
|
||||
|
||||
if( (Cycles&1) == 0 )
|
||||
{
|
||||
retval.Left = (upbuf[(ubpos+5)&7].Left + upbuf[(ubpos+7)&7].Left)>>1;
|
||||
retval.Right = (upbuf[(ubpos+5)&7].Right + upbuf[(ubpos+7)&7].Right)>>1;
|
||||
}
|
||||
else
|
||||
{
|
||||
retval.Left = upbuf[(ubpos+6)&7].Left;
|
||||
retval.Right = upbuf[(ubpos+6)&7].Right;
|
||||
}
|
||||
if ((Cycles & 1) == 0) {
|
||||
retval.Left = (upbuf[(ubpos + 5) & 7].Left + upbuf[(ubpos + 7) & 7].Left) >> 1;
|
||||
retval.Right = (upbuf[(ubpos + 5) & 7].Right + upbuf[(ubpos + 7) & 7].Right) >> 1;
|
||||
} else {
|
||||
retval.Left = upbuf[(ubpos + 6) & 7].Left;
|
||||
retval.Right = upbuf[(ubpos + 6) & 7].Right;
|
||||
}
|
||||
|
||||
// Notes:
|
||||
// the first -1 is to adjust for the null padding in every other upbuf sample (which
|
||||
// halves the overall volume).
|
||||
// The second +1 divides by two, which is part of Neill's suggestion to divide by 3.
|
||||
//
|
||||
// According Neill the final result should be divided by 3, but currently the output
|
||||
// is way too quiet for that to fly. In fact no division at all might be better.
|
||||
// In any case the problem always seems to be that the reverb isn't resonating enough
|
||||
// (indicating short buffers or bad coefficient math?), not that it isn't loud enough.
|
||||
// Notes:
|
||||
// the first -1 is to adjust for the null padding in every other upbuf sample (which
|
||||
// halves the overall volume).
|
||||
// The second +1 divides by two, which is part of Neill's suggestion to divide by 3.
|
||||
//
|
||||
// According Neill the final result should be divided by 3, but currently the output
|
||||
// is way too quiet for that to fly. In fact no division at all might be better.
|
||||
// In any case the problem always seems to be that the reverb isn't resonating enough
|
||||
// (indicating short buffers or bad coefficient math?), not that it isn't loud enough.
|
||||
|
||||
//retval.Left >>= (16-1 + 1);
|
||||
//retval.Right >>= (16-1 + 1);
|
||||
//retval.Left >>= (16-1 + 1);
|
||||
//retval.Right >>= (16-1 + 1);
|
||||
|
||||
ubpos = (ubpos+1) & 7;
|
||||
ubpos = (ubpos + 1) & 7;
|
||||
|
||||
return retval;
|
||||
return retval;
|
||||
}
|
|
@ -18,99 +18,95 @@
|
|||
#include "Global.h"
|
||||
|
||||
|
||||
StereoOut32 StereoOut32::Empty( 0, 0 );
|
||||
StereoOut32 StereoOut32::Empty(0, 0);
|
||||
|
||||
StereoOut32::StereoOut32( const StereoOut16& src ) :
|
||||
Left( src.Left ),
|
||||
Right( src.Right )
|
||||
StereoOut32::StereoOut32(const StereoOut16 &src)
|
||||
: Left(src.Left)
|
||||
, Right(src.Right)
|
||||
{
|
||||
}
|
||||
|
||||
StereoOut32::StereoOut32( const StereoOutFloat& src ) :
|
||||
Left( (s32)(src.Left * 2147483647.0f) ),
|
||||
Right( (s32)(src.Right * 2147483647.0f) )
|
||||
StereoOut32::StereoOut32(const StereoOutFloat &src)
|
||||
: Left((s32)(src.Left * 2147483647.0f))
|
||||
, Right((s32)(src.Right * 2147483647.0f))
|
||||
{
|
||||
}
|
||||
|
||||
StereoOut16 StereoOut32::DownSample() const
|
||||
{
|
||||
return StereoOut16(
|
||||
Left >> SndOutVolumeShift,
|
||||
Right >> SndOutVolumeShift
|
||||
);
|
||||
return StereoOut16(
|
||||
Left >> SndOutVolumeShift,
|
||||
Right >> SndOutVolumeShift);
|
||||
}
|
||||
|
||||
StereoOut32 StereoOut16::UpSample() const
|
||||
{
|
||||
return StereoOut32(
|
||||
Left << SndOutVolumeShift,
|
||||
Right << SndOutVolumeShift
|
||||
);
|
||||
|
||||
return StereoOut32(
|
||||
Left << SndOutVolumeShift,
|
||||
Right << SndOutVolumeShift);
|
||||
}
|
||||
|
||||
|
||||
class NullOutModule: public SndOutModule
|
||||
class NullOutModule : public SndOutModule
|
||||
{
|
||||
public:
|
||||
s32 Init() { return 0; }
|
||||
void Close() { }
|
||||
s32 Test() const { return 0; }
|
||||
void Configure(uptr parent) { }
|
||||
int GetEmptySampleCount() { return 0; }
|
||||
s32 Init() { return 0; }
|
||||
void Close() {}
|
||||
s32 Test() const { return 0; }
|
||||
void Configure(uptr parent) {}
|
||||
int GetEmptySampleCount() { return 0; }
|
||||
|
||||
const wchar_t* GetIdent() const
|
||||
{
|
||||
return L"nullout";
|
||||
}
|
||||
const wchar_t *GetIdent() const
|
||||
{
|
||||
return L"nullout";
|
||||
}
|
||||
|
||||
const wchar_t* GetLongName() const
|
||||
{
|
||||
return L"No Sound (Emulate SPU2 only)";
|
||||
}
|
||||
const wchar_t *GetLongName() const
|
||||
{
|
||||
return L"No Sound (Emulate SPU2 only)";
|
||||
}
|
||||
|
||||
void ReadSettings()
|
||||
{
|
||||
}
|
||||
void ReadSettings()
|
||||
{
|
||||
}
|
||||
|
||||
void SetApiSettings(wxString api)
|
||||
{
|
||||
}
|
||||
void SetApiSettings(wxString api)
|
||||
{
|
||||
}
|
||||
|
||||
void WriteSettings() const
|
||||
{
|
||||
}
|
||||
void WriteSettings() const
|
||||
{
|
||||
}
|
||||
|
||||
} NullOut;
|
||||
|
||||
SndOutModule* mods[]=
|
||||
{
|
||||
&NullOut,
|
||||
SndOutModule *mods[] =
|
||||
{
|
||||
&NullOut,
|
||||
#ifdef _MSC_VER
|
||||
XAudio2_27_Out,
|
||||
DSoundOut,
|
||||
WaveOut,
|
||||
XAudio2_27_Out,
|
||||
DSoundOut,
|
||||
WaveOut,
|
||||
#endif
|
||||
PortaudioOut,
|
||||
PortaudioOut,
|
||||
#if defined(SPU2X_SDL) || defined(SPU2X_SDL2)
|
||||
SDLOut,
|
||||
SDLOut,
|
||||
#endif
|
||||
#if defined(__linux__) /* && defined(__ALSA__)*/
|
||||
AlsaOut,
|
||||
AlsaOut,
|
||||
#endif
|
||||
NULL // signals the end of our list
|
||||
NULL // signals the end of our list
|
||||
};
|
||||
|
||||
int FindOutputModuleById( const wchar_t* omodid )
|
||||
int FindOutputModuleById(const wchar_t *omodid)
|
||||
{
|
||||
int modcnt = 0;
|
||||
while( mods[modcnt] != NULL )
|
||||
{
|
||||
if( wcscmp( mods[modcnt]->GetIdent(), omodid ) == 0 )
|
||||
break;
|
||||
++modcnt;
|
||||
}
|
||||
return modcnt;
|
||||
int modcnt = 0;
|
||||
while (mods[modcnt] != NULL) {
|
||||
if (wcscmp(mods[modcnt]->GetIdent(), omodid) == 0)
|
||||
break;
|
||||
++modcnt;
|
||||
}
|
||||
return modcnt;
|
||||
}
|
||||
|
||||
StereoOut32 *SndBuffer::m_buffer;
|
||||
|
@ -119,229 +115,215 @@ __aligned(4) volatile s32 SndBuffer::m_rpos;
|
|||
__aligned(4) volatile s32 SndBuffer::m_wpos;
|
||||
|
||||
bool SndBuffer::m_underrun_freeze;
|
||||
StereoOut32* SndBuffer::sndTempBuffer = NULL;
|
||||
StereoOut16* SndBuffer::sndTempBuffer16 = NULL;
|
||||
StereoOut32 *SndBuffer::sndTempBuffer = NULL;
|
||||
StereoOut16 *SndBuffer::sndTempBuffer16 = NULL;
|
||||
int SndBuffer::sndTempProgress = 0;
|
||||
|
||||
int GetAlignedBufferSize( int comp )
|
||||
int GetAlignedBufferSize(int comp)
|
||||
{
|
||||
return (comp + SndOutPacketSize-1) & ~(SndOutPacketSize-1);
|
||||
return (comp + SndOutPacketSize - 1) & ~(SndOutPacketSize - 1);
|
||||
}
|
||||
|
||||
// Returns TRUE if there is data to be output, or false if no data
|
||||
// is available to be copied.
|
||||
bool SndBuffer::CheckUnderrunStatus( int& nSamples, int& quietSampleCount )
|
||||
bool SndBuffer::CheckUnderrunStatus(int &nSamples, int &quietSampleCount)
|
||||
{
|
||||
quietSampleCount = 0;
|
||||
quietSampleCount = 0;
|
||||
|
||||
int data = _GetApproximateDataInBuffer();
|
||||
if( m_underrun_freeze )
|
||||
{
|
||||
int toFill = m_size / ( (SynchMode == 2) ? 32 : 400); // TimeStretch and Async off?
|
||||
toFill = GetAlignedBufferSize( toFill );
|
||||
int data = _GetApproximateDataInBuffer();
|
||||
if (m_underrun_freeze) {
|
||||
int toFill = m_size / ((SynchMode == 2) ? 32 : 400); // TimeStretch and Async off?
|
||||
toFill = GetAlignedBufferSize(toFill);
|
||||
|
||||
// toFill is now aligned to a SndOutPacket
|
||||
// toFill is now aligned to a SndOutPacket
|
||||
|
||||
if( data < toFill )
|
||||
{
|
||||
quietSampleCount = nSamples;
|
||||
return false;
|
||||
}
|
||||
if (data < toFill) {
|
||||
quietSampleCount = nSamples;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_underrun_freeze = false;
|
||||
if( MsgOverruns() )
|
||||
ConLog(" * SPU2 > Underrun compensation (%d packets buffered)\n", toFill / SndOutPacketSize );
|
||||
lastPct = 0.0; // normalize timestretcher
|
||||
}
|
||||
else if( data < nSamples )
|
||||
{
|
||||
nSamples = data;
|
||||
quietSampleCount = SndOutPacketSize - data;
|
||||
m_underrun_freeze = true;
|
||||
m_underrun_freeze = false;
|
||||
if (MsgOverruns())
|
||||
ConLog(" * SPU2 > Underrun compensation (%d packets buffered)\n", toFill / SndOutPacketSize);
|
||||
lastPct = 0.0; // normalize timestretcher
|
||||
} else if (data < nSamples) {
|
||||
nSamples = data;
|
||||
quietSampleCount = SndOutPacketSize - data;
|
||||
m_underrun_freeze = true;
|
||||
|
||||
if( SynchMode == 0 ) // TimeStrech on
|
||||
timeStretchUnderrun();
|
||||
if (SynchMode == 0) // TimeStrech on
|
||||
timeStretchUnderrun();
|
||||
|
||||
return nSamples != 0;
|
||||
}
|
||||
return nSamples != 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void SndBuffer::_InitFail()
|
||||
{
|
||||
// If a failure occurs, just initialize the NoSound driver. This'll allow
|
||||
// the game to emulate properly (hopefully), albeit without sound.
|
||||
OutputModule = FindOutputModuleById( NullOut.GetIdent() );
|
||||
mods[OutputModule]->Init();
|
||||
// If a failure occurs, just initialize the NoSound driver. This'll allow
|
||||
// the game to emulate properly (hopefully), albeit without sound.
|
||||
OutputModule = FindOutputModuleById(NullOut.GetIdent());
|
||||
mods[OutputModule]->Init();
|
||||
}
|
||||
|
||||
int SndBuffer::_GetApproximateDataInBuffer()
|
||||
{
|
||||
// WARNING: not necessarily 100% up to date by the time it's used, but it will have to do.
|
||||
return (m_wpos + m_size - m_rpos) % m_size;
|
||||
// WARNING: not necessarily 100% up to date by the time it's used, but it will have to do.
|
||||
return (m_wpos + m_size - m_rpos) % m_size;
|
||||
}
|
||||
|
||||
void SndBuffer::_WriteSamples_Internal(StereoOut32 *bData, int nSamples)
|
||||
{
|
||||
// WARNING: This assumes the write will NOT wrap around,
|
||||
// and also assumes there's enough free space in the buffer.
|
||||
// WARNING: This assumes the write will NOT wrap around,
|
||||
// and also assumes there's enough free space in the buffer.
|
||||
|
||||
memcpy(m_buffer + m_wpos, bData, nSamples * sizeof(StereoOut32));
|
||||
m_wpos = (m_wpos + nSamples) % m_size;
|
||||
memcpy(m_buffer + m_wpos, bData, nSamples * sizeof(StereoOut32));
|
||||
m_wpos = (m_wpos + nSamples) % m_size;
|
||||
}
|
||||
|
||||
void SndBuffer::_DropSamples_Internal(int nSamples)
|
||||
{
|
||||
m_rpos = (m_rpos + nSamples) % m_size;
|
||||
m_rpos = (m_rpos + nSamples) % m_size;
|
||||
}
|
||||
|
||||
void SndBuffer::_ReadSamples_Internal(StereoOut32 *bData, int nSamples)
|
||||
{
|
||||
// WARNING: This assumes the read will NOT wrap around,
|
||||
// and also assumes there's enough data in the buffer.
|
||||
memcpy(bData, m_buffer + m_rpos, nSamples * sizeof(StereoOut32));
|
||||
_DropSamples_Internal(nSamples);
|
||||
// WARNING: This assumes the read will NOT wrap around,
|
||||
// and also assumes there's enough data in the buffer.
|
||||
memcpy(bData, m_buffer + m_rpos, nSamples * sizeof(StereoOut32));
|
||||
_DropSamples_Internal(nSamples);
|
||||
}
|
||||
|
||||
void SndBuffer::_WriteSamples_Safe(StereoOut32 *bData, int nSamples)
|
||||
{
|
||||
// WARNING: This code assumes there's only ONE writing process.
|
||||
if( (m_size - m_wpos) < nSamples)
|
||||
{
|
||||
int b1 = m_size - m_wpos;
|
||||
int b2 = nSamples - b1;
|
||||
// WARNING: This code assumes there's only ONE writing process.
|
||||
if ((m_size - m_wpos) < nSamples) {
|
||||
int b1 = m_size - m_wpos;
|
||||
int b2 = nSamples - b1;
|
||||
|
||||
_WriteSamples_Internal(bData, b1);
|
||||
_WriteSamples_Internal(bData+b1, b2);
|
||||
}
|
||||
else
|
||||
{
|
||||
_WriteSamples_Internal(bData, nSamples);
|
||||
}
|
||||
_WriteSamples_Internal(bData, b1);
|
||||
_WriteSamples_Internal(bData + b1, b2);
|
||||
} else {
|
||||
_WriteSamples_Internal(bData, nSamples);
|
||||
}
|
||||
}
|
||||
|
||||
void SndBuffer::_ReadSamples_Safe(StereoOut32* bData, int nSamples)
|
||||
void SndBuffer::_ReadSamples_Safe(StereoOut32 *bData, int nSamples)
|
||||
{
|
||||
// WARNING: This code assumes there's only ONE reading process.
|
||||
if( (m_size - m_rpos) < nSamples)
|
||||
{
|
||||
int b1 = m_size - m_rpos;
|
||||
int b2 = nSamples - b1;
|
||||
// WARNING: This code assumes there's only ONE reading process.
|
||||
if ((m_size - m_rpos) < nSamples) {
|
||||
int b1 = m_size - m_rpos;
|
||||
int b2 = nSamples - b1;
|
||||
|
||||
_ReadSamples_Internal(bData, b1);
|
||||
_ReadSamples_Internal(bData+b1, b2);
|
||||
}
|
||||
else
|
||||
{
|
||||
_ReadSamples_Internal(bData, nSamples);
|
||||
}
|
||||
_ReadSamples_Internal(bData, b1);
|
||||
_ReadSamples_Internal(bData + b1, b2);
|
||||
} else {
|
||||
_ReadSamples_Internal(bData, nSamples);
|
||||
}
|
||||
}
|
||||
|
||||
// Note: When using with 32 bit output buffers, the user of this function is responsible
|
||||
// for shifting the values to where they need to be manually. The fixed point depth of
|
||||
// the sample output is determined by the SndOutVolumeShift, which is the number of bits
|
||||
// to shift right to get a 16 bit result.
|
||||
template<typename T> void SndBuffer::ReadSamples(T* bData)
|
||||
template <typename T>
|
||||
void SndBuffer::ReadSamples(T *bData)
|
||||
{
|
||||
int nSamples = SndOutPacketSize;
|
||||
int nSamples = SndOutPacketSize;
|
||||
|
||||
// Problem:
|
||||
// If the SPU2 gets even the least bit out of sync with the SndOut device,
|
||||
// the readpos of the circular buffer will overtake the writepos,
|
||||
// leading to a prolonged period of hopscotching read/write accesses (ie,
|
||||
// lots of staticy crap sound for several seconds).
|
||||
//
|
||||
// Fix:
|
||||
// If the read position overtakes the write position, abort the
|
||||
// transfer immediately and force the SndOut driver to wait until
|
||||
// the read buffer has filled up again before proceeding.
|
||||
// This will cause one brief hiccup that can never exceed the user's
|
||||
// set buffer length in duration.
|
||||
// Problem:
|
||||
// If the SPU2 gets even the least bit out of sync with the SndOut device,
|
||||
// the readpos of the circular buffer will overtake the writepos,
|
||||
// leading to a prolonged period of hopscotching read/write accesses (ie,
|
||||
// lots of staticy crap sound for several seconds).
|
||||
//
|
||||
// Fix:
|
||||
// If the read position overtakes the write position, abort the
|
||||
// transfer immediately and force the SndOut driver to wait until
|
||||
// the read buffer has filled up again before proceeding.
|
||||
// This will cause one brief hiccup that can never exceed the user's
|
||||
// set buffer length in duration.
|
||||
|
||||
int quietSamples;
|
||||
if( CheckUnderrunStatus( nSamples, quietSamples ) )
|
||||
{
|
||||
pxAssume( nSamples <= SndOutPacketSize );
|
||||
int quietSamples;
|
||||
if (CheckUnderrunStatus(nSamples, quietSamples)) {
|
||||
pxAssume(nSamples <= SndOutPacketSize);
|
||||
|
||||
// WARNING: This code assumes there's only ONE reading process.
|
||||
int b1 = m_size - m_rpos;
|
||||
// WARNING: This code assumes there's only ONE reading process.
|
||||
int b1 = m_size - m_rpos;
|
||||
|
||||
if(b1 > nSamples)
|
||||
b1 = nSamples;
|
||||
if (b1 > nSamples)
|
||||
b1 = nSamples;
|
||||
|
||||
if (AdvancedVolumeControl)
|
||||
{
|
||||
// First part
|
||||
for (int i = 0; i < b1; i++)
|
||||
bData[i].AdjustFrom(m_buffer[i + m_rpos]);
|
||||
if (AdvancedVolumeControl) {
|
||||
// First part
|
||||
for (int i = 0; i < b1; i++)
|
||||
bData[i].AdjustFrom(m_buffer[i + m_rpos]);
|
||||
|
||||
// Second part
|
||||
int b2 = nSamples - b1;
|
||||
for (int i = 0; i < b2; i++)
|
||||
bData[i + b1].AdjustFrom(m_buffer[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// First part
|
||||
for (int i = 0; i < b1; i++)
|
||||
bData[i].ResampleFrom(m_buffer[i + m_rpos]);
|
||||
// Second part
|
||||
int b2 = nSamples - b1;
|
||||
for (int i = 0; i < b2; i++)
|
||||
bData[i + b1].AdjustFrom(m_buffer[i]);
|
||||
} else {
|
||||
// First part
|
||||
for (int i = 0; i < b1; i++)
|
||||
bData[i].ResampleFrom(m_buffer[i + m_rpos]);
|
||||
|
||||
// Second part
|
||||
int b2 = nSamples - b1;
|
||||
for (int i = 0; i < b2; i++)
|
||||
bData[i + b1].ResampleFrom(m_buffer[i]);
|
||||
}
|
||||
// Second part
|
||||
int b2 = nSamples - b1;
|
||||
for (int i = 0; i < b2; i++)
|
||||
bData[i + b1].ResampleFrom(m_buffer[i]);
|
||||
}
|
||||
|
||||
_DropSamples_Internal(nSamples);
|
||||
}
|
||||
_DropSamples_Internal(nSamples);
|
||||
}
|
||||
|
||||
// If quietSamples != 0 it means we have an underrun...
|
||||
// Let's just dull out some silence, because that's usually the least
|
||||
// painful way of dealing with underruns:
|
||||
memset( bData, 0, quietSamples * sizeof(T) );
|
||||
// If quietSamples != 0 it means we have an underrun...
|
||||
// Let's just dull out some silence, because that's usually the least
|
||||
// painful way of dealing with underruns:
|
||||
memset(bData, 0, quietSamples * sizeof(T));
|
||||
}
|
||||
|
||||
template void SndBuffer::ReadSamples(StereoOut16*);
|
||||
template void SndBuffer::ReadSamples(StereoOut32*);
|
||||
template void SndBuffer::ReadSamples(StereoOut16 *);
|
||||
template void SndBuffer::ReadSamples(StereoOut32 *);
|
||||
|
||||
//template void SndBuffer::ReadSamples(StereoOutFloat*);
|
||||
template void SndBuffer::ReadSamples(Stereo21Out16*);
|
||||
template void SndBuffer::ReadSamples(Stereo40Out16*);
|
||||
template void SndBuffer::ReadSamples(Stereo41Out16*);
|
||||
template void SndBuffer::ReadSamples(Stereo51Out16*);
|
||||
template void SndBuffer::ReadSamples(Stereo51Out16Dpl*);
|
||||
template void SndBuffer::ReadSamples(Stereo51Out16DplII*);
|
||||
template void SndBuffer::ReadSamples(Stereo71Out16*);
|
||||
template void SndBuffer::ReadSamples(Stereo21Out16 *);
|
||||
template void SndBuffer::ReadSamples(Stereo40Out16 *);
|
||||
template void SndBuffer::ReadSamples(Stereo41Out16 *);
|
||||
template void SndBuffer::ReadSamples(Stereo51Out16 *);
|
||||
template void SndBuffer::ReadSamples(Stereo51Out16Dpl *);
|
||||
template void SndBuffer::ReadSamples(Stereo51Out16DplII *);
|
||||
template void SndBuffer::ReadSamples(Stereo71Out16 *);
|
||||
|
||||
template void SndBuffer::ReadSamples(Stereo20Out32*);
|
||||
template void SndBuffer::ReadSamples(Stereo21Out32*);
|
||||
template void SndBuffer::ReadSamples(Stereo40Out32*);
|
||||
template void SndBuffer::ReadSamples(Stereo41Out32*);
|
||||
template void SndBuffer::ReadSamples(Stereo51Out32*);
|
||||
template void SndBuffer::ReadSamples(Stereo51Out32Dpl*);
|
||||
template void SndBuffer::ReadSamples(Stereo51Out32DplII*);
|
||||
template void SndBuffer::ReadSamples(Stereo71Out32*);
|
||||
template void SndBuffer::ReadSamples(Stereo20Out32 *);
|
||||
template void SndBuffer::ReadSamples(Stereo21Out32 *);
|
||||
template void SndBuffer::ReadSamples(Stereo40Out32 *);
|
||||
template void SndBuffer::ReadSamples(Stereo41Out32 *);
|
||||
template void SndBuffer::ReadSamples(Stereo51Out32 *);
|
||||
template void SndBuffer::ReadSamples(Stereo51Out32Dpl *);
|
||||
template void SndBuffer::ReadSamples(Stereo51Out32DplII *);
|
||||
template void SndBuffer::ReadSamples(Stereo71Out32 *);
|
||||
|
||||
void SndBuffer::_WriteSamples(StereoOut32 *bData, int nSamples)
|
||||
{
|
||||
m_predictData = 0;
|
||||
m_predictData = 0;
|
||||
|
||||
// Problem:
|
||||
// If the SPU2 gets out of sync with the SndOut device, the writepos of the
|
||||
// circular buffer will overtake the readpos, leading to a prolonged period
|
||||
// of hopscotching read/write accesses (ie, lots of staticy crap sound for
|
||||
// several seconds).
|
||||
//
|
||||
// Compromise:
|
||||
// When an overrun occurs, we adapt by discarding a portion of the buffer.
|
||||
// The older portion of the buffer is discarded rather than incoming data,
|
||||
// so that the overall audio synchronization is better.
|
||||
// Problem:
|
||||
// If the SPU2 gets out of sync with the SndOut device, the writepos of the
|
||||
// circular buffer will overtake the readpos, leading to a prolonged period
|
||||
// of hopscotching read/write accesses (ie, lots of staticy crap sound for
|
||||
// several seconds).
|
||||
//
|
||||
// Compromise:
|
||||
// When an overrun occurs, we adapt by discarding a portion of the buffer.
|
||||
// The older portion of the buffer is discarded rather than incoming data,
|
||||
// so that the overall audio synchronization is better.
|
||||
|
||||
int free = m_size - _GetApproximateDataInBuffer(); // -1, but the <= handles that
|
||||
if( free <= nSamples )
|
||||
{
|
||||
// Disabled since the lock-free queue can't handle changing the read end from the write thread
|
||||
int free = m_size - _GetApproximateDataInBuffer(); // -1, but the <= handles that
|
||||
if (free <= nSamples) {
|
||||
// Disabled since the lock-free queue can't handle changing the read end from the write thread
|
||||
#if 0
|
||||
// Buffer overrun!
|
||||
// Dump samples from the read portion of the buffer instead of dropping
|
||||
|
@ -366,72 +348,69 @@ void SndBuffer::_WriteSamples(StereoOut32 *bData, int nSamples)
|
|||
ConLog(" * SPU2 > Overrun Compensation (%d packets tossed)\n", comp / SndOutPacketSize );
|
||||
lastPct = 0.0; // normalize the timestretcher
|
||||
#else
|
||||
if( MsgOverruns() )
|
||||
ConLog(" * SPU2 > Overrun! 1 packet tossed)\n");
|
||||
lastPct = 0.0; // normalize the timestretcher
|
||||
return;
|
||||
if (MsgOverruns())
|
||||
ConLog(" * SPU2 > Overrun! 1 packet tossed)\n");
|
||||
lastPct = 0.0; // normalize the timestretcher
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
_WriteSamples_Safe(bData, nSamples);
|
||||
_WriteSamples_Safe(bData, nSamples);
|
||||
}
|
||||
|
||||
void SndBuffer::Init()
|
||||
{
|
||||
if( mods[OutputModule] == NULL )
|
||||
{
|
||||
_InitFail();
|
||||
return;
|
||||
}
|
||||
if (mods[OutputModule] == NULL) {
|
||||
_InitFail();
|
||||
return;
|
||||
}
|
||||
|
||||
// initialize sound buffer
|
||||
// Buffer actually attempts to run ~50%, so allocate near double what
|
||||
// the requested latency is:
|
||||
|
||||
m_rpos = 0;
|
||||
m_wpos = 0;
|
||||
// initialize sound buffer
|
||||
// Buffer actually attempts to run ~50%, so allocate near double what
|
||||
// the requested latency is:
|
||||
|
||||
try
|
||||
{
|
||||
const float latencyMS = SndOutLatencyMS * 16;
|
||||
m_size = GetAlignedBufferSize( (int)(latencyMS * SampleRate / 1000.0f ) );
|
||||
m_buffer = new StereoOut32[m_size];
|
||||
m_underrun_freeze = false;
|
||||
m_rpos = 0;
|
||||
m_wpos = 0;
|
||||
|
||||
sndTempBuffer = new StereoOut32[SndOutPacketSize];
|
||||
sndTempBuffer16 = new StereoOut16[SndOutPacketSize * 2]; // in case of leftovers.
|
||||
}
|
||||
catch( std::bad_alloc& )
|
||||
{
|
||||
// out of memory exception (most likely)
|
||||
try {
|
||||
const float latencyMS = SndOutLatencyMS * 16;
|
||||
m_size = GetAlignedBufferSize((int)(latencyMS * SampleRate / 1000.0f));
|
||||
m_buffer = new StereoOut32[m_size];
|
||||
m_underrun_freeze = false;
|
||||
|
||||
SysMessage( "Out of memory error occurred while initializing SPU2." );
|
||||
_InitFail();
|
||||
return;
|
||||
}
|
||||
sndTempBuffer = new StereoOut32[SndOutPacketSize];
|
||||
sndTempBuffer16 = new StereoOut16[SndOutPacketSize * 2]; // in case of leftovers.
|
||||
} catch (std::bad_alloc &) {
|
||||
// out of memory exception (most likely)
|
||||
|
||||
// clear buffers!
|
||||
// Fixes loopy sounds on emu resets.
|
||||
memset( sndTempBuffer, 0, sizeof(StereoOut32) * SndOutPacketSize );
|
||||
memset( sndTempBuffer16, 0, sizeof(StereoOut16) * SndOutPacketSize );
|
||||
SysMessage("Out of memory error occurred while initializing SPU2.");
|
||||
_InitFail();
|
||||
return;
|
||||
}
|
||||
|
||||
sndTempProgress = 0;
|
||||
// clear buffers!
|
||||
// Fixes loopy sounds on emu resets.
|
||||
memset(sndTempBuffer, 0, sizeof(StereoOut32) * SndOutPacketSize);
|
||||
memset(sndTempBuffer16, 0, sizeof(StereoOut16) * SndOutPacketSize);
|
||||
|
||||
soundtouchInit(); // initializes the timestretching
|
||||
sndTempProgress = 0;
|
||||
|
||||
// initialize module
|
||||
if( mods[OutputModule]->Init() == -1 ) _InitFail();
|
||||
soundtouchInit(); // initializes the timestretching
|
||||
|
||||
// initialize module
|
||||
if (mods[OutputModule]->Init() == -1)
|
||||
_InitFail();
|
||||
}
|
||||
|
||||
void SndBuffer::Cleanup()
|
||||
{
|
||||
mods[OutputModule]->Close();
|
||||
mods[OutputModule]->Close();
|
||||
|
||||
soundtouchCleanup();
|
||||
soundtouchCleanup();
|
||||
|
||||
safe_delete_array( m_buffer );
|
||||
safe_delete_array( sndTempBuffer );
|
||||
safe_delete_array( sndTempBuffer16 );
|
||||
safe_delete_array(m_buffer);
|
||||
safe_delete_array(sndTempBuffer);
|
||||
safe_delete_array(sndTempBuffer16);
|
||||
}
|
||||
|
||||
int SndBuffer::m_dsp_progress = 0;
|
||||
|
@ -441,77 +420,77 @@ int SndBuffer::ssFreeze = 0;
|
|||
|
||||
void SndBuffer::ClearContents()
|
||||
{
|
||||
SndBuffer::soundtouchClearContents();
|
||||
SndBuffer::ssFreeze = 256; //Delays sound output for about 1 second.
|
||||
SndBuffer::soundtouchClearContents();
|
||||
SndBuffer::ssFreeze = 256; //Delays sound output for about 1 second.
|
||||
}
|
||||
|
||||
void SndBuffer::Write( const StereoOut32& Sample )
|
||||
void SndBuffer::Write(const StereoOut32 &Sample)
|
||||
{
|
||||
// Log final output to wavefile.
|
||||
WaveDump::WriteCore( 1, CoreSrc_External, Sample.DownSample() );
|
||||
// Log final output to wavefile.
|
||||
WaveDump::WriteCore(1, CoreSrc_External, Sample.DownSample());
|
||||
|
||||
if( WavRecordEnabled ) RecordWrite( Sample.DownSample() );
|
||||
if (WavRecordEnabled)
|
||||
RecordWrite(Sample.DownSample());
|
||||
|
||||
if(mods[OutputModule] == &NullOut) // null output doesn't need buffering or stretching! :p
|
||||
return;
|
||||
if (mods[OutputModule] == &NullOut) // null output doesn't need buffering or stretching! :p
|
||||
return;
|
||||
|
||||
sndTempBuffer[sndTempProgress++] = Sample;
|
||||
sndTempBuffer[sndTempProgress++] = Sample;
|
||||
|
||||
// If we haven't accumulated a full packet yet, do nothing more:
|
||||
if(sndTempProgress < SndOutPacketSize) return;
|
||||
sndTempProgress = 0;
|
||||
// If we haven't accumulated a full packet yet, do nothing more:
|
||||
if (sndTempProgress < SndOutPacketSize)
|
||||
return;
|
||||
sndTempProgress = 0;
|
||||
|
||||
//Don't play anything directly after loading a savestate, avoids static killing your speakers.
|
||||
if ( ssFreeze > 0 )
|
||||
{
|
||||
ssFreeze--;
|
||||
memset( sndTempBuffer, 0, sizeof(StereoOut32) * SndOutPacketSize ); // Play silence
|
||||
}
|
||||
//Don't play anything directly after loading a savestate, avoids static killing your speakers.
|
||||
if (ssFreeze > 0) {
|
||||
ssFreeze--;
|
||||
memset(sndTempBuffer, 0, sizeof(StereoOut32) * SndOutPacketSize); // Play silence
|
||||
}
|
||||
#ifndef __POSIX__
|
||||
if( dspPluginEnabled )
|
||||
{
|
||||
// Convert in, send to winamp DSP, and convert out.
|
||||
if (dspPluginEnabled) {
|
||||
// Convert in, send to winamp DSP, and convert out.
|
||||
|
||||
int ei= m_dsp_progress;
|
||||
for( int i=0; i<SndOutPacketSize; ++i, ++ei ) { sndTempBuffer16[ei] = sndTempBuffer[i].DownSample(); }
|
||||
m_dsp_progress += DspProcess( (s16*)sndTempBuffer16 + m_dsp_progress, SndOutPacketSize );
|
||||
int ei = m_dsp_progress;
|
||||
for (int i = 0; i < SndOutPacketSize; ++i, ++ei) {
|
||||
sndTempBuffer16[ei] = sndTempBuffer[i].DownSample();
|
||||
}
|
||||
m_dsp_progress += DspProcess((s16 *)sndTempBuffer16 + m_dsp_progress, SndOutPacketSize);
|
||||
|
||||
// Some ugly code to ensure full packet handling:
|
||||
ei = 0;
|
||||
while( m_dsp_progress >= SndOutPacketSize )
|
||||
{
|
||||
for( int i=0; i<SndOutPacketSize; ++i, ++ei ) { sndTempBuffer[i] = sndTempBuffer16[ei].UpSample(); }
|
||||
// Some ugly code to ensure full packet handling:
|
||||
ei = 0;
|
||||
while (m_dsp_progress >= SndOutPacketSize) {
|
||||
for (int i = 0; i < SndOutPacketSize; ++i, ++ei) {
|
||||
sndTempBuffer[i] = sndTempBuffer16[ei].UpSample();
|
||||
}
|
||||
|
||||
if( SynchMode == 0 ) // TimeStrech on
|
||||
timeStretchWrite();
|
||||
else
|
||||
_WriteSamples(sndTempBuffer, SndOutPacketSize);
|
||||
if (SynchMode == 0) // TimeStrech on
|
||||
timeStretchWrite();
|
||||
else
|
||||
_WriteSamples(sndTempBuffer, SndOutPacketSize);
|
||||
|
||||
m_dsp_progress -= SndOutPacketSize;
|
||||
}
|
||||
m_dsp_progress -= SndOutPacketSize;
|
||||
}
|
||||
|
||||
// copy any leftovers to the front of the dsp buffer.
|
||||
if( m_dsp_progress > 0 )
|
||||
{
|
||||
memcpy( sndTempBuffer16, &sndTempBuffer16[ei],
|
||||
sizeof(sndTempBuffer16[0]) * m_dsp_progress
|
||||
);
|
||||
}
|
||||
}
|
||||
// copy any leftovers to the front of the dsp buffer.
|
||||
if (m_dsp_progress > 0) {
|
||||
memcpy(sndTempBuffer16, &sndTempBuffer16[ei],
|
||||
sizeof(sndTempBuffer16[0]) * m_dsp_progress);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
if( SynchMode == 0 ) // TimeStrech on
|
||||
timeStretchWrite();
|
||||
else
|
||||
_WriteSamples(sndTempBuffer, SndOutPacketSize);
|
||||
}
|
||||
else {
|
||||
if (SynchMode == 0) // TimeStrech on
|
||||
timeStretchWrite();
|
||||
else
|
||||
_WriteSamples(sndTempBuffer, SndOutPacketSize);
|
||||
}
|
||||
}
|
||||
|
||||
s32 SndBuffer::Test()
|
||||
{
|
||||
if( mods[OutputModule] == NULL )
|
||||
return -1;
|
||||
if (mods[OutputModule] == NULL)
|
||||
return -1;
|
||||
|
||||
return mods[OutputModule]->Test();
|
||||
return mods[OutputModule]->Test();
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -29,152 +29,161 @@
|
|||
#include <SDL_audio.h>
|
||||
typedef StereoOut16 StereoOut_SDL;
|
||||
|
||||
namespace {
|
||||
/* Since spu2 only ever outputs stereo, we don't worry about emitting surround sound
|
||||
namespace
|
||||
{
|
||||
/* Since spu2 only ever outputs stereo, we don't worry about emitting surround sound
|
||||
* even though SDL2 supports it */
|
||||
const Uint8 channels = 2;
|
||||
/* SDL2 supports s32 audio */
|
||||
/* Samples should vary from [512,8192] according to SDL spec. Take note this is the desired
|
||||
const Uint8 channels = 2;
|
||||
/* SDL2 supports s32 audio */
|
||||
/* Samples should vary from [512,8192] according to SDL spec. Take note this is the desired
|
||||
* sample count and SDL may provide otherwise. Pulseaudio will cut this value in half if
|
||||
* PA_STREAM_ADJUST_LATENCY is set in the backened, for example. */
|
||||
const Uint16 desiredSamples = 2048;
|
||||
const Uint16 format = AUDIO_S16SYS;
|
||||
const Uint16 desiredSamples = 2048;
|
||||
const Uint16 format = AUDIO_S16SYS;
|
||||
|
||||
Uint16 samples = desiredSamples;
|
||||
Uint16 samples = desiredSamples;
|
||||
|
||||
std::unique_ptr<StereoOut_SDL[]> buffer;
|
||||
std::unique_ptr<StereoOut_SDL[]> buffer;
|
||||
|
||||
void callback_fillBuffer(void *userdata, Uint8 *stream, int len) {
|
||||
Uint16 sdl_samples = samples;
|
||||
void callback_fillBuffer(void *userdata, Uint8 *stream, int len)
|
||||
{
|
||||
Uint16 sdl_samples = samples;
|
||||
|
||||
#if SDL_MAJOR_VERSION >= 2
|
||||
memset(stream, 0, len);
|
||||
// As of SDL 2.0.4 the buffer is too small to contains all samples
|
||||
// len is 2048, samples is 1024 and sizeof(StereoOut_SDL) is 4
|
||||
sdl_samples = len / sizeof(StereoOut_SDL);
|
||||
memset(stream, 0, len);
|
||||
// As of SDL 2.0.4 the buffer is too small to contains all samples
|
||||
// len is 2048, samples is 1024 and sizeof(StereoOut_SDL) is 4
|
||||
sdl_samples = len / sizeof(StereoOut_SDL);
|
||||
#endif
|
||||
|
||||
// Length should always be samples in bytes.
|
||||
assert(len / sizeof(StereoOut_SDL) == sdl_samples);
|
||||
// Length should always be samples in bytes.
|
||||
assert(len / sizeof(StereoOut_SDL) == sdl_samples);
|
||||
|
||||
for(Uint16 i = 0; i < sdl_samples; i += SndOutPacketSize)
|
||||
SndBuffer::ReadSamples(&buffer[i]);
|
||||
SDL_MixAudio(stream, (Uint8*) buffer.get() , len, SDL_MIX_MAXVOLUME);
|
||||
}
|
||||
for (Uint16 i = 0; i < sdl_samples; i += SndOutPacketSize)
|
||||
SndBuffer::ReadSamples(&buffer[i]);
|
||||
SDL_MixAudio(stream, (Uint8 *)buffer.get(), len, SDL_MIX_MAXVOLUME);
|
||||
}
|
||||
}
|
||||
|
||||
struct SDLAudioMod : public SndOutModule {
|
||||
static SDLAudioMod mod;
|
||||
std::string m_api;
|
||||
struct SDLAudioMod : public SndOutModule
|
||||
{
|
||||
static SDLAudioMod mod;
|
||||
std::string m_api;
|
||||
|
||||
s32 Init() {
|
||||
ReadSettings();
|
||||
s32 Init()
|
||||
{
|
||||
ReadSettings();
|
||||
|
||||
#if SDL_MAJOR_VERSION >= 2
|
||||
std::cerr << "Request SDL audio driver: " << m_api.c_str() << std::endl;
|
||||
std::cerr << "Request SDL audio driver: " << m_api.c_str() << std::endl;
|
||||
#endif
|
||||
|
||||
/* SDL backends will mangle the AudioSpec and change the sample count. If we reopen
|
||||
/* SDL backends will mangle the AudioSpec and change the sample count. If we reopen
|
||||
* the audio backend, we need to make sure we keep our desired samples in the spec */
|
||||
spec.samples = desiredSamples;
|
||||
spec.samples = desiredSamples;
|
||||
|
||||
// Mandatory otherwise, init will be redone in SDL_OpenAudio
|
||||
if (SDL_Init(SDL_INIT_AUDIO) < 0) {
|
||||
std::cerr << "SPU2-X: SDL INIT audio error: " << SDL_GetError() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
// Mandatory otherwise, init will be redone in SDL_OpenAudio
|
||||
if (SDL_Init(SDL_INIT_AUDIO) < 0) {
|
||||
std::cerr << "SPU2-X: SDL INIT audio error: " << SDL_GetError() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if SDL_MAJOR_VERSION >= 2
|
||||
if (m_api.compare("pulseaudio")) {
|
||||
// Close the audio, but keep the subsystem open
|
||||
SDL_AudioQuit();
|
||||
// Reopen the audio
|
||||
if (SDL_AudioInit(m_api.c_str()) < 0) {
|
||||
std::cerr << "SPU2-X: SDL audio init error: " << SDL_GetError() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (m_api.compare("pulseaudio")) {
|
||||
// Close the audio, but keep the subsystem open
|
||||
SDL_AudioQuit();
|
||||
// Reopen the audio
|
||||
if (SDL_AudioInit(m_api.c_str()) < 0) {
|
||||
std::cerr << "SPU2-X: SDL audio init error: " << SDL_GetError() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (SDL_OpenAudio(&spec, NULL) < 0) {
|
||||
std::cerr << "SPU2-X: SDL audio error: " << SDL_GetError() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
if (SDL_OpenAudio(&spec, NULL) < 0) {
|
||||
std::cerr << "SPU2-X: SDL audio error: " << SDL_GetError() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if SDL_MAJOR_VERSION >= 2
|
||||
std::cerr << "Opened SDL audio driver: " << SDL_GetCurrentAudioDriver() << std::endl;
|
||||
std::cerr << "Opened SDL audio driver: " << SDL_GetCurrentAudioDriver() << std::endl;
|
||||
#endif
|
||||
|
||||
/* This is so ugly. It is hilariously ugly. I didn't use a vector to save reallocs. */
|
||||
if(samples != spec.samples || buffer == NULL)
|
||||
buffer = std::unique_ptr<StereoOut_SDL[]>(new StereoOut_SDL[spec.samples]);
|
||||
if(samples != spec.samples) {
|
||||
fprintf(stderr, "SPU2-X: SDL failed to get desired samples (%d) got %d samples instead\n", samples, spec.samples);
|
||||
/* This is so ugly. It is hilariously ugly. I didn't use a vector to save reallocs. */
|
||||
if (samples != spec.samples || buffer == NULL)
|
||||
buffer = std::unique_ptr<StereoOut_SDL[]>(new StereoOut_SDL[spec.samples]);
|
||||
if (samples != spec.samples) {
|
||||
fprintf(stderr, "SPU2-X: SDL failed to get desired samples (%d) got %d samples instead\n", samples, spec.samples);
|
||||
|
||||
// Samples must always be a multiple of packet size.
|
||||
assert(spec.samples % SndOutPacketSize == 0);
|
||||
samples = spec.samples;
|
||||
}
|
||||
SDL_PauseAudio(0);
|
||||
return 0;
|
||||
}
|
||||
// Samples must always be a multiple of packet size.
|
||||
assert(spec.samples % SndOutPacketSize == 0);
|
||||
samples = spec.samples;
|
||||
}
|
||||
SDL_PauseAudio(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const wchar_t* GetIdent() const { return L"SDLAudio"; }
|
||||
const wchar_t* GetLongName() const { return L"SDL Audio"; }
|
||||
const wchar_t *GetIdent() const { return L"SDLAudio"; }
|
||||
const wchar_t *GetLongName() const { return L"SDL Audio"; }
|
||||
|
||||
void Close() {
|
||||
// Related to SDL_Init(SDL_INIT_AUDIO)
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
}
|
||||
void Close()
|
||||
{
|
||||
// Related to SDL_Init(SDL_INIT_AUDIO)
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
}
|
||||
|
||||
~SDLAudioMod() { Close(); }
|
||||
~SDLAudioMod() { Close(); }
|
||||
|
||||
s32 Test() const { return 0; }
|
||||
int GetEmptySampleCount() { return 0; }
|
||||
s32 Test() const { return 0; }
|
||||
int GetEmptySampleCount() { return 0; }
|
||||
|
||||
void Configure(uptr parent) {}
|
||||
void Configure(uptr parent) {}
|
||||
|
||||
void ReadSettings() {
|
||||
wxString api(L"EMPTYEMPTYEMPTY");
|
||||
CfgReadStr(L"SDL", L"HostApi", api, L"pulseaudio");
|
||||
SetApiSettings(api);
|
||||
}
|
||||
void ReadSettings()
|
||||
{
|
||||
wxString api(L"EMPTYEMPTYEMPTY");
|
||||
CfgReadStr(L"SDL", L"HostApi", api, L"pulseaudio");
|
||||
SetApiSettings(api);
|
||||
}
|
||||
|
||||
void WriteSettings() const {
|
||||
CfgWriteStr(L"SDL", L"HostApi", wxString(m_api.c_str(), wxConvUTF8));
|
||||
};
|
||||
void WriteSettings() const
|
||||
{
|
||||
CfgWriteStr(L"SDL", L"HostApi", wxString(m_api.c_str(), wxConvUTF8));
|
||||
};
|
||||
|
||||
void SetApiSettings(wxString api) {
|
||||
void SetApiSettings(wxString api)
|
||||
{
|
||||
#if SDL_MAJOR_VERSION >= 2
|
||||
// Validate the api name
|
||||
bool valid = false;
|
||||
std::string api_name = std::string(api.utf8_str());
|
||||
for (int i = 0; i < SDL_GetNumAudioDrivers(); ++i) {
|
||||
valid |= (api_name.compare(SDL_GetAudioDriver(i)) == 0);
|
||||
}
|
||||
if (valid) {
|
||||
m_api = api.utf8_str();
|
||||
} else {
|
||||
std::cerr << "SDL audio driver configuration is invalid!" << std::endl
|
||||
<< "It will be replaced by pulseaudio!" << std::endl;
|
||||
m_api = "pulseaudio";
|
||||
}
|
||||
// Validate the api name
|
||||
bool valid = false;
|
||||
std::string api_name = std::string(api.utf8_str());
|
||||
for (int i = 0; i < SDL_GetNumAudioDrivers(); ++i) {
|
||||
valid |= (api_name.compare(SDL_GetAudioDriver(i)) == 0);
|
||||
}
|
||||
if (valid) {
|
||||
m_api = api.utf8_str();
|
||||
} else {
|
||||
std::cerr << "SDL audio driver configuration is invalid!" << std::endl
|
||||
<< "It will be replaced by pulseaudio!" << std::endl;
|
||||
m_api = "pulseaudio";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
SDL_AudioSpec spec;
|
||||
private:
|
||||
SDL_AudioSpec spec;
|
||||
|
||||
SDLAudioMod() : m_api("pulseaudio"),
|
||||
spec({SampleRate, format, channels, 0,
|
||||
desiredSamples, 0, 0, &callback_fillBuffer, nullptr})
|
||||
{
|
||||
// Number of samples must be a multiple of packet size.
|
||||
assert(samples % SndOutPacketSize == 0);
|
||||
}
|
||||
SDLAudioMod()
|
||||
: m_api("pulseaudio")
|
||||
, spec({SampleRate, format, channels, 0,
|
||||
desiredSamples, 0, 0, &callback_fillBuffer, nullptr})
|
||||
{
|
||||
// Number of samples must be a multiple of packet size.
|
||||
assert(samples % SndOutPacketSize == 0);
|
||||
}
|
||||
};
|
||||
|
||||
SDLAudioMod SDLAudioMod::mod;
|
||||
|
||||
SndOutModule * const SDLOut = &SDLAudioMod::mod;
|
||||
SndOutModule *const SDLOut = &SDLAudioMod::mod;
|
||||
|
|
|
@ -20,73 +20,78 @@
|
|||
#include "PS2E-spu2.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include "Windows.h"
|
||||
#include "Windows.h"
|
||||
#endif
|
||||
|
||||
FILE* s2rfile;
|
||||
FILE *s2rfile;
|
||||
|
||||
void s2r_write16(s16 data)
|
||||
{
|
||||
fwrite(&data,2,1,s2rfile);
|
||||
fwrite(&data, 2, 1, s2rfile);
|
||||
}
|
||||
|
||||
void s2r_write32(u32 data)
|
||||
{
|
||||
fwrite(&data,4,1,s2rfile);
|
||||
fwrite(&data, 4, 1, s2rfile);
|
||||
}
|
||||
|
||||
static void EMITC(u32 i, u32 a)
|
||||
{
|
||||
s2r_write32(((i&0x7u)<<29u)|(a&0x1FFFFFFFu));
|
||||
s2r_write32(((i & 0x7u) << 29u) | (a & 0x1FFFFFFFu));
|
||||
}
|
||||
|
||||
int s2r_open(u32 ticks, char *filename)
|
||||
{
|
||||
s2rfile=fopen(filename,"wb");
|
||||
if(s2rfile)
|
||||
s2r_write32(ticks);
|
||||
return s2rfile?0:-1;
|
||||
s2rfile = fopen(filename, "wb");
|
||||
if (s2rfile)
|
||||
s2r_write32(ticks);
|
||||
return s2rfile ? 0 : -1;
|
||||
}
|
||||
|
||||
void s2r_readreg(u32 ticks,u32 addr)
|
||||
void s2r_readreg(u32 ticks, u32 addr)
|
||||
{
|
||||
if(!s2rfile) return;
|
||||
s2r_write32(ticks);
|
||||
EMITC(0,addr);
|
||||
if (!s2rfile)
|
||||
return;
|
||||
s2r_write32(ticks);
|
||||
EMITC(0, addr);
|
||||
}
|
||||
|
||||
void s2r_writereg(u32 ticks,u32 addr,s16 value)
|
||||
void s2r_writereg(u32 ticks, u32 addr, s16 value)
|
||||
{
|
||||
if(!s2rfile) return;
|
||||
s2r_write32(ticks);
|
||||
EMITC(1,addr);
|
||||
s2r_write16(value);
|
||||
if (!s2rfile)
|
||||
return;
|
||||
s2r_write32(ticks);
|
||||
EMITC(1, addr);
|
||||
s2r_write16(value);
|
||||
}
|
||||
|
||||
void s2r_writedma4(u32 ticks,u16*data,u32 len)
|
||||
void s2r_writedma4(u32 ticks, u16 *data, u32 len)
|
||||
{
|
||||
u32 i;
|
||||
if(!s2rfile) return;
|
||||
s2r_write32(ticks);
|
||||
EMITC(2,len);
|
||||
for(i=0;i<len;i++,data++)
|
||||
s2r_write16(*data);
|
||||
u32 i;
|
||||
if (!s2rfile)
|
||||
return;
|
||||
s2r_write32(ticks);
|
||||
EMITC(2, len);
|
||||
for (i = 0; i < len; i++, data++)
|
||||
s2r_write16(*data);
|
||||
}
|
||||
|
||||
void s2r_writedma7(u32 ticks,u16*data,u32 len)
|
||||
void s2r_writedma7(u32 ticks, u16 *data, u32 len)
|
||||
{
|
||||
u32 i;
|
||||
if(!s2rfile) return;
|
||||
s2r_write32(ticks);
|
||||
EMITC(3,len);
|
||||
for(i=0;i<len;i++,data++)
|
||||
s2r_write16(*data);
|
||||
u32 i;
|
||||
if (!s2rfile)
|
||||
return;
|
||||
s2r_write32(ticks);
|
||||
EMITC(3, len);
|
||||
for (i = 0; i < len; i++, data++)
|
||||
s2r_write16(*data);
|
||||
}
|
||||
|
||||
void s2r_close()
|
||||
{
|
||||
if(!s2rfile) return;
|
||||
fclose(s2rfile);
|
||||
if (!s2rfile)
|
||||
return;
|
||||
fclose(s2rfile);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
@ -94,13 +99,13 @@ void s2r_close()
|
|||
///////////////////////////////////////////////////////////////
|
||||
// replay code
|
||||
|
||||
bool replay_mode=false;
|
||||
bool replay_mode = false;
|
||||
|
||||
u16 dmabuffer[0xFFFFF];
|
||||
|
||||
const u32 IOP_CLK = 768*48000;
|
||||
const u32 IOPCiclesPerMS = 768*48;
|
||||
u32 CurrentIOPCycle=0;
|
||||
const u32 IOP_CLK = 768 * 48000;
|
||||
const u32 IOPCiclesPerMS = 768 * 48;
|
||||
u32 CurrentIOPCycle = 0;
|
||||
|
||||
u64 HighResFreq;
|
||||
u64 HighResPrev;
|
||||
|
@ -110,31 +115,31 @@ bool Running = false;
|
|||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
int conprintf(const char* fmt, ...)
|
||||
int conprintf(const char *fmt, ...)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
char s[1024];
|
||||
va_list list;
|
||||
char s[1024];
|
||||
va_list list;
|
||||
|
||||
va_start(list, fmt);
|
||||
vsprintf(s,fmt, list);
|
||||
va_end(list);
|
||||
va_start(list, fmt);
|
||||
vsprintf(s, fmt, list);
|
||||
va_end(list);
|
||||
|
||||
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if(handle == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
DWORD written = 0;
|
||||
WriteConsoleA(handle, s, strlen(s), &written, 0);
|
||||
FlushFileBuffers(handle);
|
||||
DWORD written = 0;
|
||||
WriteConsoleA(handle, s, strlen(s), &written, 0);
|
||||
FlushFileBuffers(handle);
|
||||
|
||||
return written;
|
||||
return written;
|
||||
#else
|
||||
va_list list;
|
||||
va_start(list, fmt);
|
||||
int ret = vsprintf(stderr,fmt,list);
|
||||
va_end(list);
|
||||
return ret;
|
||||
va_list list;
|
||||
va_start(list, fmt);
|
||||
int ret = vsprintf(stderr, fmt, list);
|
||||
va_end(list);
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -145,190 +150,188 @@ void dummy1()
|
|||
void dummy4()
|
||||
{
|
||||
#ifndef ENABLE_NEW_IOPDMA_SPU2
|
||||
SPU2interruptDMA4();
|
||||
SPU2interruptDMA4();
|
||||
#endif
|
||||
}
|
||||
|
||||
void dummy7()
|
||||
{
|
||||
#ifndef ENABLE_NEW_IOPDMA_SPU2
|
||||
SPU2interruptDMA7();
|
||||
SPU2interruptDMA7();
|
||||
#endif
|
||||
}
|
||||
|
||||
u64 HighResFrequency()
|
||||
{
|
||||
u64 freq;
|
||||
u64 freq;
|
||||
#ifdef _WIN32
|
||||
QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
|
||||
QueryPerformanceFrequency((LARGE_INTEGER *)&freq);
|
||||
#else
|
||||
// TODO
|
||||
// TODO
|
||||
#endif
|
||||
return freq;
|
||||
return freq;
|
||||
}
|
||||
|
||||
u64 HighResCounter()
|
||||
{
|
||||
u64 time;
|
||||
u64 time;
|
||||
#ifdef _WIN32
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&time);
|
||||
QueryPerformanceCounter((LARGE_INTEGER *)&time);
|
||||
#else
|
||||
// TODO
|
||||
// TODO
|
||||
#endif
|
||||
return time;
|
||||
return time;
|
||||
}
|
||||
|
||||
void InitWaitSync() // not extremely accurate but enough.
|
||||
void InitWaitSync() // not extremely accurate but enough.
|
||||
{
|
||||
HighResFreq = HighResFrequency();
|
||||
HighResPrev = HighResCounter();
|
||||
HighResScale = (double)HighResFreq / (double)IOP_CLK;
|
||||
HighResFreq = HighResFrequency();
|
||||
HighResPrev = HighResCounter();
|
||||
HighResScale = (double)HighResFreq / (double)IOP_CLK;
|
||||
}
|
||||
|
||||
u32 WaitSync( u32 TargetCycle )
|
||||
u32 WaitSync(u32 TargetCycle)
|
||||
{
|
||||
u32 WaitCycles = (TargetCycle - CurrentIOPCycle);
|
||||
u32 WaitTime = WaitCycles / IOPCiclesPerMS;
|
||||
if(WaitTime > 10)
|
||||
WaitTime = 10;
|
||||
if(WaitTime == 0)
|
||||
WaitTime = 1;
|
||||
SleepEx(WaitTime, TRUE);
|
||||
u32 WaitCycles = (TargetCycle - CurrentIOPCycle);
|
||||
u32 WaitTime = WaitCycles / IOPCiclesPerMS;
|
||||
if (WaitTime > 10)
|
||||
WaitTime = 10;
|
||||
if (WaitTime == 0)
|
||||
WaitTime = 1;
|
||||
SleepEx(WaitTime, TRUE);
|
||||
|
||||
// Refresh current time after sleeping
|
||||
u64 Current = HighResCounter();
|
||||
u32 delta = (u32)floor((Current-HighResPrev) / HighResScale + 0.5); // We lose some precision here, cycles might drift away over long periods of time ;P
|
||||
// Refresh current time after sleeping
|
||||
u64 Current = HighResCounter();
|
||||
u32 delta = (u32)floor((Current - HighResPrev) / HighResScale + 0.5); // We lose some precision here, cycles might drift away over long periods of time ;P
|
||||
|
||||
// Calculate time delta
|
||||
CurrentIOPCycle += delta;
|
||||
HighResPrev += (u64)floor(delta * HighResScale + 0.5); // Trying to compensate drifting mentioned above, not necessarily useful.
|
||||
// Calculate time delta
|
||||
CurrentIOPCycle += delta;
|
||||
HighResPrev += (u64)floor(delta * HighResScale + 0.5); // Trying to compensate drifting mentioned above, not necessarily useful.
|
||||
|
||||
return delta;
|
||||
return delta;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
BOOL WINAPI HandlerRoutine(DWORD dwCtrlType)
|
||||
{
|
||||
Running = false;
|
||||
return TRUE;
|
||||
Running = false;
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "Windows/Dialogs.h"
|
||||
EXPORT_C_(void) s2r_replay(HWND hwnd, HINSTANCE hinst, LPSTR filename, int nCmdShow)
|
||||
EXPORT_C_(void)
|
||||
s2r_replay(HWND hwnd, HINSTANCE hinst, LPSTR filename, int nCmdShow)
|
||||
{
|
||||
#ifndef ENABLE_NEW_IOPDMA_SPU2
|
||||
int events=0;
|
||||
int events = 0;
|
||||
|
||||
Running = true;
|
||||
Running = true;
|
||||
|
||||
#ifdef _WIN32
|
||||
AllocConsole();
|
||||
SetConsoleCtrlHandler(HandlerRoutine, TRUE);
|
||||
|
||||
conprintf("Playing %s file on %x...",filename,hwnd);
|
||||
AllocConsole();
|
||||
SetConsoleCtrlHandler(HandlerRoutine, TRUE);
|
||||
|
||||
if (IsWindows8OrGreater())
|
||||
{
|
||||
for (int n = 0; mods[n] != nullptr; ++n)
|
||||
{
|
||||
if (mods[n] == XAudio2_27_Out)
|
||||
{
|
||||
mods[n] = XAudio2Out;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
conprintf("Playing %s file on %x...", filename, hwnd);
|
||||
|
||||
if (IsWindows8OrGreater()) {
|
||||
for (int n = 0; mods[n] != nullptr; ++n) {
|
||||
if (mods[n] == XAudio2_27_Out) {
|
||||
mods[n] = XAudio2Out;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// load file
|
||||
FILE *file=fopen(filename,"rb");
|
||||
// load file
|
||||
FILE *file = fopen(filename, "rb");
|
||||
|
||||
if(!file)
|
||||
{
|
||||
conprintf("Could not open the replay file.");
|
||||
return;
|
||||
}
|
||||
// if successful, init the plugin
|
||||
if (!file) {
|
||||
conprintf("Could not open the replay file.");
|
||||
return;
|
||||
}
|
||||
// if successful, init the plugin
|
||||
|
||||
#define TryRead(dest,size,count,file) if(fread(dest,size,count,file)<count) { conprintf("Error reading from file."); goto Finish; /* Need to exit the while() loop and maybe also the switch */ }
|
||||
#define TryRead(dest, size, count, file) \
|
||||
if (fread(dest, size, count, file) < count) { \
|
||||
conprintf("Error reading from file."); \
|
||||
goto Finish; /* Need to exit the while() loop and maybe also the switch */ \
|
||||
}
|
||||
|
||||
TryRead(&CurrentIOPCycle,4,1,file);
|
||||
|
||||
replay_mode=true;
|
||||
TryRead(&CurrentIOPCycle, 4, 1, file);
|
||||
|
||||
InitWaitSync(); // Initialize the WaitSync stuff
|
||||
replay_mode = true;
|
||||
|
||||
SPU2init();
|
||||
SPU2irqCallback(dummy1,dummy4,dummy7);
|
||||
SPU2setClockPtr(&CurrentIOPCycle);
|
||||
SPU2open(&hwnd);
|
||||
InitWaitSync(); // Initialize the WaitSync stuff
|
||||
|
||||
CurrentIOPCycle=0;
|
||||
SPU2init();
|
||||
SPU2irqCallback(dummy1, dummy4, dummy7);
|
||||
SPU2setClockPtr(&CurrentIOPCycle);
|
||||
SPU2open(&hwnd);
|
||||
|
||||
SPU2async(0);
|
||||
CurrentIOPCycle = 0;
|
||||
|
||||
while(!feof(file) && Running)
|
||||
{
|
||||
u32 ccycle=0;
|
||||
u32 evid=0;
|
||||
u32 sval=0;
|
||||
u32 tval=0;
|
||||
SPU2async(0);
|
||||
|
||||
TryRead(&ccycle,4,1,file);
|
||||
TryRead(&sval,4,1,file);
|
||||
while (!feof(file) && Running) {
|
||||
u32 ccycle = 0;
|
||||
u32 evid = 0;
|
||||
u32 sval = 0;
|
||||
u32 tval = 0;
|
||||
|
||||
evid=sval>>29;
|
||||
sval&=0x1FFFFFFF;
|
||||
TryRead(&ccycle, 4, 1, file);
|
||||
TryRead(&sval, 4, 1, file);
|
||||
|
||||
u32 TargetCycle = ccycle * 768;
|
||||
evid = sval >> 29;
|
||||
sval &= 0x1FFFFFFF;
|
||||
|
||||
while(TargetCycle > CurrentIOPCycle)
|
||||
{
|
||||
u32 delta = WaitSync(TargetCycle);
|
||||
SPU2async(delta);
|
||||
}
|
||||
|
||||
switch(evid)
|
||||
{
|
||||
case 0:
|
||||
SPU2read(sval);
|
||||
break;
|
||||
case 1:
|
||||
TryRead(&tval,2,1,file);
|
||||
SPU2write(sval,tval);
|
||||
break;
|
||||
case 2:
|
||||
TryRead(dmabuffer,sval,2,file);
|
||||
SPU2writeDMA4Mem(dmabuffer,sval);
|
||||
break;
|
||||
case 3:
|
||||
TryRead(dmabuffer,sval,2,file);
|
||||
SPU2writeDMA7Mem(dmabuffer,sval);
|
||||
break;
|
||||
default:
|
||||
// not implemented
|
||||
return;
|
||||
break;
|
||||
}
|
||||
events++;
|
||||
}
|
||||
u32 TargetCycle = ccycle * 768;
|
||||
|
||||
while (TargetCycle > CurrentIOPCycle) {
|
||||
u32 delta = WaitSync(TargetCycle);
|
||||
SPU2async(delta);
|
||||
}
|
||||
|
||||
switch (evid) {
|
||||
case 0:
|
||||
SPU2read(sval);
|
||||
break;
|
||||
case 1:
|
||||
TryRead(&tval, 2, 1, file);
|
||||
SPU2write(sval, tval);
|
||||
break;
|
||||
case 2:
|
||||
TryRead(dmabuffer, sval, 2, file);
|
||||
SPU2writeDMA4Mem(dmabuffer, sval);
|
||||
break;
|
||||
case 3:
|
||||
TryRead(dmabuffer, sval, 2, file);
|
||||
SPU2writeDMA7Mem(dmabuffer, sval);
|
||||
break;
|
||||
default:
|
||||
// not implemented
|
||||
return;
|
||||
break;
|
||||
}
|
||||
events++;
|
||||
}
|
||||
|
||||
Finish:
|
||||
|
||||
//shutdown
|
||||
SPU2close();
|
||||
SPU2shutdown();
|
||||
fclose(file);
|
||||
//shutdown
|
||||
SPU2close();
|
||||
SPU2shutdown();
|
||||
fclose(file);
|
||||
|
||||
conprintf("Finished playing %s file (%d cycles, %d events).",filename,CurrentIOPCycle,events);
|
||||
conprintf("Finished playing %s file (%d cycles, %d events).", filename, CurrentIOPCycle, events);
|
||||
|
||||
#ifdef _WIN32
|
||||
FreeConsole();
|
||||
FreeConsole();
|
||||
#endif
|
||||
|
||||
replay_mode=false;
|
||||
replay_mode = false;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -22,10 +22,10 @@
|
|||
|
||||
// s2r dumping
|
||||
int s2r_open(u32 ticks, char *filename);
|
||||
void s2r_readreg(u32 ticks,u32 addr);
|
||||
void s2r_writereg(u32 ticks,u32 addr,s16 value);
|
||||
void s2r_writedma4(u32 ticks,u16*data,u32 len);
|
||||
void s2r_writedma7(u32 ticks,u16*data,u32 len);
|
||||
void s2r_readreg(u32 ticks, u32 addr);
|
||||
void s2r_writereg(u32 ticks, u32 addr, s16 value);
|
||||
void s2r_writedma4(u32 ticks, u16 *data, u32 len);
|
||||
void s2r_writedma7(u32 ticks, u16 *data, u32 len);
|
||||
void s2r_close();
|
||||
|
||||
extern bool replay_mode;
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
//Uncomment the next line to use the old time stretcher
|
||||
//#define SPU2X_USE_OLD_STRETCHER
|
||||
|
||||
static soundtouch::SoundTouch* pSoundTouch = NULL;
|
||||
static soundtouch::SoundTouch *pSoundTouch = NULL;
|
||||
|
||||
// data prediction amount, used to "commit" data that hasn't
|
||||
// finished timestretch processing.
|
||||
|
@ -36,9 +36,9 @@ float SndBuffer::lastEmergencyAdj;
|
|||
float SndBuffer::cTempo = 1;
|
||||
float SndBuffer::eTempo = 1;
|
||||
|
||||
void SndBuffer::PredictDataWrite( int samples )
|
||||
void SndBuffer::PredictDataWrite(int samples)
|
||||
{
|
||||
m_predictData += samples;
|
||||
m_predictData += samples;
|
||||
}
|
||||
|
||||
// Calculate the buffer status percentage.
|
||||
|
@ -48,17 +48,17 @@ void SndBuffer::PredictDataWrite( int samples )
|
|||
// -1.0 = buffer underflow!
|
||||
float SndBuffer::GetStatusPct()
|
||||
{
|
||||
// Get the buffer status of the output driver too, so that we can
|
||||
// obtain a more accurate overall buffer status.
|
||||
// Get the buffer status of the output driver too, so that we can
|
||||
// obtain a more accurate overall buffer status.
|
||||
|
||||
int drvempty = mods[OutputModule]->GetEmptySampleCount(); // / 2;
|
||||
int drvempty = mods[OutputModule]->GetEmptySampleCount(); // / 2;
|
||||
|
||||
//ConLog( "Data %d >>> driver: %d predict: %d\n", m_data, drvempty, m_predictData );
|
||||
//ConLog( "Data %d >>> driver: %d predict: %d\n", m_data, drvempty, m_predictData );
|
||||
|
||||
int data = _GetApproximateDataInBuffer();
|
||||
float result = (float)( data + m_predictData - drvempty) - (m_size/16);
|
||||
result /= (m_size/16);
|
||||
return result;
|
||||
int data = _GetApproximateDataInBuffer();
|
||||
float result = (float)(data + m_predictData - drvempty) - (m_size / 16);
|
||||
result /= (m_size / 16);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
@ -87,7 +87,7 @@ float SndBuffer::GetStatusPct()
|
|||
// These params were tested to show good respond and stability, on all audio systems (dsound, wav, port audio, xaudio2),
|
||||
// even at extreme small latency of 50ms which can handle 50%-100% variations without audible glitches.
|
||||
|
||||
int targetIPS=750;
|
||||
int targetIPS = 750;
|
||||
|
||||
//Dynamic tuning changes the values of the base algorithm parameters (derived from targetIPS) to adapt, in real time, to
|
||||
// different number of invocations/sec (mostly affects number of iterations to average).
|
||||
|
@ -99,277 +99,277 @@ int targetIPS=750;
|
|||
//#define NEWSTRETCHER_USE_DYNAMIC_TUNING
|
||||
|
||||
|
||||
//Additional performance note: since MAX_STRETCH_AVERAGE_LEN = 128 (or any power of 2), the '%' below
|
||||
//Additional performance note: since MAX_STRETCH_AVERAGE_LEN = 128 (or any power of 2), the '%' below
|
||||
//could be replaced with a faster '&'. The compiler is highly likely to do it since all the values are unsigned.
|
||||
#define AVERAGING_BUFFER_SIZE 256U
|
||||
unsigned int AVERAGING_WINDOW = 50.0 * targetIPS/750;
|
||||
unsigned int AVERAGING_WINDOW = 50.0 * targetIPS / 750;
|
||||
|
||||
|
||||
#define STRETCHER_RESET_THRESHOLD 5
|
||||
int gRequestStretcherReset = STRETCHER_RESET_THRESHOLD;
|
||||
//Adds a value to the running average buffer, and return the new running average.
|
||||
float addToAvg(float val){
|
||||
static float avg_fullness[AVERAGING_BUFFER_SIZE];
|
||||
static unsigned int nextAvgPos = 0;
|
||||
static unsigned int available = 0; // Make sure we're not averaging AVERAGING_WINDOW items if we inserted less.
|
||||
if (gRequestStretcherReset >= STRETCHER_RESET_THRESHOLD)
|
||||
available = 0;
|
||||
float addToAvg(float val)
|
||||
{
|
||||
static float avg_fullness[AVERAGING_BUFFER_SIZE];
|
||||
static unsigned int nextAvgPos = 0;
|
||||
static unsigned int available = 0; // Make sure we're not averaging AVERAGING_WINDOW items if we inserted less.
|
||||
if (gRequestStretcherReset >= STRETCHER_RESET_THRESHOLD)
|
||||
available = 0;
|
||||
|
||||
if (available < AVERAGING_BUFFER_SIZE)
|
||||
available++;
|
||||
if (available < AVERAGING_BUFFER_SIZE)
|
||||
available++;
|
||||
|
||||
avg_fullness[nextAvgPos] = val;
|
||||
nextAvgPos = (nextAvgPos + 1U) % AVERAGING_BUFFER_SIZE;
|
||||
|
||||
unsigned int actualWindow = std::min(available, AVERAGING_WINDOW);
|
||||
unsigned int first = (nextAvgPos - actualWindow + AVERAGING_BUFFER_SIZE)
|
||||
% AVERAGING_BUFFER_SIZE;
|
||||
avg_fullness[nextAvgPos] = val;
|
||||
nextAvgPos = (nextAvgPos + 1U) % AVERAGING_BUFFER_SIZE;
|
||||
|
||||
// Possible optimization: if we know that actualWindow hasn't changed since
|
||||
// last invocation, we could calculate the running average in O(1) instead of O(N)
|
||||
// by keeping a running sum between invocations, and then
|
||||
// do "runningSum = runningSum + val - avg_fullness[(first-1)%...]" instead of the following loop.
|
||||
// Few gotchas: val overwrites first-1, handling actualWindow changes, etc.
|
||||
// However, this isn't hot code, so unless proven otherwise, we can live with unoptimized code.
|
||||
float sum = 0;
|
||||
for(unsigned int i = first; i < first + actualWindow; i++) {
|
||||
sum += avg_fullness[i % AVERAGING_BUFFER_SIZE];
|
||||
}
|
||||
sum = sum / actualWindow;
|
||||
unsigned int actualWindow = std::min(available, AVERAGING_WINDOW);
|
||||
unsigned int first = (nextAvgPos - actualWindow + AVERAGING_BUFFER_SIZE) % AVERAGING_BUFFER_SIZE;
|
||||
|
||||
return sum ? sum : 1; // 1 because that's the 100% perfect speed value
|
||||
// Possible optimization: if we know that actualWindow hasn't changed since
|
||||
// last invocation, we could calculate the running average in O(1) instead of O(N)
|
||||
// by keeping a running sum between invocations, and then
|
||||
// do "runningSum = runningSum + val - avg_fullness[(first-1)%...]" instead of the following loop.
|
||||
// Few gotchas: val overwrites first-1, handling actualWindow changes, etc.
|
||||
// However, this isn't hot code, so unless proven otherwise, we can live with unoptimized code.
|
||||
float sum = 0;
|
||||
for (unsigned int i = first; i < first + actualWindow; i++) {
|
||||
sum += avg_fullness[i % AVERAGING_BUFFER_SIZE];
|
||||
}
|
||||
sum = sum / actualWindow;
|
||||
|
||||
return sum ? sum : 1; // 1 because that's the 100% perfect speed value
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool IsInRange(const T& val, const T& min, const T& max)
|
||||
bool IsInRange(const T &val, const T &min, const T &max)
|
||||
{
|
||||
return ( min <= val && val <= max );
|
||||
return (min <= val && val <= max);
|
||||
}
|
||||
|
||||
//actual stretch algorithm implementation
|
||||
void SndBuffer::UpdateTempoChangeSoundTouch2()
|
||||
{
|
||||
|
||||
long targetSamplesReservoir=48*SndOutLatencyMS;//48000*SndOutLatencyMS/1000
|
||||
//base aim at buffer filled %
|
||||
float baseTargetFullness=(double)targetSamplesReservoir;///(double)m_size;//0.05;
|
||||
long targetSamplesReservoir = 48 * SndOutLatencyMS; //48000*SndOutLatencyMS/1000
|
||||
//base aim at buffer filled %
|
||||
float baseTargetFullness = (double)targetSamplesReservoir; ///(double)m_size;//0.05;
|
||||
|
||||
//state vars
|
||||
static bool inside_hysteresis;//=false;
|
||||
static int hys_ok_count;//=0;
|
||||
static float dynamicTargetFullness;//=baseTargetFullness;
|
||||
if (gRequestStretcherReset >= STRETCHER_RESET_THRESHOLD) {
|
||||
ConLog("______> stretch: Reset.\n");
|
||||
inside_hysteresis=false;
|
||||
hys_ok_count=0;
|
||||
dynamicTargetFullness=baseTargetFullness;
|
||||
}
|
||||
//state vars
|
||||
static bool inside_hysteresis; //=false;
|
||||
static int hys_ok_count; //=0;
|
||||
static float dynamicTargetFullness; //=baseTargetFullness;
|
||||
if (gRequestStretcherReset >= STRETCHER_RESET_THRESHOLD) {
|
||||
ConLog("______> stretch: Reset.\n");
|
||||
inside_hysteresis = false;
|
||||
hys_ok_count = 0;
|
||||
dynamicTargetFullness = baseTargetFullness;
|
||||
}
|
||||
|
||||
int data = _GetApproximateDataInBuffer();
|
||||
float bufferFullness=(float)data;///(float)m_size;
|
||||
int data = _GetApproximateDataInBuffer();
|
||||
float bufferFullness = (float)data; ///(float)m_size;
|
||||
|
||||
#ifdef NEWSTRETCHER_USE_DYNAMIC_TUNING
|
||||
{//test current iterations/sec every 0.5s, and change algo params accordingly if different than previous IPS more than 30%
|
||||
static long iters=0;
|
||||
static wxDateTime last=wxDateTime::UNow();
|
||||
wxDateTime unow=wxDateTime::UNow();
|
||||
wxTimeSpan delta = unow.Subtract(last);
|
||||
if( delta.GetMilliseconds()>500 ){
|
||||
int pot_targetIPS=1000.0/delta.GetMilliseconds().ToDouble()*iters;
|
||||
if(!IsInRange(pot_targetIPS, int((float)targetIPS/1.3f), int((float)targetIPS*1.3f)) ){
|
||||
if(MsgOverruns()) ConLog("Stretcher: setting iters/sec from %d to %d\n", targetIPS, pot_targetIPS);
|
||||
targetIPS=pot_targetIPS;
|
||||
AVERAGING_WINDOW=GetClamped((int)(50.0f *(float)targetIPS/750.0f), 3, (int)AVERAGING_BUFFER_SIZE);
|
||||
}
|
||||
last=unow;
|
||||
iters=0;
|
||||
}
|
||||
iters++;
|
||||
}
|
||||
{ //test current iterations/sec every 0.5s, and change algo params accordingly if different than previous IPS more than 30%
|
||||
static long iters = 0;
|
||||
static wxDateTime last = wxDateTime::UNow();
|
||||
wxDateTime unow = wxDateTime::UNow();
|
||||
wxTimeSpan delta = unow.Subtract(last);
|
||||
if (delta.GetMilliseconds() > 500) {
|
||||
int pot_targetIPS = 1000.0 / delta.GetMilliseconds().ToDouble() * iters;
|
||||
if (!IsInRange(pot_targetIPS, int((float)targetIPS / 1.3f), int((float)targetIPS * 1.3f))) {
|
||||
if (MsgOverruns())
|
||||
ConLog("Stretcher: setting iters/sec from %d to %d\n", targetIPS, pot_targetIPS);
|
||||
targetIPS = pot_targetIPS;
|
||||
AVERAGING_WINDOW = GetClamped((int)(50.0f * (float)targetIPS / 750.0f), 3, (int)AVERAGING_BUFFER_SIZE);
|
||||
}
|
||||
last = unow;
|
||||
iters = 0;
|
||||
}
|
||||
iters++;
|
||||
}
|
||||
#endif
|
||||
|
||||
//Algorithm params: (threshold params (hysteresis), etc)
|
||||
const float hys_ok_factor = 1.04f;
|
||||
const float hys_bad_factor = 1.2f;
|
||||
int hys_min_ok_count = GetClamped((int)(50.0 *(float)targetIPS/750.0), 2, 100); //consecutive iterations within hys_ok before going to 1:1 mode
|
||||
int compensationDivider = GetClamped((int)(100.0 *(float)targetIPS/750), 15, 150);
|
||||
//Algorithm params: (threshold params (hysteresis), etc)
|
||||
const float hys_ok_factor = 1.04f;
|
||||
const float hys_bad_factor = 1.2f;
|
||||
int hys_min_ok_count = GetClamped((int)(50.0 * (float)targetIPS / 750.0), 2, 100); //consecutive iterations within hys_ok before going to 1:1 mode
|
||||
int compensationDivider = GetClamped((int)(100.0 * (float)targetIPS / 750), 15, 150);
|
||||
|
||||
float tempoAdjust=bufferFullness/dynamicTargetFullness;
|
||||
float avgerage = addToAvg(tempoAdjust);
|
||||
tempoAdjust = avgerage;
|
||||
float tempoAdjust = bufferFullness / dynamicTargetFullness;
|
||||
float avgerage = addToAvg(tempoAdjust);
|
||||
tempoAdjust = avgerage;
|
||||
|
||||
// Dampen the adjustment to avoid overshoots (this means the average will compensate to the other side).
|
||||
// This is different than simply bigger averaging window since bigger window also has bigger "momentum",
|
||||
// so it's slower to slow down when it gets close to the equilibrium state and can therefore resonate.
|
||||
// The dampening (sqrt was chosen for no very good reason) manages to mostly prevent that.
|
||||
tempoAdjust = sqrt(tempoAdjust);
|
||||
// Dampen the adjustment to avoid overshoots (this means the average will compensate to the other side).
|
||||
// This is different than simply bigger averaging window since bigger window also has bigger "momentum",
|
||||
// so it's slower to slow down when it gets close to the equilibrium state and can therefore resonate.
|
||||
// The dampening (sqrt was chosen for no very good reason) manages to mostly prevent that.
|
||||
tempoAdjust = sqrt(tempoAdjust);
|
||||
|
||||
tempoAdjust = GetClamped( tempoAdjust, 0.05f, 10.0f);
|
||||
|
||||
if (tempoAdjust < 1)
|
||||
baseTargetFullness /= sqrt(tempoAdjust); // slightly increase latency when running slow.
|
||||
|
||||
dynamicTargetFullness += (baseTargetFullness/tempoAdjust - dynamicTargetFullness)/(double)compensationDivider;
|
||||
if( IsInRange(tempoAdjust, 0.9f, 1.1f) && IsInRange( dynamicTargetFullness, baseTargetFullness*0.9f, baseTargetFullness*1.1f) )
|
||||
dynamicTargetFullness=baseTargetFullness;
|
||||
tempoAdjust = GetClamped(tempoAdjust, 0.05f, 10.0f);
|
||||
|
||||
if( !inside_hysteresis )
|
||||
{
|
||||
if( IsInRange( tempoAdjust, 1.0f/hys_ok_factor, hys_ok_factor ) )
|
||||
hys_ok_count++;
|
||||
else
|
||||
hys_ok_count=0;
|
||||
if (tempoAdjust < 1)
|
||||
baseTargetFullness /= sqrt(tempoAdjust); // slightly increase latency when running slow.
|
||||
|
||||
if( hys_ok_count >= hys_min_ok_count ){
|
||||
inside_hysteresis=true;
|
||||
if(MsgOverruns()) ConLog("======> stretch: None (1:1)\n");
|
||||
}
|
||||
dynamicTargetFullness += (baseTargetFullness / tempoAdjust - dynamicTargetFullness) / (double)compensationDivider;
|
||||
if (IsInRange(tempoAdjust, 0.9f, 1.1f) && IsInRange(dynamicTargetFullness, baseTargetFullness * 0.9f, baseTargetFullness * 1.1f))
|
||||
dynamicTargetFullness = baseTargetFullness;
|
||||
|
||||
}
|
||||
else if( !IsInRange( tempoAdjust, 1.0f/hys_bad_factor, hys_bad_factor ) ){
|
||||
if(MsgOverruns()) ConLog("~~~~~~> stretch: Dynamic\n");
|
||||
inside_hysteresis=false;
|
||||
hys_ok_count=0;
|
||||
}
|
||||
if (!inside_hysteresis) {
|
||||
if (IsInRange(tempoAdjust, 1.0f / hys_ok_factor, hys_ok_factor))
|
||||
hys_ok_count++;
|
||||
else
|
||||
hys_ok_count = 0;
|
||||
|
||||
if(inside_hysteresis)
|
||||
tempoAdjust=1.0;
|
||||
if (hys_ok_count >= hys_min_ok_count) {
|
||||
inside_hysteresis = true;
|
||||
if (MsgOverruns())
|
||||
ConLog("======> stretch: None (1:1)\n");
|
||||
}
|
||||
|
||||
if(MsgOverruns()){
|
||||
static int iters=0;
|
||||
static wxDateTime last=wxDateTime::UNow();
|
||||
wxDateTime unow=wxDateTime::UNow();
|
||||
wxTimeSpan delta = unow.Subtract(last);
|
||||
} else if (!IsInRange(tempoAdjust, 1.0f / hys_bad_factor, hys_bad_factor)) {
|
||||
if (MsgOverruns())
|
||||
ConLog("~~~~~~> stretch: Dynamic\n");
|
||||
inside_hysteresis = false;
|
||||
hys_ok_count = 0;
|
||||
}
|
||||
|
||||
if(delta.GetMilliseconds()>1000){//report buffers state and tempo adjust every second
|
||||
ConLog("buffers: %4d ms (%3.0f%%), tempo: %f, comp: %2.3f, iters: %d, (N-IPS:%d -> avg:%d, minokc:%d, div:%d) reset:%d\n",
|
||||
(int)(data/48), (double)(100.0*bufferFullness/baseTargetFullness), (double)tempoAdjust, (double)(dynamicTargetFullness/baseTargetFullness), iters, (int)targetIPS
|
||||
, AVERAGING_WINDOW, hys_min_ok_count, compensationDivider, gRequestStretcherReset
|
||||
);
|
||||
last=unow;
|
||||
iters=0;
|
||||
}
|
||||
iters++;
|
||||
}
|
||||
if (inside_hysteresis)
|
||||
tempoAdjust = 1.0;
|
||||
|
||||
pSoundTouch->setTempo(tempoAdjust);
|
||||
if (gRequestStretcherReset >= STRETCHER_RESET_THRESHOLD)
|
||||
gRequestStretcherReset = 0;
|
||||
if (MsgOverruns()) {
|
||||
static int iters = 0;
|
||||
static wxDateTime last = wxDateTime::UNow();
|
||||
wxDateTime unow = wxDateTime::UNow();
|
||||
wxTimeSpan delta = unow.Subtract(last);
|
||||
|
||||
return;
|
||||
if (delta.GetMilliseconds() > 1000) { //report buffers state and tempo adjust every second
|
||||
ConLog("buffers: %4d ms (%3.0f%%), tempo: %f, comp: %2.3f, iters: %d, (N-IPS:%d -> avg:%d, minokc:%d, div:%d) reset:%d\n",
|
||||
(int)(data / 48), (double)(100.0 * bufferFullness / baseTargetFullness), (double)tempoAdjust, (double)(dynamicTargetFullness / baseTargetFullness), iters, (int)targetIPS, AVERAGING_WINDOW, hys_min_ok_count, compensationDivider, gRequestStretcherReset);
|
||||
last = unow;
|
||||
iters = 0;
|
||||
}
|
||||
iters++;
|
||||
}
|
||||
|
||||
pSoundTouch->setTempo(tempoAdjust);
|
||||
if (gRequestStretcherReset >= STRETCHER_RESET_THRESHOLD)
|
||||
gRequestStretcherReset = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SndBuffer::UpdateTempoChangeSoundTouch()
|
||||
{
|
||||
float statusPct = GetStatusPct();
|
||||
float pctChange = statusPct - lastPct;
|
||||
float statusPct = GetStatusPct();
|
||||
float pctChange = statusPct - lastPct;
|
||||
|
||||
float tempoChange;
|
||||
float emergencyAdj = 0;
|
||||
float newcee = cTempo; // workspace var. for cTempo
|
||||
float tempoChange;
|
||||
float emergencyAdj = 0;
|
||||
float newcee = cTempo; // workspace var. for cTempo
|
||||
|
||||
// IMPORTANT!
|
||||
// If you plan to tweak these values, make sure you're using a release build
|
||||
// OUTSIDE THE DEBUGGER to test it! The Visual Studio debugger can really cause
|
||||
// erratic behavior in the audio buffers, and makes the timestretcher seem a
|
||||
// lot more inconsistent than it really is.
|
||||
// IMPORTANT!
|
||||
// If you plan to tweak these values, make sure you're using a release build
|
||||
// OUTSIDE THE DEBUGGER to test it! The Visual Studio debugger can really cause
|
||||
// erratic behavior in the audio buffers, and makes the timestretcher seem a
|
||||
// lot more inconsistent than it really is.
|
||||
|
||||
// We have two factors.
|
||||
// * Distance from nominal buffer status (50% full)
|
||||
// * The change from previous update to this update.
|
||||
// We have two factors.
|
||||
// * Distance from nominal buffer status (50% full)
|
||||
// * The change from previous update to this update.
|
||||
|
||||
// Prediction based on the buffer change:
|
||||
// (linear seems to work better here)
|
||||
// Prediction based on the buffer change:
|
||||
// (linear seems to work better here)
|
||||
|
||||
tempoChange = pctChange * 0.75f;
|
||||
tempoChange = pctChange * 0.75f;
|
||||
|
||||
if( statusPct * tempoChange < 0.0f )
|
||||
{
|
||||
// only apply tempo change if it is in synch with the buffer status.
|
||||
// In other words, if the buffer is high (over 0%), and is decreasing,
|
||||
// ignore it. It'll just muck things up.
|
||||
if (statusPct * tempoChange < 0.0f) {
|
||||
// only apply tempo change if it is in synch with the buffer status.
|
||||
// In other words, if the buffer is high (over 0%), and is decreasing,
|
||||
// ignore it. It'll just muck things up.
|
||||
|
||||
tempoChange = 0;
|
||||
}
|
||||
tempoChange = 0;
|
||||
}
|
||||
|
||||
// Sudden spikes in framerate can cause the nominal buffer status
|
||||
// to go critical, in which case we have to enact an emergency
|
||||
// stretch. The following cubic formulas do that. Values near
|
||||
// the extremeites give much larger results than those near 0.
|
||||
// And the value is added only this time, and does not accumulate.
|
||||
// (otherwise a large value like this would cause problems down the road)
|
||||
// Sudden spikes in framerate can cause the nominal buffer status
|
||||
// to go critical, in which case we have to enact an emergency
|
||||
// stretch. The following cubic formulas do that. Values near
|
||||
// the extremeites give much larger results than those near 0.
|
||||
// And the value is added only this time, and does not accumulate.
|
||||
// (otherwise a large value like this would cause problems down the road)
|
||||
|
||||
// Constants:
|
||||
// Weight - weights the statusPct's "emergency" consideration.
|
||||
// higher values here will make the buffer perform more drastic
|
||||
// compensations at the outer edges of the buffer (at -75 or +75%
|
||||
// or beyond, for example).
|
||||
// Constants:
|
||||
// Weight - weights the statusPct's "emergency" consideration.
|
||||
// higher values here will make the buffer perform more drastic
|
||||
// compensations at the outer edges of the buffer (at -75 or +75%
|
||||
// or beyond, for example).
|
||||
|
||||
// Range - scales the adjustment to the given range (more or less).
|
||||
// The actual range is dependent on the weight used, so if you increase
|
||||
// Weight you'll usually want to decrease Range somewhat to compensate.
|
||||
// Range - scales the adjustment to the given range (more or less).
|
||||
// The actual range is dependent on the weight used, so if you increase
|
||||
// Weight you'll usually want to decrease Range somewhat to compensate.
|
||||
|
||||
// Prediction based on the buffer fill status:
|
||||
// Prediction based on the buffer fill status:
|
||||
|
||||
const float statusWeight = 2.99f;
|
||||
const float statusRange = 0.068f;
|
||||
const float statusWeight = 2.99f;
|
||||
const float statusRange = 0.068f;
|
||||
|
||||
// "non-emergency" deadzone: In this area stretching will be strongly discouraged.
|
||||
// Note: due tot he nature of timestretch latency, it's always a wee bit harder to
|
||||
// cope with low fps (underruns) than it is high fps (overruns). So to help out a
|
||||
// little, the low-end portions of this check are less forgiving than the high-sides.
|
||||
// "non-emergency" deadzone: In this area stretching will be strongly discouraged.
|
||||
// Note: due tot he nature of timestretch latency, it's always a wee bit harder to
|
||||
// cope with low fps (underruns) than it is high fps (overruns). So to help out a
|
||||
// little, the low-end portions of this check are less forgiving than the high-sides.
|
||||
|
||||
if( cTempo < 0.965f || cTempo > 1.060f ||
|
||||
pctChange < -0.38f || pctChange > 0.54f ||
|
||||
statusPct < -0.42f || statusPct > 0.70f ||
|
||||
eTempo < 0.89f || eTempo > 1.19f )
|
||||
{
|
||||
//printf("Emergency stretch: cTempo = %f eTempo = %f pctChange = %f statusPct = %f\n",cTempo,eTempo,pctChange,statusPct);
|
||||
emergencyAdj = ( pow( statusPct*statusWeight, 3.0f ) * statusRange);
|
||||
}
|
||||
if (cTempo < 0.965f || cTempo > 1.060f ||
|
||||
pctChange < -0.38f || pctChange > 0.54f ||
|
||||
statusPct < -0.42f || statusPct > 0.70f ||
|
||||
eTempo < 0.89f || eTempo > 1.19f) {
|
||||
//printf("Emergency stretch: cTempo = %f eTempo = %f pctChange = %f statusPct = %f\n",cTempo,eTempo,pctChange,statusPct);
|
||||
emergencyAdj = (pow(statusPct * statusWeight, 3.0f) * statusRange);
|
||||
}
|
||||
|
||||
// Smooth things out by factoring our previous adjustment into this one.
|
||||
// It helps make the system 'feel' a little smarter by giving it at least
|
||||
// one packet worth of history to help work off of:
|
||||
// Smooth things out by factoring our previous adjustment into this one.
|
||||
// It helps make the system 'feel' a little smarter by giving it at least
|
||||
// one packet worth of history to help work off of:
|
||||
|
||||
emergencyAdj = (emergencyAdj * 0.75f) + (lastEmergencyAdj * 0.25f );
|
||||
emergencyAdj = (emergencyAdj * 0.75f) + (lastEmergencyAdj * 0.25f);
|
||||
|
||||
lastEmergencyAdj = emergencyAdj;
|
||||
lastPct = statusPct;
|
||||
lastEmergencyAdj = emergencyAdj;
|
||||
lastPct = statusPct;
|
||||
|
||||
// Accumulate a fraction of the tempo change into the tempo itself.
|
||||
// This helps the system run "smarter" to games that run consistently
|
||||
// fast or slow by altering the base tempo to something closer to the
|
||||
// game's active speed. In tests most games normalize within 2 seconds
|
||||
// at 100ms latency, which is pretty good (larger buffers normalize even
|
||||
// quicker).
|
||||
// Accumulate a fraction of the tempo change into the tempo itself.
|
||||
// This helps the system run "smarter" to games that run consistently
|
||||
// fast or slow by altering the base tempo to something closer to the
|
||||
// game's active speed. In tests most games normalize within 2 seconds
|
||||
// at 100ms latency, which is pretty good (larger buffers normalize even
|
||||
// quicker).
|
||||
|
||||
newcee += newcee * (tempoChange+emergencyAdj) * 0.03f;
|
||||
newcee += newcee * (tempoChange + emergencyAdj) * 0.03f;
|
||||
|
||||
// Apply tempoChange as a scale of cTempo. That way the effect is proportional
|
||||
// to the current tempo. (otherwise tempos rate of change at the extremes would
|
||||
// be too drastic)
|
||||
// Apply tempoChange as a scale of cTempo. That way the effect is proportional
|
||||
// to the current tempo. (otherwise tempos rate of change at the extremes would
|
||||
// be too drastic)
|
||||
|
||||
float newTempo = newcee + ( emergencyAdj * cTempo );
|
||||
float newTempo = newcee + (emergencyAdj * cTempo);
|
||||
|
||||
// ... and as a final optimization, only stretch if the new tempo is outside
|
||||
// a nominal threshold. Keep this threshold check small, because it could
|
||||
// cause some serious side effects otherwise. (enlarging the cTempo check above
|
||||
// is usually better/safer)
|
||||
if( newTempo < 0.970f || newTempo > 1.045f )
|
||||
{
|
||||
cTempo = (float)newcee;
|
||||
// ... and as a final optimization, only stretch if the new tempo is outside
|
||||
// a nominal threshold. Keep this threshold check small, because it could
|
||||
// cause some serious side effects otherwise. (enlarging the cTempo check above
|
||||
// is usually better/safer)
|
||||
if (newTempo < 0.970f || newTempo > 1.045f) {
|
||||
cTempo = (float)newcee;
|
||||
|
||||
if( newTempo < 0.10f ) newTempo = 0.10f;
|
||||
else if( newTempo > 10.0f ) newTempo = 10.0f;
|
||||
if (newTempo < 0.10f)
|
||||
newTempo = 0.10f;
|
||||
else if (newTempo > 10.0f)
|
||||
newTempo = 10.0f;
|
||||
|
||||
if( cTempo < 0.15f ) cTempo = 0.15f;
|
||||
else if( cTempo > 7.5f ) cTempo = 7.5f;
|
||||
if (cTempo < 0.15f)
|
||||
cTempo = 0.15f;
|
||||
else if (cTempo > 7.5f)
|
||||
cTempo = 7.5f;
|
||||
|
||||
pSoundTouch->setTempo( eTempo = (float)newTempo );
|
||||
pSoundTouch->setTempo(eTempo = (float)newTempo);
|
||||
|
||||
/*ConLog("* SPU2-X: [Nominal %d%%] [Emergency: %d%%] (baseTempo: %d%% ) (newTempo: %d%%) (buffer: %d%%)\n",
|
||||
/*ConLog("* SPU2-X: [Nominal %d%%] [Emergency: %d%%] (baseTempo: %d%% ) (newTempo: %d%%) (buffer: %d%%)\n",
|
||||
//(relation < 0.0) ? "Normalize" : "",
|
||||
(int)(tempoChange * 100.0 * 0.03),
|
||||
(int)(emergencyAdj * 100.0),
|
||||
|
@ -377,168 +377,164 @@ void SndBuffer::UpdateTempoChangeSoundTouch()
|
|||
(int)(newTempo * 100.0),
|
||||
(int)(statusPct * 100.0)
|
||||
);*/
|
||||
}
|
||||
else
|
||||
{
|
||||
// Nominal operation -- turn off stretching.
|
||||
// note: eTempo 'slides' toward 1.0 for smoother audio and better
|
||||
// protection against spikes.
|
||||
if( cTempo != 1.0f )
|
||||
{
|
||||
cTempo = 1.0f;
|
||||
eTempo = ( 1.0f + eTempo ) * 0.5f;
|
||||
pSoundTouch->setTempo( eTempo );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( eTempo != cTempo )
|
||||
pSoundTouch->setTempo( eTempo=cTempo );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Nominal operation -- turn off stretching.
|
||||
// note: eTempo 'slides' toward 1.0 for smoother audio and better
|
||||
// protection against spikes.
|
||||
if (cTempo != 1.0f) {
|
||||
cTempo = 1.0f;
|
||||
eTempo = (1.0f + eTempo) * 0.5f;
|
||||
pSoundTouch->setTempo(eTempo);
|
||||
} else {
|
||||
if (eTempo != cTempo)
|
||||
pSoundTouch->setTempo(eTempo = cTempo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern uint TickInterval;
|
||||
void SndBuffer::UpdateTempoChangeAsyncMixing()
|
||||
{
|
||||
float statusPct = GetStatusPct();
|
||||
float statusPct = GetStatusPct();
|
||||
|
||||
lastPct = statusPct;
|
||||
if( statusPct < -0.1f )
|
||||
{
|
||||
TickInterval -= 4;
|
||||
if( statusPct < -0.3f ) TickInterval = 64;
|
||||
if( TickInterval < 64 ) TickInterval = 64;
|
||||
//printf("-- %d, %f\n",TickInterval,statusPct);
|
||||
}
|
||||
else if( statusPct > 0.2f )
|
||||
{
|
||||
TickInterval += 1;
|
||||
if( TickInterval >= 7000 ) TickInterval = 7000;
|
||||
//printf("++ %d, %f\n",TickInterval,statusPct);
|
||||
}
|
||||
else TickInterval = 768;
|
||||
lastPct = statusPct;
|
||||
if (statusPct < -0.1f) {
|
||||
TickInterval -= 4;
|
||||
if (statusPct < -0.3f)
|
||||
TickInterval = 64;
|
||||
if (TickInterval < 64)
|
||||
TickInterval = 64;
|
||||
//printf("-- %d, %f\n",TickInterval,statusPct);
|
||||
} else if (statusPct > 0.2f) {
|
||||
TickInterval += 1;
|
||||
if (TickInterval >= 7000)
|
||||
TickInterval = 7000;
|
||||
//printf("++ %d, %f\n",TickInterval,statusPct);
|
||||
} else
|
||||
TickInterval = 768;
|
||||
}
|
||||
|
||||
void SndBuffer::timeStretchUnderrun()
|
||||
{
|
||||
gRequestStretcherReset++;
|
||||
// timeStretcher failed it's job. We need to slow down the audio some.
|
||||
gRequestStretcherReset++;
|
||||
// timeStretcher failed it's job. We need to slow down the audio some.
|
||||
|
||||
cTempo -= (cTempo * 0.12f);
|
||||
eTempo -= (eTempo * 0.30f);
|
||||
if( eTempo < 0.1f ) eTempo = 0.1f;
|
||||
// pSoundTouch->setTempo( eTempo );
|
||||
//pSoundTouch->setTempoChange(-30); // temporary (until stretcher is called) slow down
|
||||
cTempo -= (cTempo * 0.12f);
|
||||
eTempo -= (eTempo * 0.30f);
|
||||
if (eTempo < 0.1f)
|
||||
eTempo = 0.1f;
|
||||
// pSoundTouch->setTempo( eTempo );
|
||||
//pSoundTouch->setTempoChange(-30); // temporary (until stretcher is called) slow down
|
||||
}
|
||||
|
||||
s32 SndBuffer::timeStretchOverrun()
|
||||
{
|
||||
// If we overran it means the timestretcher failed. We need to speed
|
||||
// up audio playback.
|
||||
cTempo += cTempo * 0.12f;
|
||||
eTempo += eTempo * 0.40f;
|
||||
if( eTempo > 7.5f ) eTempo = 7.5f;
|
||||
//pSoundTouch->setTempo( eTempo );
|
||||
//pSoundTouch->setTempoChange(30);// temporary (until stretcher is called) speed up
|
||||
// If we overran it means the timestretcher failed. We need to speed
|
||||
// up audio playback.
|
||||
cTempo += cTempo * 0.12f;
|
||||
eTempo += eTempo * 0.40f;
|
||||
if (eTempo > 7.5f)
|
||||
eTempo = 7.5f;
|
||||
//pSoundTouch->setTempo( eTempo );
|
||||
//pSoundTouch->setTempoChange(30);// temporary (until stretcher is called) speed up
|
||||
|
||||
// Throw out just a little bit (two packets worth) to help
|
||||
// give the TS some room to work:
|
||||
gRequestStretcherReset++;
|
||||
return SndOutPacketSize*2;
|
||||
// Throw out just a little bit (two packets worth) to help
|
||||
// give the TS some room to work:
|
||||
gRequestStretcherReset++;
|
||||
return SndOutPacketSize * 2;
|
||||
}
|
||||
|
||||
static void CvtPacketToFloat( StereoOut32* srcdest )
|
||||
static void CvtPacketToFloat(StereoOut32 *srcdest)
|
||||
{
|
||||
StereoOutFloat* dest = (StereoOutFloat*)srcdest;
|
||||
const StereoOut32* src = (StereoOut32*)srcdest;
|
||||
for( uint i=0; i<SndOutPacketSize; ++i, ++dest, ++src )
|
||||
*dest = (StereoOutFloat)*src;
|
||||
StereoOutFloat *dest = (StereoOutFloat *)srcdest;
|
||||
const StereoOut32 *src = (StereoOut32 *)srcdest;
|
||||
for (uint i = 0; i < SndOutPacketSize; ++i, ++dest, ++src)
|
||||
*dest = (StereoOutFloat)*src;
|
||||
}
|
||||
|
||||
// Parameter note: Size should always be a multiple of 128, thanks!
|
||||
static void CvtPacketToInt( StereoOut32* srcdest, uint size )
|
||||
static void CvtPacketToInt(StereoOut32 *srcdest, uint size)
|
||||
{
|
||||
//pxAssume( (size & 127) == 0 );
|
||||
//pxAssume( (size & 127) == 0 );
|
||||
|
||||
const StereoOutFloat* src = (StereoOutFloat*)srcdest;
|
||||
StereoOut32* dest = srcdest;
|
||||
const StereoOutFloat *src = (StereoOutFloat *)srcdest;
|
||||
StereoOut32 *dest = srcdest;
|
||||
|
||||
for( uint i=0; i<size; ++i, ++dest, ++src )
|
||||
*dest = (StereoOut32)*src;
|
||||
for (uint i = 0; i < size; ++i, ++dest, ++src)
|
||||
*dest = (StereoOut32)*src;
|
||||
}
|
||||
|
||||
void SndBuffer::timeStretchWrite()
|
||||
{
|
||||
// data prediction helps keep the tempo adjustments more accurate.
|
||||
// The timestretcher returns packets in belated "clump" form.
|
||||
// Meaning that most of the time we'll get nothing back, and then
|
||||
// suddenly we'll get several chunks back at once. Thus we use
|
||||
// data prediction to make the timestretcher more responsive.
|
||||
// data prediction helps keep the tempo adjustments more accurate.
|
||||
// The timestretcher returns packets in belated "clump" form.
|
||||
// Meaning that most of the time we'll get nothing back, and then
|
||||
// suddenly we'll get several chunks back at once. Thus we use
|
||||
// data prediction to make the timestretcher more responsive.
|
||||
|
||||
PredictDataWrite( (int)( SndOutPacketSize / eTempo ) );
|
||||
CvtPacketToFloat( sndTempBuffer );
|
||||
PredictDataWrite((int)(SndOutPacketSize / eTempo));
|
||||
CvtPacketToFloat(sndTempBuffer);
|
||||
|
||||
pSoundTouch->putSamples( (float*)sndTempBuffer, SndOutPacketSize );
|
||||
pSoundTouch->putSamples((float *)sndTempBuffer, SndOutPacketSize);
|
||||
|
||||
int tempProgress;
|
||||
while( tempProgress = pSoundTouch->receiveSamples( (float*)sndTempBuffer, SndOutPacketSize),
|
||||
tempProgress != 0 )
|
||||
{
|
||||
// Hint: It's assumed that pSoundTouch will return chunks of 128 bytes (it always does as
|
||||
// long as the SSE optimizations are enabled), which means we can do our own SSE opts here.
|
||||
int tempProgress;
|
||||
while (tempProgress = pSoundTouch->receiveSamples((float *)sndTempBuffer, SndOutPacketSize),
|
||||
tempProgress != 0) {
|
||||
// Hint: It's assumed that pSoundTouch will return chunks of 128 bytes (it always does as
|
||||
// long as the SSE optimizations are enabled), which means we can do our own SSE opts here.
|
||||
|
||||
CvtPacketToInt( sndTempBuffer, tempProgress );
|
||||
_WriteSamples( sndTempBuffer, tempProgress );
|
||||
}
|
||||
CvtPacketToInt(sndTempBuffer, tempProgress);
|
||||
_WriteSamples(sndTempBuffer, tempProgress);
|
||||
}
|
||||
|
||||
#ifdef SPU2X_USE_OLD_STRETCHER
|
||||
UpdateTempoChangeSoundTouch();
|
||||
UpdateTempoChangeSoundTouch();
|
||||
#else
|
||||
UpdateTempoChangeSoundTouch2();
|
||||
UpdateTempoChangeSoundTouch2();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void SndBuffer::soundtouchInit()
|
||||
{
|
||||
pSoundTouch = new soundtouch::SoundTouch();
|
||||
pSoundTouch->setSampleRate(SampleRate);
|
||||
pSoundTouch->setChannels(2);
|
||||
pSoundTouch = new soundtouch::SoundTouch();
|
||||
pSoundTouch->setSampleRate(SampleRate);
|
||||
pSoundTouch->setChannels(2);
|
||||
|
||||
pSoundTouch->setSetting( SETTING_USE_QUICKSEEK, 0 );
|
||||
pSoundTouch->setSetting( SETTING_USE_AA_FILTER, 0 );
|
||||
pSoundTouch->setSetting(SETTING_USE_QUICKSEEK, 0);
|
||||
pSoundTouch->setSetting(SETTING_USE_AA_FILTER, 0);
|
||||
|
||||
SoundtouchCfg::ApplySettings( *pSoundTouch );
|
||||
SoundtouchCfg::ApplySettings(*pSoundTouch);
|
||||
|
||||
pSoundTouch->setTempo(1);
|
||||
pSoundTouch->setTempo(1);
|
||||
|
||||
// some timestretch management vars:
|
||||
// some timestretch management vars:
|
||||
|
||||
cTempo = 1.0;
|
||||
eTempo = 1.0;
|
||||
lastPct = 0;
|
||||
lastEmergencyAdj = 0;
|
||||
cTempo = 1.0;
|
||||
eTempo = 1.0;
|
||||
lastPct = 0;
|
||||
lastEmergencyAdj = 0;
|
||||
|
||||
m_predictData = 0;
|
||||
m_predictData = 0;
|
||||
}
|
||||
|
||||
// reset timestretch management vars, and delay updates a bit:
|
||||
void SndBuffer::soundtouchClearContents()
|
||||
{
|
||||
if( pSoundTouch == NULL ) return;
|
||||
if (pSoundTouch == NULL)
|
||||
return;
|
||||
|
||||
pSoundTouch->clear();
|
||||
pSoundTouch->setTempo(1);
|
||||
pSoundTouch->clear();
|
||||
pSoundTouch->setTempo(1);
|
||||
|
||||
cTempo = 1.0;
|
||||
eTempo = 1.0;
|
||||
lastPct = 0;
|
||||
lastEmergencyAdj = 0;
|
||||
cTempo = 1.0;
|
||||
eTempo = 1.0;
|
||||
lastPct = 0;
|
||||
lastEmergencyAdj = 0;
|
||||
|
||||
m_predictData = 0;
|
||||
m_predictData = 0;
|
||||
}
|
||||
|
||||
void SndBuffer::soundtouchCleanup()
|
||||
{
|
||||
safe_delete( pSoundTouch );
|
||||
safe_delete(pSoundTouch);
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Note the file is mostly a copy paste of the WavFile.h from SoundTouch library. It was
|
||||
// Note the file is mostly a copy paste of the WavFile.h from SoundTouch library. It was
|
||||
// shrunken to support only output 16 bits wav files
|
||||
|
||||
#include <stdio.h>
|
||||
|
@ -32,7 +32,7 @@ using namespace std;
|
|||
|
||||
static const char riffStr[] = "RIFF";
|
||||
static const char waveStr[] = "WAVE";
|
||||
static const char fmtStr[] = "fmt ";
|
||||
static const char fmtStr[] = "fmt ";
|
||||
static const char dataStr[] = "data";
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -44,8 +44,7 @@ WavOutFile::WavOutFile(const char *fileName, int sampleRate, int bits, int chann
|
|||
{
|
||||
bytesWritten = 0;
|
||||
fptr = fopen(fileName, "wb");
|
||||
if (fptr == NULL)
|
||||
{
|
||||
if (fptr == NULL) {
|
||||
string msg = "Error : Unable to open file \"";
|
||||
msg += fileName;
|
||||
msg += "\" for writing.";
|
||||
|
@ -60,8 +59,7 @@ WavOutFile::WavOutFile(const char *fileName, int sampleRate, int bits, int chann
|
|||
|
||||
WavOutFile::~WavOutFile()
|
||||
{
|
||||
if (fptr)
|
||||
{
|
||||
if (fptr) {
|
||||
finishHeader();
|
||||
fclose(fptr);
|
||||
}
|
||||
|
@ -122,8 +120,7 @@ void WavOutFile::writeHeader()
|
|||
// write the supplemented header in the beginning of the file
|
||||
fseek(fptr, 0, SEEK_SET);
|
||||
res = fwrite(&header, sizeof(header), 1, fptr);
|
||||
if (res != 1)
|
||||
{
|
||||
if (res != 1) {
|
||||
throw runtime_error("Error while writing to a wav file.");
|
||||
}
|
||||
|
||||
|
@ -139,12 +136,12 @@ void WavOutFile::write(const short *buffer, int numElems)
|
|||
// 16bit format & 16 bit samples
|
||||
|
||||
assert(header.format.bits_per_sample == 16);
|
||||
if (numElems < 1) return; // nothing to do
|
||||
if (numElems < 1)
|
||||
return; // nothing to do
|
||||
|
||||
res = fwrite(buffer, 2, numElems, fptr);
|
||||
|
||||
if (res != numElems)
|
||||
{
|
||||
if (res != numElems) {
|
||||
throw runtime_error("Error while writing to a wav file.");
|
||||
}
|
||||
bytesWritten += 2 * numElems;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Note the file is mostly a copy paste of the WavFile.h from SoundTouch library. It was
|
||||
// Note the file is mostly a copy paste of the WavFile.h from SoundTouch library. It was
|
||||
// shrunken to support only output 16 bits wav files
|
||||
|
||||
#ifndef WAVFILE_H
|
||||
|
@ -26,44 +26,44 @@
|
|||
|
||||
#ifndef uint
|
||||
typedef unsigned int uint;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/// WAV audio file 'riff' section header
|
||||
typedef struct
|
||||
typedef struct
|
||||
{
|
||||
char riff_char[4];
|
||||
int package_len;
|
||||
int package_len;
|
||||
char wave[4];
|
||||
} WavRiff;
|
||||
|
||||
/// WAV audio file 'format' section header
|
||||
typedef struct
|
||||
typedef struct
|
||||
{
|
||||
char fmt[4];
|
||||
int format_len;
|
||||
char fmt[4];
|
||||
int format_len;
|
||||
short fixed;
|
||||
short channel_number;
|
||||
int sample_rate;
|
||||
int byte_rate;
|
||||
int sample_rate;
|
||||
int byte_rate;
|
||||
short byte_per_sample;
|
||||
short bits_per_sample;
|
||||
} WavFormat;
|
||||
|
||||
/// WAV audio file 'data' section header
|
||||
typedef struct
|
||||
typedef struct
|
||||
{
|
||||
char data_field[4];
|
||||
uint data_len;
|
||||
char data_field[4];
|
||||
uint data_len;
|
||||
} WavData;
|
||||
|
||||
|
||||
/// WAV audio file header
|
||||
typedef struct
|
||||
typedef struct
|
||||
{
|
||||
WavRiff riff;
|
||||
WavRiff riff;
|
||||
WavFormat format;
|
||||
WavData data;
|
||||
WavData data;
|
||||
} WavHeader;
|
||||
|
||||
|
||||
|
@ -91,12 +91,12 @@ private:
|
|||
void writeHeader();
|
||||
|
||||
public:
|
||||
/// Constructor: Creates a new WAV file. Throws a 'runtime_error' exception
|
||||
/// Constructor: Creates a new WAV file. Throws a 'runtime_error' exception
|
||||
/// if file creation fails.
|
||||
WavOutFile(const char *fileName, ///< Filename
|
||||
int sampleRate, ///< Sample rate (e.g. 44100 etc)
|
||||
int bits, ///< Bits per sample (8 or 16 bits)
|
||||
int channels ///< Number of channels (1=mono, 2=stereo)
|
||||
WavOutFile(const char *fileName, ///< Filename
|
||||
int sampleRate, ///< Sample rate (e.g. 44100 etc)
|
||||
int bits, ///< Bits per sample (8 or 16 bits)
|
||||
int channels ///< Number of channels (1=mono, 2=stereo)
|
||||
);
|
||||
|
||||
/// Destructor: Finalizes & closes the WAV file.
|
||||
|
@ -104,10 +104,9 @@ public:
|
|||
|
||||
/// Write data to WAV file. Throws a 'runtime_error' exception if writing to
|
||||
/// file fails.
|
||||
void write(const short *buffer, ///< Pointer to sample data buffer.
|
||||
int numElems ///< How many array items are to be written to file.
|
||||
void write(const short *buffer, ///< Pointer to sample data buffer.
|
||||
int numElems ///< How many array items are to be written to file.
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -22,81 +22,77 @@
|
|||
#include "soundtouch/source/SoundStretch/WavFile.h"
|
||||
#endif
|
||||
|
||||
static WavOutFile* _new_WavOutFile( const char* destfile )
|
||||
static WavOutFile *_new_WavOutFile(const char *destfile)
|
||||
{
|
||||
return new WavOutFile( destfile, 48000, 16, 2 );
|
||||
return new WavOutFile(destfile, 48000, 16, 2);
|
||||
}
|
||||
|
||||
namespace WaveDump
|
||||
{
|
||||
static WavOutFile* m_CoreWav[2][CoreSrc_Count] = { NULL };
|
||||
static WavOutFile *m_CoreWav[2][CoreSrc_Count] = {NULL};
|
||||
|
||||
static const char* m_tbl_CoreOutputTypeNames[CoreSrc_Count] =
|
||||
{
|
||||
"Input",
|
||||
"DryVoiceMix",
|
||||
"WetVoiceMix",
|
||||
"PreReverb",
|
||||
"PostReverb",
|
||||
"External"
|
||||
};
|
||||
static const char *m_tbl_CoreOutputTypeNames[CoreSrc_Count] =
|
||||
{
|
||||
"Input",
|
||||
"DryVoiceMix",
|
||||
"WetVoiceMix",
|
||||
"PreReverb",
|
||||
"PostReverb",
|
||||
"External"};
|
||||
|
||||
void Open()
|
||||
{
|
||||
if( !IsDevBuild ) return;
|
||||
if( !WaveLog() ) return;
|
||||
void Open()
|
||||
{
|
||||
if (!IsDevBuild)
|
||||
return;
|
||||
if (!WaveLog())
|
||||
return;
|
||||
|
||||
char wavfilename[256];
|
||||
char wavfilename[256];
|
||||
|
||||
for( uint cidx=0; cidx<2; cidx++ )
|
||||
{
|
||||
for( int srcidx=0; srcidx<CoreSrc_Count; srcidx++ )
|
||||
{
|
||||
safe_delete( m_CoreWav[cidx][srcidx] );
|
||||
for (uint cidx = 0; cidx < 2; cidx++) {
|
||||
for (int srcidx = 0; srcidx < CoreSrc_Count; srcidx++) {
|
||||
safe_delete(m_CoreWav[cidx][srcidx]);
|
||||
#ifdef __POSIX__
|
||||
sprintf( wavfilename, "logs/spu2x-Core%d-%s.wav",
|
||||
cidx, m_tbl_CoreOutputTypeNames[ srcidx ] );
|
||||
sprintf(wavfilename, "logs/spu2x-Core%d-%s.wav",
|
||||
cidx, m_tbl_CoreOutputTypeNames[srcidx]);
|
||||
#else
|
||||
sprintf( wavfilename, "logs\\spu2x-Core%d-%s.wav",
|
||||
cidx, m_tbl_CoreOutputTypeNames[ srcidx ] );
|
||||
sprintf(wavfilename, "logs\\spu2x-Core%d-%s.wav",
|
||||
cidx, m_tbl_CoreOutputTypeNames[srcidx]);
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
m_CoreWav[cidx][srcidx] = _new_WavOutFile( wavfilename );
|
||||
}
|
||||
catch( std::runtime_error& ex )
|
||||
{
|
||||
printf( "SPU2-X > %s.\n\tWave Log for this core source disabled.", ex.what() );
|
||||
m_CoreWav[cidx][srcidx] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
m_CoreWav[cidx][srcidx] = _new_WavOutFile(wavfilename);
|
||||
} catch (std::runtime_error &ex) {
|
||||
printf("SPU2-X > %s.\n\tWave Log for this core source disabled.", ex.what());
|
||||
m_CoreWav[cidx][srcidx] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
if( !IsDevBuild ) return;
|
||||
for( uint cidx=0; cidx<2; cidx++ )
|
||||
{
|
||||
for( int srcidx=0; srcidx<CoreSrc_Count; srcidx++ )
|
||||
{
|
||||
safe_delete( m_CoreWav[cidx][srcidx] );
|
||||
}
|
||||
}
|
||||
}
|
||||
void Close()
|
||||
{
|
||||
if (!IsDevBuild)
|
||||
return;
|
||||
for (uint cidx = 0; cidx < 2; cidx++) {
|
||||
for (int srcidx = 0; srcidx < CoreSrc_Count; srcidx++) {
|
||||
safe_delete(m_CoreWav[cidx][srcidx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WriteCore( uint coreidx, CoreSourceType src, const StereoOut16& sample )
|
||||
{
|
||||
if( !IsDevBuild ) return;
|
||||
if( m_CoreWav[coreidx][src] != NULL )
|
||||
m_CoreWav[coreidx][src]->write( (s16*)&sample, 2 );
|
||||
}
|
||||
void WriteCore(uint coreidx, CoreSourceType src, const StereoOut16 &sample)
|
||||
{
|
||||
if (!IsDevBuild)
|
||||
return;
|
||||
if (m_CoreWav[coreidx][src] != NULL)
|
||||
m_CoreWav[coreidx][src]->write((s16 *)&sample, 2);
|
||||
}
|
||||
|
||||
void WriteCore( uint coreidx, CoreSourceType src, s16 left, s16 right )
|
||||
{
|
||||
WriteCore( coreidx, src, StereoOut16( left, right ) );
|
||||
}
|
||||
void WriteCore(uint coreidx, CoreSourceType src, s16 left, s16 right)
|
||||
{
|
||||
WriteCore(coreidx, src, StereoOut16(left, right));
|
||||
}
|
||||
}
|
||||
|
||||
#include "Utilities/Threading.h"
|
||||
|
@ -105,37 +101,35 @@ using namespace Threading;
|
|||
|
||||
bool WavRecordEnabled = false;
|
||||
|
||||
static WavOutFile* m_wavrecord = NULL;
|
||||
static Mutex WavRecordMutex;
|
||||
static WavOutFile *m_wavrecord = NULL;
|
||||
static Mutex WavRecordMutex;
|
||||
|
||||
void RecordStart()
|
||||
{
|
||||
WavRecordEnabled = false;
|
||||
WavRecordEnabled = false;
|
||||
|
||||
try
|
||||
{
|
||||
ScopedLock lock( WavRecordMutex );
|
||||
safe_delete( m_wavrecord );
|
||||
m_wavrecord = new WavOutFile( "recording.wav", 48000, 16, 2 );
|
||||
WavRecordEnabled = true;
|
||||
}
|
||||
catch( std::runtime_error& )
|
||||
{
|
||||
m_wavrecord = NULL; // not needed, but what the heck. :)
|
||||
SysMessage("SPU2-X couldn't open file for recording: %s.\nRecording to wavfile disabled.", "recording.wav");
|
||||
}
|
||||
try {
|
||||
ScopedLock lock(WavRecordMutex);
|
||||
safe_delete(m_wavrecord);
|
||||
m_wavrecord = new WavOutFile("recording.wav", 48000, 16, 2);
|
||||
WavRecordEnabled = true;
|
||||
} catch (std::runtime_error &) {
|
||||
m_wavrecord = NULL; // not needed, but what the heck. :)
|
||||
SysMessage("SPU2-X couldn't open file for recording: %s.\nRecording to wavfile disabled.", "recording.wav");
|
||||
}
|
||||
}
|
||||
|
||||
void RecordStop()
|
||||
{
|
||||
WavRecordEnabled = false;
|
||||
ScopedLock lock( WavRecordMutex );
|
||||
safe_delete( m_wavrecord );
|
||||
WavRecordEnabled = false;
|
||||
ScopedLock lock(WavRecordMutex);
|
||||
safe_delete(m_wavrecord);
|
||||
}
|
||||
|
||||
void RecordWrite( const StereoOut16& sample )
|
||||
void RecordWrite(const StereoOut16 &sample)
|
||||
{
|
||||
ScopedLock lock( WavRecordMutex );
|
||||
if( m_wavrecord == NULL ) return;
|
||||
m_wavrecord->write( (s16*)&sample, 2 );
|
||||
ScopedLock lock(WavRecordMutex);
|
||||
if (m_wavrecord == NULL)
|
||||
return;
|
||||
m_wavrecord->write((s16 *)&sample, 2);
|
||||
}
|
||||
|
|
|
@ -22,48 +22,45 @@
|
|||
|
||||
static LRESULT WINAPI AboutProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch(uMsg)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
wchar_t outstr[256];
|
||||
if( IsDevBuild )
|
||||
swprintf_s( outstr, L"Build %lld -- Compiled on " _T(__DATE__), SVN_REV );
|
||||
else
|
||||
swprintf_s( outstr, L"Release v%d.%d -- Compiled on " _T(__DATE__),
|
||||
VersionInfo::Release, VersionInfo::Revision );
|
||||
switch (uMsg) {
|
||||
case WM_INITDIALOG: {
|
||||
wchar_t outstr[256];
|
||||
if (IsDevBuild)
|
||||
swprintf_s(outstr, L"Build %lld -- Compiled on " _T(__DATE__), SVN_REV);
|
||||
else
|
||||
swprintf_s(outstr, L"Release v%d.%d -- Compiled on " _T(__DATE__),
|
||||
VersionInfo::Release, VersionInfo::Revision);
|
||||
|
||||
SetWindowText( GetDlgItem(hDlg, IDC_LABEL_VERSION_INFO), outstr );
|
||||
ShowWindow( hDlg, true );
|
||||
}
|
||||
return TRUE;
|
||||
SetWindowText(GetDlgItem(hDlg, IDC_LABEL_VERSION_INFO), outstr);
|
||||
ShowWindow(hDlg, true);
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
case WM_COMMAND:
|
||||
switch( LOWORD(wParam) )
|
||||
{
|
||||
case IDOK:
|
||||
EndDialog(hDlg, TRUE );
|
||||
return TRUE;
|
||||
case WM_COMMAND:
|
||||
switch (LOWORD(wParam)) {
|
||||
case IDOK:
|
||||
EndDialog(hDlg, TRUE);
|
||||
return TRUE;
|
||||
|
||||
case IDC_LINK_WEBSITE:
|
||||
ShellExecute(hDlg, L"open", L"http://www.pcsx2.net/",
|
||||
NULL, NULL, SW_SHOWNORMAL);
|
||||
return TRUE;
|
||||
case IDC_LINK_WEBSITE:
|
||||
ShellExecute(hDlg, L"open", L"http://www.pcsx2.net/",
|
||||
NULL, NULL, SW_SHOWNORMAL);
|
||||
return TRUE;
|
||||
|
||||
case IDC_LINK_GOOGLECODE:
|
||||
ShellExecute(hDlg, L"open", L"https://github.com/PCSX2/pcsx2",
|
||||
NULL, NULL, SW_SHOWNORMAL);
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case IDC_LINK_GOOGLECODE:
|
||||
ShellExecute(hDlg, L"open", L"https://github.com/PCSX2/pcsx2",
|
||||
NULL, NULL, SW_SHOWNORMAL);
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void AboutBox()
|
||||
{
|
||||
DialogBox( hInstance, MAKEINTRESOURCE(IDD_ABOUT), GetActiveWindow(), (DLGPROC)AboutProc );
|
||||
DialogBox(hInstance, MAKEINTRESOURCE(IDD_ABOUT), GetActiveWindow(), (DLGPROC)AboutProc);
|
||||
}
|
||||
|
|
|
@ -24,38 +24,38 @@ extern uptr gsWindowHandle;
|
|||
|
||||
void SysMessage(const char *fmt, ...)
|
||||
{
|
||||
va_list list;
|
||||
char tmp[512];
|
||||
wchar_t wtmp[512];
|
||||
va_list list;
|
||||
char tmp[512];
|
||||
wchar_t wtmp[512];
|
||||
|
||||
va_start(list,fmt);
|
||||
vsprintf_s(tmp,fmt,list);
|
||||
va_end(list);
|
||||
swprintf_s(wtmp, L"%S", tmp);
|
||||
MessageBox( (!!gsWindowHandle) ? (HWND)gsWindowHandle : GetActiveWindow(), wtmp,
|
||||
L"SPU2-X System Message", MB_OK | MB_SETFOREGROUND);
|
||||
va_start(list, fmt);
|
||||
vsprintf_s(tmp, fmt, list);
|
||||
va_end(list);
|
||||
swprintf_s(wtmp, L"%S", tmp);
|
||||
MessageBox((!!gsWindowHandle) ? (HWND)gsWindowHandle : GetActiveWindow(), wtmp,
|
||||
L"SPU2-X System Message", MB_OK | MB_SETFOREGROUND);
|
||||
}
|
||||
|
||||
void SysMessage(const wchar_t *fmt, ...)
|
||||
{
|
||||
va_list list;
|
||||
va_start(list,fmt);
|
||||
wxString wtmp;
|
||||
wtmp.PrintfV( fmt, list );
|
||||
va_end(list);
|
||||
MessageBox( (!!gsWindowHandle) ? (HWND)gsWindowHandle : GetActiveWindow(), wtmp,
|
||||
L"SPU2-X System Message", MB_OK | MB_SETFOREGROUND);
|
||||
va_list list;
|
||||
va_start(list, fmt);
|
||||
wxString wtmp;
|
||||
wtmp.PrintfV(fmt, list);
|
||||
va_end(list);
|
||||
MessageBox((!!gsWindowHandle) ? (HWND)gsWindowHandle : GetActiveWindow(), wtmp,
|
||||
L"SPU2-X System Message", MB_OK | MB_SETFOREGROUND);
|
||||
}
|
||||
|
||||
//////
|
||||
|
||||
#include "Utilities/Path.h"
|
||||
|
||||
static wxString CfgFile( L"inis/SPU2-X.ini" );
|
||||
static wxString CfgFile(L"inis/SPU2-X.ini");
|
||||
|
||||
void CfgSetSettingsDir( const char* dir )
|
||||
void CfgSetSettingsDir(const char *dir)
|
||||
{
|
||||
CfgFile = Path::Combine( (dir==NULL) ? wxString(L"inis") : wxString(dir, wxConvFile), L"SPU2-X.ini" );
|
||||
CfgFile = Path::Combine((dir == NULL) ? wxString(L"inis") : wxString(dir, wxConvFile), L"SPU2-X.ini");
|
||||
}
|
||||
|
||||
|
||||
|
@ -74,24 +74,24 @@ void CfgSetSettingsDir( const char* dir )
|
|||
\*_____________________________________________*/
|
||||
|
||||
|
||||
void CfgWriteBool(const TCHAR* Section, const TCHAR* Name, bool Value)
|
||||
void CfgWriteBool(const TCHAR *Section, const TCHAR *Name, bool Value)
|
||||
{
|
||||
const TCHAR *Data = Value ? L"TRUE" : L"FALSE";
|
||||
WritePrivateProfileString( Section, Name, Data, CfgFile );
|
||||
const TCHAR *Data = Value ? L"TRUE" : L"FALSE";
|
||||
WritePrivateProfileString(Section, Name, Data, CfgFile);
|
||||
}
|
||||
|
||||
void CfgWriteInt(const TCHAR* Section, const TCHAR* Name, int Value)
|
||||
void CfgWriteInt(const TCHAR *Section, const TCHAR *Name, int Value)
|
||||
{
|
||||
TCHAR Data[32];
|
||||
_itow( Value, Data, 10 );
|
||||
WritePrivateProfileString(Section,Name,Data,CfgFile);
|
||||
TCHAR Data[32];
|
||||
_itow(Value, Data, 10);
|
||||
WritePrivateProfileString(Section, Name, Data, CfgFile);
|
||||
}
|
||||
|
||||
void CfgWriteFloat(const TCHAR* Section, const TCHAR* Name, float Value)
|
||||
void CfgWriteFloat(const TCHAR *Section, const TCHAR *Name, float Value)
|
||||
{
|
||||
TCHAR Data[32];
|
||||
_swprintf(Data, L"%f", Value);
|
||||
WritePrivateProfileString(Section, Name, Data, CfgFile);
|
||||
TCHAR Data[32];
|
||||
_swprintf(Data, L"%f", Value);
|
||||
WritePrivateProfileString(Section, Name, Data, CfgFile);
|
||||
}
|
||||
|
||||
/*void CfgWriteStr(const TCHAR* Section, const TCHAR* Name, const TCHAR *Data)
|
||||
|
@ -99,94 +99,99 @@ void CfgWriteFloat(const TCHAR* Section, const TCHAR* Name, float Value)
|
|||
WritePrivateProfileString( Section, Name, Data, CfgFile );
|
||||
}*/
|
||||
|
||||
void CfgWriteStr(const TCHAR* Section, const TCHAR* Name, const wxString& Data)
|
||||
void CfgWriteStr(const TCHAR *Section, const TCHAR *Name, const wxString &Data)
|
||||
{
|
||||
WritePrivateProfileString( Section, Name, Data, CfgFile );
|
||||
WritePrivateProfileString(Section, Name, Data, CfgFile);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
bool CfgReadBool(const TCHAR *Section,const TCHAR* Name, bool Default)
|
||||
bool CfgReadBool(const TCHAR *Section, const TCHAR *Name, bool Default)
|
||||
{
|
||||
TCHAR Data[255] = {0};
|
||||
TCHAR Data[255] = {0};
|
||||
|
||||
GetPrivateProfileString( Section, Name, L"", Data, 255, CfgFile );
|
||||
Data[254]=0;
|
||||
if(wcslen(Data)==0) {
|
||||
CfgWriteBool(Section,Name,Default);
|
||||
return Default;
|
||||
}
|
||||
GetPrivateProfileString(Section, Name, L"", Data, 255, CfgFile);
|
||||
Data[254] = 0;
|
||||
if (wcslen(Data) == 0) {
|
||||
CfgWriteBool(Section, Name, Default);
|
||||
return Default;
|
||||
}
|
||||
|
||||
if(wcscmp(Data,L"1")==0) return true;
|
||||
if(wcscmp(Data,L"Y")==0) return true;
|
||||
if(wcscmp(Data,L"T")==0) return true;
|
||||
if(wcscmp(Data,L"YES")==0) return true;
|
||||
if(wcscmp(Data,L"TRUE")==0) return true;
|
||||
return false;
|
||||
if (wcscmp(Data, L"1") == 0)
|
||||
return true;
|
||||
if (wcscmp(Data, L"Y") == 0)
|
||||
return true;
|
||||
if (wcscmp(Data, L"T") == 0)
|
||||
return true;
|
||||
if (wcscmp(Data, L"YES") == 0)
|
||||
return true;
|
||||
if (wcscmp(Data, L"TRUE") == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int CfgReadInt(const TCHAR* Section, const TCHAR* Name,int Default)
|
||||
int CfgReadInt(const TCHAR *Section, const TCHAR *Name, int Default)
|
||||
{
|
||||
TCHAR Data[255]={0};
|
||||
GetPrivateProfileString(Section,Name,L"",Data,255,CfgFile);
|
||||
Data[254]=0;
|
||||
TCHAR Data[255] = {0};
|
||||
GetPrivateProfileString(Section, Name, L"", Data, 255, CfgFile);
|
||||
Data[254] = 0;
|
||||
|
||||
if(wcslen(Data)==0) {
|
||||
CfgWriteInt(Section,Name,Default);
|
||||
return Default;
|
||||
}
|
||||
if (wcslen(Data) == 0) {
|
||||
CfgWriteInt(Section, Name, Default);
|
||||
return Default;
|
||||
}
|
||||
|
||||
return _wtoi(Data);
|
||||
return _wtoi(Data);
|
||||
}
|
||||
|
||||
float CfgReadFloat(const TCHAR* Section, const TCHAR* Name, float Default)
|
||||
float CfgReadFloat(const TCHAR *Section, const TCHAR *Name, float Default)
|
||||
{
|
||||
TCHAR Data[255] = { 0 };
|
||||
GetPrivateProfileString(Section, Name, L"", Data, 255, CfgFile);
|
||||
Data[254] = 0;
|
||||
TCHAR Data[255] = {0};
|
||||
GetPrivateProfileString(Section, Name, L"", Data, 255, CfgFile);
|
||||
Data[254] = 0;
|
||||
|
||||
if (wcslen(Data) == 0) {
|
||||
CfgWriteFloat(Section, Name, Default);
|
||||
return Default;
|
||||
}
|
||||
if (wcslen(Data) == 0) {
|
||||
CfgWriteFloat(Section, Name, Default);
|
||||
return Default;
|
||||
}
|
||||
|
||||
return (float)_wtof(Data);
|
||||
return (float)_wtof(Data);
|
||||
}
|
||||
|
||||
void CfgReadStr(const TCHAR* Section, const TCHAR* Name, TCHAR* Data, int DataSize, const TCHAR* Default)
|
||||
void CfgReadStr(const TCHAR *Section, const TCHAR *Name, TCHAR *Data, int DataSize, const TCHAR *Default)
|
||||
{
|
||||
GetPrivateProfileString(Section,Name,L"",Data,DataSize,CfgFile);
|
||||
GetPrivateProfileString(Section, Name, L"", Data, DataSize, CfgFile);
|
||||
|
||||
if(wcslen(Data)==0) {
|
||||
swprintf_s( Data, DataSize, L"%s", Default );
|
||||
CfgWriteStr( Section, Name, Data );
|
||||
}
|
||||
if (wcslen(Data) == 0) {
|
||||
swprintf_s(Data, DataSize, L"%s", Default);
|
||||
CfgWriteStr(Section, Name, Data);
|
||||
}
|
||||
}
|
||||
|
||||
void CfgReadStr(const TCHAR* Section, const TCHAR* Name, wxString& Data, const TCHAR* Default)
|
||||
void CfgReadStr(const TCHAR *Section, const TCHAR *Name, wxString &Data, const TCHAR *Default)
|
||||
{
|
||||
wchar_t workspace[512];
|
||||
GetPrivateProfileString(Section,Name,L"",workspace,ArraySize(workspace),CfgFile);
|
||||
wchar_t workspace[512];
|
||||
GetPrivateProfileString(Section, Name, L"", workspace, ArraySize(workspace), CfgFile);
|
||||
|
||||
Data = workspace;
|
||||
Data = workspace;
|
||||
|
||||
if(Data.empty())
|
||||
{
|
||||
Data = Default;
|
||||
CfgWriteStr( Section, Name, Default );
|
||||
}
|
||||
if (Data.empty()) {
|
||||
Data = Default;
|
||||
CfgWriteStr(Section, Name, Default);
|
||||
}
|
||||
}
|
||||
|
||||
// Tries to read the requested value.
|
||||
// Returns FALSE if the value isn't found.
|
||||
bool CfgFindName( const TCHAR *Section, const TCHAR* Name)
|
||||
bool CfgFindName(const TCHAR *Section, const TCHAR *Name)
|
||||
{
|
||||
// Only load 24 characters. No need to load more.
|
||||
TCHAR Data[24]={0};
|
||||
GetPrivateProfileString(Section,Name,L"",Data,24,CfgFile);
|
||||
Data[23]=0;
|
||||
// Only load 24 characters. No need to load more.
|
||||
TCHAR Data[24] = {0};
|
||||
GetPrivateProfileString(Section, Name, L"", Data, 24, CfgFile);
|
||||
Data[23] = 0;
|
||||
|
||||
if(wcslen(Data)==0) return false;
|
||||
return true;
|
||||
if (wcslen(Data) == 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -40,9 +40,9 @@ int Interpolation = 4;
|
|||
|
||||
bool EffectsDisabled = false;
|
||||
|
||||
float FinalVolume; // Global
|
||||
float FinalVolume; // Global
|
||||
bool AdvancedVolumeControl;
|
||||
float VolumeAdjustFLdb; // decibels settings, cos audiophiles love that
|
||||
float VolumeAdjustFLdb; // decibels settings, cos audiophiles love that
|
||||
float VolumeAdjustCdb;
|
||||
float VolumeAdjustFRdb;
|
||||
float VolumeAdjustBLdb;
|
||||
|
@ -50,7 +50,7 @@ float VolumeAdjustBRdb;
|
|||
float VolumeAdjustSLdb;
|
||||
float VolumeAdjustSRdb;
|
||||
float VolumeAdjustLFEdb;
|
||||
float VolumeAdjustFL; // linear coefs calcualted from decibels,
|
||||
float VolumeAdjustFL; // linear coefs calcualted from decibels,
|
||||
float VolumeAdjustC;
|
||||
float VolumeAdjustFR;
|
||||
float VolumeAdjustBL;
|
||||
|
@ -65,7 +65,7 @@ bool postprocess_filter_dealias = false;
|
|||
|
||||
// OUTPUT
|
||||
int SndOutLatencyMS = 100;
|
||||
int SynchMode = 0; // Time Stretch, Async or Disabled
|
||||
int SynchMode = 0; // Time Stretch, Async or Disabled
|
||||
|
||||
u32 OutputModule = 0;
|
||||
|
||||
|
@ -74,7 +74,7 @@ CONFIG_XAUDIO2 Config_XAudio2;
|
|||
|
||||
// DSP
|
||||
bool dspPluginEnabled = false;
|
||||
int dspPluginModule = 0;
|
||||
int dspPluginModule = 0;
|
||||
wchar_t dspPlugin[256];
|
||||
|
||||
int numSpeakers = 0;
|
||||
|
@ -85,344 +85,324 @@ int dplLevel = 0;
|
|||
|
||||
void ReadSettings()
|
||||
{
|
||||
Interpolation = CfgReadInt( L"MIXING",L"Interpolation", 4 );
|
||||
Interpolation = CfgReadInt(L"MIXING", L"Interpolation", 4);
|
||||
|
||||
EffectsDisabled = CfgReadBool( L"MIXING", L"Disable_Effects", false );
|
||||
postprocess_filter_dealias = CfgReadBool( L"MIXING", L"DealiasFilter", false );
|
||||
FinalVolume = ((float)CfgReadInt( L"MIXING", L"FinalVolume", 100 )) / 100;
|
||||
if ( FinalVolume > 1.0f) FinalVolume = 1.0f;
|
||||
EffectsDisabled = CfgReadBool(L"MIXING", L"Disable_Effects", false);
|
||||
postprocess_filter_dealias = CfgReadBool(L"MIXING", L"DealiasFilter", false);
|
||||
FinalVolume = ((float)CfgReadInt(L"MIXING", L"FinalVolume", 100)) / 100;
|
||||
if (FinalVolume > 1.0f)
|
||||
FinalVolume = 1.0f;
|
||||
|
||||
AdvancedVolumeControl = CfgReadBool(L"MIXING", L"AdvancedVolumeControl", false);
|
||||
VolumeAdjustCdb = CfgReadFloat(L"MIXING", L"VolumeAdjustC(dB)", 0);
|
||||
VolumeAdjustFLdb = CfgReadFloat(L"MIXING", L"VolumeAdjustFL(dB)", 0);
|
||||
VolumeAdjustFRdb = CfgReadFloat(L"MIXING", L"VolumeAdjustFR(dB)", 0);
|
||||
VolumeAdjustBLdb = CfgReadFloat(L"MIXING", L"VolumeAdjustBL(dB)", 0);
|
||||
VolumeAdjustBRdb = CfgReadFloat(L"MIXING", L"VolumeAdjustBR(dB)", 0);
|
||||
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);
|
||||
VolumeAdjustBL = powf(10, VolumeAdjustBLdb / 10);
|
||||
VolumeAdjustBR = powf(10, VolumeAdjustBRdb / 10);
|
||||
VolumeAdjustSL = powf(10, VolumeAdjustSLdb / 10);
|
||||
VolumeAdjustSR = powf(10, VolumeAdjustSRdb / 10);
|
||||
VolumeAdjustLFE = powf(10, VolumeAdjustLFEdb / 10);
|
||||
AdvancedVolumeControl = CfgReadBool(L"MIXING", L"AdvancedVolumeControl", false);
|
||||
VolumeAdjustCdb = CfgReadFloat(L"MIXING", L"VolumeAdjustC(dB)", 0);
|
||||
VolumeAdjustFLdb = CfgReadFloat(L"MIXING", L"VolumeAdjustFL(dB)", 0);
|
||||
VolumeAdjustFRdb = CfgReadFloat(L"MIXING", L"VolumeAdjustFR(dB)", 0);
|
||||
VolumeAdjustBLdb = CfgReadFloat(L"MIXING", L"VolumeAdjustBL(dB)", 0);
|
||||
VolumeAdjustBRdb = CfgReadFloat(L"MIXING", L"VolumeAdjustBR(dB)", 0);
|
||||
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);
|
||||
VolumeAdjustBL = powf(10, VolumeAdjustBLdb / 10);
|
||||
VolumeAdjustBR = powf(10, VolumeAdjustBRdb / 10);
|
||||
VolumeAdjustSL = powf(10, VolumeAdjustSLdb / 10);
|
||||
VolumeAdjustSR = powf(10, VolumeAdjustSRdb / 10);
|
||||
VolumeAdjustLFE = powf(10, VolumeAdjustLFEdb / 10);
|
||||
|
||||
SynchMode = CfgReadInt( L"OUTPUT", L"Synch_Mode", 0);
|
||||
numSpeakers = CfgReadInt( L"OUTPUT", L"SpeakerConfiguration", 0);
|
||||
dplLevel = CfgReadInt( L"OUTPUT", L"DplDecodingLevel", 0);
|
||||
SndOutLatencyMS = CfgReadInt(L"OUTPUT",L"Latency", 100);
|
||||
SynchMode = CfgReadInt(L"OUTPUT", L"Synch_Mode", 0);
|
||||
numSpeakers = CfgReadInt(L"OUTPUT", L"SpeakerConfiguration", 0);
|
||||
dplLevel = CfgReadInt(L"OUTPUT", L"DplDecodingLevel", 0);
|
||||
SndOutLatencyMS = CfgReadInt(L"OUTPUT", L"Latency", 100);
|
||||
|
||||
if((SynchMode == 0) && (SndOutLatencyMS < LATENCY_MIN_TS)) // can't use low-latency with timestretcher atm
|
||||
SndOutLatencyMS = LATENCY_MIN_TS;
|
||||
else if(SndOutLatencyMS < LATENCY_MIN)
|
||||
SndOutLatencyMS = LATENCY_MIN;
|
||||
if ((SynchMode == 0) && (SndOutLatencyMS < LATENCY_MIN_TS)) // can't use low-latency with timestretcher atm
|
||||
SndOutLatencyMS = LATENCY_MIN_TS;
|
||||
else if (SndOutLatencyMS < LATENCY_MIN)
|
||||
SndOutLatencyMS = LATENCY_MIN;
|
||||
|
||||
wchar_t omodid[128];
|
||||
wchar_t omodid[128];
|
||||
|
||||
// portaudio occasionally has issues selecting the proper default audio device.
|
||||
// let's use xaudio2 until this is sorted (rama)
|
||||
// portaudio occasionally has issues selecting the proper default audio device.
|
||||
// let's use xaudio2 until this is sorted (rama)
|
||||
|
||||
// CfgReadStr(L"OUTPUT", L"Output_Module", omodid, 127, PortaudioOut->GetIdent());
|
||||
if (IsWindows8OrGreater())
|
||||
CfgReadStr(L"OUTPUT", L"Output_Module", omodid, 127, XAudio2Out->GetIdent());
|
||||
else
|
||||
CfgReadStr(L"OUTPUT", L"Output_Module", omodid, 127, XAudio2_27_Out->GetIdent());
|
||||
// CfgReadStr(L"OUTPUT", L"Output_Module", omodid, 127, PortaudioOut->GetIdent());
|
||||
if (IsWindows8OrGreater())
|
||||
CfgReadStr(L"OUTPUT", L"Output_Module", omodid, 127, XAudio2Out->GetIdent());
|
||||
else
|
||||
CfgReadStr(L"OUTPUT", L"Output_Module", omodid, 127, XAudio2_27_Out->GetIdent());
|
||||
|
||||
// find the driver index of this module:
|
||||
OutputModule = FindOutputModuleById( omodid );
|
||||
// find the driver index of this module:
|
||||
OutputModule = FindOutputModuleById(omodid);
|
||||
|
||||
CfgReadStr( L"DSP PLUGIN",L"Filename",dspPlugin,255,L"");
|
||||
dspPluginModule = CfgReadInt(L"DSP PLUGIN",L"ModuleNum",0);
|
||||
dspPluginEnabled= CfgReadBool(L"DSP PLUGIN",L"Enabled",false);
|
||||
CfgReadStr(L"DSP PLUGIN", L"Filename", dspPlugin, 255, L"");
|
||||
dspPluginModule = CfgReadInt(L"DSP PLUGIN", L"ModuleNum", 0);
|
||||
dspPluginEnabled = CfgReadBool(L"DSP PLUGIN", L"Enabled", false);
|
||||
|
||||
// Read DSOUNDOUT and WAVEOUT configs:
|
||||
CfgReadStr( L"WAVEOUT", L"Device", Config_WaveOut.Device, L"default" );
|
||||
Config_WaveOut.NumBuffers = CfgReadInt( L"WAVEOUT", L"Buffer_Count", 4 );
|
||||
// Read DSOUNDOUT and WAVEOUT configs:
|
||||
CfgReadStr(L"WAVEOUT", L"Device", Config_WaveOut.Device, L"default");
|
||||
Config_WaveOut.NumBuffers = CfgReadInt(L"WAVEOUT", L"Buffer_Count", 4);
|
||||
|
||||
DSoundOut->ReadSettings();
|
||||
PortaudioOut->ReadSettings();
|
||||
DSoundOut->ReadSettings();
|
||||
PortaudioOut->ReadSettings();
|
||||
|
||||
SoundtouchCfg::ReadSettings();
|
||||
DebugConfig::ReadSettings();
|
||||
SoundtouchCfg::ReadSettings();
|
||||
DebugConfig::ReadSettings();
|
||||
|
||||
// Sanity Checks
|
||||
// -------------
|
||||
// Sanity Checks
|
||||
// -------------
|
||||
|
||||
Clampify( SndOutLatencyMS, LATENCY_MIN, LATENCY_MAX );
|
||||
Clampify(SndOutLatencyMS, LATENCY_MIN, LATENCY_MAX);
|
||||
|
||||
if( mods[OutputModule] == NULL )
|
||||
{
|
||||
// Unsupported or legacy module.
|
||||
fwprintf( stderr, L"* SPU2-X: Unknown output module '%s' specified in configuration file.\n", omodid );
|
||||
fprintf( stderr, "* SPU2-X: Defaulting to DirectSound (%S).\n", DSoundOut->GetIdent() );
|
||||
OutputModule = FindOutputModuleById( DSoundOut->GetIdent() );
|
||||
}
|
||||
if (mods[OutputModule] == NULL) {
|
||||
// Unsupported or legacy module.
|
||||
fwprintf(stderr, L"* SPU2-X: Unknown output module '%s' specified in configuration file.\n", omodid);
|
||||
fprintf(stderr, "* SPU2-X: Defaulting to DirectSound (%S).\n", DSoundOut->GetIdent());
|
||||
OutputModule = FindOutputModuleById(DSoundOut->GetIdent());
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void WriteSettings()
|
||||
{
|
||||
CfgWriteInt(L"MIXING",L"Interpolation",Interpolation);
|
||||
CfgWriteInt(L"MIXING", L"Interpolation", Interpolation);
|
||||
|
||||
CfgWriteBool(L"MIXING",L"Disable_Effects",EffectsDisabled);
|
||||
CfgWriteBool(L"MIXING",L"DealiasFilter",postprocess_filter_dealias);
|
||||
CfgWriteInt(L"MIXING",L"FinalVolume",(int)(FinalVolume * 100 + 0.5f));
|
||||
CfgWriteBool(L"MIXING", L"Disable_Effects", EffectsDisabled);
|
||||
CfgWriteBool(L"MIXING", L"DealiasFilter", postprocess_filter_dealias);
|
||||
CfgWriteInt(L"MIXING", L"FinalVolume", (int)(FinalVolume * 100 + 0.5f));
|
||||
|
||||
CfgWriteBool(L"MIXING", L"AdvancedVolumeControl", AdvancedVolumeControl);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustC(dB)", VolumeAdjustCdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustFL(dB)", VolumeAdjustFLdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustFR(dB)", VolumeAdjustFRdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustBL(dB)", VolumeAdjustBLdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustBR(dB)", VolumeAdjustBRdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustSL(dB)", VolumeAdjustSLdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustSR(dB)", VolumeAdjustSRdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustLFE(dB)", VolumeAdjustLFEdb);
|
||||
CfgWriteBool(L"MIXING", L"AdvancedVolumeControl", AdvancedVolumeControl);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustC(dB)", VolumeAdjustCdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustFL(dB)", VolumeAdjustFLdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustFR(dB)", VolumeAdjustFRdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustBL(dB)", VolumeAdjustBLdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustBR(dB)", VolumeAdjustBRdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustSL(dB)", VolumeAdjustSLdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustSR(dB)", VolumeAdjustSRdb);
|
||||
CfgWriteFloat(L"MIXING", L"VolumeAdjustLFE(dB)", VolumeAdjustLFEdb);
|
||||
|
||||
CfgWriteStr(L"OUTPUT",L"Output_Module", mods[OutputModule]->GetIdent() );
|
||||
CfgWriteInt(L"OUTPUT",L"Latency", SndOutLatencyMS);
|
||||
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);
|
||||
CfgWriteStr(L"OUTPUT", L"Output_Module", mods[OutputModule]->GetIdent());
|
||||
CfgWriteInt(L"OUTPUT", L"Latency", SndOutLatencyMS);
|
||||
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";
|
||||
CfgWriteStr(L"WAVEOUT",L"Device",Config_WaveOut.Device);
|
||||
CfgWriteInt(L"WAVEOUT",L"Buffer_Count",Config_WaveOut.NumBuffers);
|
||||
if (Config_WaveOut.Device.empty())
|
||||
Config_WaveOut.Device = L"default";
|
||||
CfgWriteStr(L"WAVEOUT", L"Device", Config_WaveOut.Device);
|
||||
CfgWriteInt(L"WAVEOUT", L"Buffer_Count", Config_WaveOut.NumBuffers);
|
||||
|
||||
CfgWriteStr(L"DSP PLUGIN",L"Filename",dspPlugin);
|
||||
CfgWriteInt(L"DSP PLUGIN",L"ModuleNum",dspPluginModule);
|
||||
CfgWriteBool(L"DSP PLUGIN",L"Enabled",dspPluginEnabled);
|
||||
|
||||
PortaudioOut->WriteSettings();
|
||||
DSoundOut->WriteSettings();
|
||||
SoundtouchCfg::WriteSettings();
|
||||
DebugConfig::WriteSettings();
|
||||
CfgWriteStr(L"DSP PLUGIN", L"Filename", dspPlugin);
|
||||
CfgWriteInt(L"DSP PLUGIN", L"ModuleNum", dspPluginModule);
|
||||
CfgWriteBool(L"DSP PLUGIN", L"Enabled", dspPluginEnabled);
|
||||
|
||||
PortaudioOut->WriteSettings();
|
||||
DSoundOut->WriteSettings();
|
||||
SoundtouchCfg::WriteSettings();
|
||||
DebugConfig::WriteSettings();
|
||||
}
|
||||
|
||||
BOOL CALLBACK ConfigProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
|
||||
BOOL CALLBACK ConfigProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
int wmId,wmEvent;
|
||||
wchar_t temp[384]={0};
|
||||
int wmId, wmEvent;
|
||||
wchar_t temp[384] = {0};
|
||||
|
||||
switch(uMsg)
|
||||
{
|
||||
case WM_PAINT:
|
||||
return FALSE;
|
||||
switch (uMsg) {
|
||||
case WM_PAINT:
|
||||
return FALSE;
|
||||
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
SendDialogMsg( hWnd, IDC_INTERPOLATE, CB_RESETCONTENT,0,0 );
|
||||
SendDialogMsg( hWnd, IDC_INTERPOLATE, CB_ADDSTRING,0,(LPARAM) L"0 - Nearest (fastest/bad quality)" );
|
||||
SendDialogMsg( hWnd, IDC_INTERPOLATE, CB_ADDSTRING,0,(LPARAM) L"1 - Linear (simple/okay sound)" );
|
||||
SendDialogMsg( hWnd, IDC_INTERPOLATE, CB_ADDSTRING,0,(LPARAM) L"2 - Cubic (artificial highs)" );
|
||||
SendDialogMsg( hWnd, IDC_INTERPOLATE, CB_ADDSTRING,0,(LPARAM) L"3 - Hermite (better highs)" );
|
||||
SendDialogMsg( hWnd, IDC_INTERPOLATE, CB_ADDSTRING,0,(LPARAM) L"4 - Catmull-Rom (PS2-like/slow)" );
|
||||
SendDialogMsg( hWnd, IDC_INTERPOLATE, CB_SETCURSEL,Interpolation,0 );
|
||||
case WM_INITDIALOG: {
|
||||
SendDialogMsg(hWnd, IDC_INTERPOLATE, CB_RESETCONTENT, 0, 0);
|
||||
SendDialogMsg(hWnd, IDC_INTERPOLATE, CB_ADDSTRING, 0, (LPARAM)L"0 - Nearest (fastest/bad quality)");
|
||||
SendDialogMsg(hWnd, IDC_INTERPOLATE, CB_ADDSTRING, 0, (LPARAM)L"1 - Linear (simple/okay sound)");
|
||||
SendDialogMsg(hWnd, IDC_INTERPOLATE, CB_ADDSTRING, 0, (LPARAM)L"2 - Cubic (artificial highs)");
|
||||
SendDialogMsg(hWnd, IDC_INTERPOLATE, CB_ADDSTRING, 0, (LPARAM)L"3 - Hermite (better highs)");
|
||||
SendDialogMsg(hWnd, IDC_INTERPOLATE, CB_ADDSTRING, 0, (LPARAM)L"4 - Catmull-Rom (PS2-like/slow)");
|
||||
SendDialogMsg(hWnd, IDC_INTERPOLATE, CB_SETCURSEL, Interpolation, 0);
|
||||
|
||||
SendDialogMsg( hWnd, IDC_SYNCHMODE, CB_RESETCONTENT,0,0 );
|
||||
SendDialogMsg( hWnd, IDC_SYNCHMODE, CB_ADDSTRING,0,(LPARAM) L"TimeStretch (Recommended)" );
|
||||
SendDialogMsg( hWnd, IDC_SYNCHMODE, CB_ADDSTRING,0,(LPARAM) L"Async Mix (Breaks some games!)" );
|
||||
SendDialogMsg( hWnd, IDC_SYNCHMODE, CB_ADDSTRING,0,(LPARAM) L"None (Audio can skip.)" );
|
||||
SendDialogMsg( hWnd, IDC_SYNCHMODE, CB_SETCURSEL,SynchMode,0 );
|
||||
|
||||
SendDialogMsg( hWnd, IDC_SPEAKERS, CB_RESETCONTENT,0,0 );
|
||||
SendDialogMsg( hWnd, IDC_SPEAKERS, CB_ADDSTRING,0,(LPARAM) L"Stereo (none, default)" );
|
||||
SendDialogMsg( hWnd, IDC_SPEAKERS, CB_ADDSTRING,0,(LPARAM) L"Quadrafonic" );
|
||||
SendDialogMsg( hWnd, IDC_SPEAKERS, CB_ADDSTRING,0,(LPARAM) L"Surround 5.1" );
|
||||
SendDialogMsg( hWnd, IDC_SPEAKERS, CB_ADDSTRING,0,(LPARAM) L"Surround 7.1" );
|
||||
SendDialogMsg( hWnd, IDC_SPEAKERS, CB_SETCURSEL,numSpeakers,0 );
|
||||
SendDialogMsg(hWnd, IDC_SYNCHMODE, CB_RESETCONTENT, 0, 0);
|
||||
SendDialogMsg(hWnd, IDC_SYNCHMODE, CB_ADDSTRING, 0, (LPARAM)L"TimeStretch (Recommended)");
|
||||
SendDialogMsg(hWnd, IDC_SYNCHMODE, CB_ADDSTRING, 0, (LPARAM)L"Async Mix (Breaks some games!)");
|
||||
SendDialogMsg(hWnd, IDC_SYNCHMODE, CB_ADDSTRING, 0, (LPARAM)L"None (Audio can skip.)");
|
||||
SendDialogMsg(hWnd, IDC_SYNCHMODE, CB_SETCURSEL, SynchMode, 0);
|
||||
|
||||
SendDialogMsg( hWnd, IDC_OUTPUT, CB_RESETCONTENT,0,0 );
|
||||
SendDialogMsg(hWnd, IDC_SPEAKERS, CB_RESETCONTENT, 0, 0);
|
||||
SendDialogMsg(hWnd, IDC_SPEAKERS, CB_ADDSTRING, 0, (LPARAM)L"Stereo (none, default)");
|
||||
SendDialogMsg(hWnd, IDC_SPEAKERS, CB_ADDSTRING, 0, (LPARAM)L"Quadrafonic");
|
||||
SendDialogMsg(hWnd, IDC_SPEAKERS, CB_ADDSTRING, 0, (LPARAM)L"Surround 5.1");
|
||||
SendDialogMsg(hWnd, IDC_SPEAKERS, CB_ADDSTRING, 0, (LPARAM)L"Surround 7.1");
|
||||
SendDialogMsg(hWnd, IDC_SPEAKERS, CB_SETCURSEL, numSpeakers, 0);
|
||||
|
||||
int modidx = 0;
|
||||
while( mods[modidx] != NULL )
|
||||
{
|
||||
swprintf_s( temp, 72, L"%d - %s", modidx, mods[modidx]->GetLongName() );
|
||||
SendDialogMsg( hWnd, IDC_OUTPUT, CB_ADDSTRING,0,(LPARAM)temp );
|
||||
++modidx;
|
||||
}
|
||||
SendDialogMsg( hWnd, IDC_OUTPUT, CB_SETCURSEL, OutputModule, 0 );
|
||||
SendDialogMsg(hWnd, IDC_OUTPUT, CB_RESETCONTENT, 0, 0);
|
||||
|
||||
double minlat = (SynchMode == 0)?LATENCY_MIN_TS:LATENCY_MIN;
|
||||
int minexp = (int)(pow( minlat+1, 1.0/3.0 ) * 128.0);
|
||||
int maxexp = (int)(pow( (double)LATENCY_MAX+2, 1.0/3.0 ) * 128.0);
|
||||
INIT_SLIDER( IDC_LATENCY_SLIDER, minexp, maxexp, 200, 42, 1 );
|
||||
int modidx = 0;
|
||||
while (mods[modidx] != NULL) {
|
||||
swprintf_s(temp, 72, L"%d - %s", modidx, mods[modidx]->GetLongName());
|
||||
SendDialogMsg(hWnd, IDC_OUTPUT, CB_ADDSTRING, 0, (LPARAM)temp);
|
||||
++modidx;
|
||||
}
|
||||
SendDialogMsg(hWnd, IDC_OUTPUT, CB_SETCURSEL, OutputModule, 0);
|
||||
|
||||
SendDialogMsg( hWnd, IDC_LATENCY_SLIDER, TBM_SETPOS, TRUE, (int)((pow( (double)SndOutLatencyMS, 1.0/3.0 ) * 128.0) + 1) );
|
||||
swprintf_s(temp,L"%d ms (avg)",SndOutLatencyMS);
|
||||
SetWindowText(GetDlgItem(hWnd,IDC_LATENCY_LABEL),temp);
|
||||
double minlat = (SynchMode == 0) ? LATENCY_MIN_TS : LATENCY_MIN;
|
||||
int minexp = (int)(pow(minlat + 1, 1.0 / 3.0) * 128.0);
|
||||
int maxexp = (int)(pow((double)LATENCY_MAX + 2, 1.0 / 3.0) * 128.0);
|
||||
INIT_SLIDER(IDC_LATENCY_SLIDER, minexp, maxexp, 200, 42, 1);
|
||||
|
||||
int configvol = (int)(FinalVolume * 100 + 0.5f);
|
||||
INIT_SLIDER( IDC_VOLUME_SLIDER, 0, 100, 10, 42, 1 );
|
||||
SendDialogMsg(hWnd, IDC_LATENCY_SLIDER, TBM_SETPOS, TRUE, (int)((pow((double)SndOutLatencyMS, 1.0 / 3.0) * 128.0) + 1));
|
||||
swprintf_s(temp, L"%d ms (avg)", SndOutLatencyMS);
|
||||
SetWindowText(GetDlgItem(hWnd, IDC_LATENCY_LABEL), temp);
|
||||
|
||||
SendDialogMsg( hWnd, IDC_VOLUME_SLIDER, TBM_SETPOS, TRUE, configvol );
|
||||
swprintf_s(temp,L"%d%%",configvol);
|
||||
SetWindowText(GetDlgItem(hWnd,IDC_VOLUME_LABEL),temp);
|
||||
|
||||
EnableWindow( GetDlgItem( hWnd, IDC_OPEN_CONFIG_SOUNDTOUCH ), (SynchMode == 0) );
|
||||
EnableWindow( GetDlgItem( hWnd, IDC_OPEN_CONFIG_DEBUG ), DebugEnabled );
|
||||
int configvol = (int)(FinalVolume * 100 + 0.5f);
|
||||
INIT_SLIDER(IDC_VOLUME_SLIDER, 0, 100, 10, 42, 1);
|
||||
|
||||
SET_CHECK(IDC_EFFECTS_DISABLE, EffectsDisabled);
|
||||
SET_CHECK(IDC_DEALIASFILTER, postprocess_filter_dealias);
|
||||
SET_CHECK(IDC_DEBUG_ENABLE, DebugEnabled);
|
||||
SET_CHECK(IDC_DSP_ENABLE, dspPluginEnabled);
|
||||
}
|
||||
break;
|
||||
SendDialogMsg(hWnd, IDC_VOLUME_SLIDER, TBM_SETPOS, TRUE, configvol);
|
||||
swprintf_s(temp, L"%d%%", configvol);
|
||||
SetWindowText(GetDlgItem(hWnd, IDC_VOLUME_LABEL), temp);
|
||||
|
||||
case WM_COMMAND:
|
||||
wmId = LOWORD(wParam);
|
||||
wmEvent = HIWORD(wParam);
|
||||
// Parse the menu selections:
|
||||
switch (wmId)
|
||||
{
|
||||
case IDOK:
|
||||
{
|
||||
double res = ((int)SendDialogMsg( hWnd, IDC_LATENCY_SLIDER, TBM_GETPOS, 0, 0 )) / 128.0;
|
||||
SndOutLatencyMS = (int)pow( res, 3.0 );
|
||||
Clampify( SndOutLatencyMS, LATENCY_MIN, LATENCY_MAX );
|
||||
FinalVolume = (float)(SendDialogMsg( hWnd, IDC_VOLUME_SLIDER, TBM_GETPOS, 0, 0 )) / 100;
|
||||
Interpolation = (int)SendDialogMsg( hWnd, IDC_INTERPOLATE, CB_GETCURSEL,0,0 );
|
||||
OutputModule = (int)SendDialogMsg( hWnd, IDC_OUTPUT, CB_GETCURSEL,0,0 );
|
||||
SynchMode = (int)SendDialogMsg( hWnd, IDC_SYNCHMODE, CB_GETCURSEL,0,0 );
|
||||
numSpeakers = (int)SendDialogMsg( hWnd, IDC_SPEAKERS, CB_GETCURSEL,0,0 );
|
||||
EnableWindow(GetDlgItem(hWnd, IDC_OPEN_CONFIG_SOUNDTOUCH), (SynchMode == 0));
|
||||
EnableWindow(GetDlgItem(hWnd, IDC_OPEN_CONFIG_DEBUG), DebugEnabled);
|
||||
|
||||
WriteSettings();
|
||||
EndDialog(hWnd,0);
|
||||
}
|
||||
break;
|
||||
SET_CHECK(IDC_EFFECTS_DISABLE, EffectsDisabled);
|
||||
SET_CHECK(IDC_DEALIASFILTER, postprocess_filter_dealias);
|
||||
SET_CHECK(IDC_DEBUG_ENABLE, DebugEnabled);
|
||||
SET_CHECK(IDC_DSP_ENABLE, dspPluginEnabled);
|
||||
} break;
|
||||
|
||||
case IDCANCEL:
|
||||
EndDialog(hWnd,0);
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
wmId = LOWORD(wParam);
|
||||
wmEvent = HIWORD(wParam);
|
||||
// Parse the menu selections:
|
||||
switch (wmId) {
|
||||
case IDOK: {
|
||||
double res = ((int)SendDialogMsg(hWnd, IDC_LATENCY_SLIDER, TBM_GETPOS, 0, 0)) / 128.0;
|
||||
SndOutLatencyMS = (int)pow(res, 3.0);
|
||||
Clampify(SndOutLatencyMS, LATENCY_MIN, LATENCY_MAX);
|
||||
FinalVolume = (float)(SendDialogMsg(hWnd, IDC_VOLUME_SLIDER, TBM_GETPOS, 0, 0)) / 100;
|
||||
Interpolation = (int)SendDialogMsg(hWnd, IDC_INTERPOLATE, CB_GETCURSEL, 0, 0);
|
||||
OutputModule = (int)SendDialogMsg(hWnd, IDC_OUTPUT, CB_GETCURSEL, 0, 0);
|
||||
SynchMode = (int)SendDialogMsg(hWnd, IDC_SYNCHMODE, CB_GETCURSEL, 0, 0);
|
||||
numSpeakers = (int)SendDialogMsg(hWnd, IDC_SPEAKERS, CB_GETCURSEL, 0, 0);
|
||||
|
||||
case IDC_OUTCONF:
|
||||
{
|
||||
const int module = (int)SendMessage(GetDlgItem(hWnd,IDC_OUTPUT),CB_GETCURSEL,0,0);
|
||||
if( mods[module] == NULL ) break;
|
||||
mods[module]->Configure((uptr)hWnd);
|
||||
}
|
||||
break;
|
||||
WriteSettings();
|
||||
EndDialog(hWnd, 0);
|
||||
} break;
|
||||
|
||||
case IDC_OPEN_CONFIG_DEBUG:
|
||||
{
|
||||
// Quick Hack -- DebugEnabled is re-loaded with the DebugConfig's API,
|
||||
// so we need to override it here:
|
||||
case IDCANCEL:
|
||||
EndDialog(hWnd, 0);
|
||||
break;
|
||||
|
||||
bool dbgtmp = DebugEnabled;
|
||||
DebugConfig::OpenDialog();
|
||||
DebugEnabled = dbgtmp;
|
||||
}
|
||||
break;
|
||||
case IDC_OUTCONF: {
|
||||
const int module = (int)SendMessage(GetDlgItem(hWnd, IDC_OUTPUT), CB_GETCURSEL, 0, 0);
|
||||
if (mods[module] == NULL)
|
||||
break;
|
||||
mods[module]->Configure((uptr)hWnd);
|
||||
} break;
|
||||
|
||||
case IDC_SYNCHMODE:
|
||||
{
|
||||
if(wmEvent == CBN_SELCHANGE)
|
||||
{
|
||||
int sMode = (int)SendDialogMsg( hWnd, IDC_SYNCHMODE, CB_GETCURSEL,0,0 );
|
||||
double minlat = (sMode == 0)?LATENCY_MIN_TS:LATENCY_MIN;
|
||||
int minexp = (int)(pow( minlat+1, 1.0/3.0 ) * 128.0);
|
||||
int maxexp = (int)(pow( (double)LATENCY_MAX+2, 1.0/3.0 ) * 128.0);
|
||||
INIT_SLIDER( IDC_LATENCY_SLIDER, minexp, maxexp, 200, 42, 1 );
|
||||
|
||||
int curpos = (int)SendMessage(GetDlgItem( hWnd, IDC_LATENCY_SLIDER ),TBM_GETPOS,0,0);
|
||||
double res = pow( curpos / 128.0, 3.0 );
|
||||
curpos = (int)res;
|
||||
swprintf_s(temp,L"%d ms (avg)",curpos);
|
||||
SetDlgItemText(hWnd,IDC_LATENCY_LABEL,temp);
|
||||
bool soundtouch = sMode == 0;
|
||||
EnableWindow(GetDlgItem(hWnd, IDC_OPEN_CONFIG_SOUNDTOUCH), soundtouch);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case IDC_OPEN_CONFIG_DEBUG: {
|
||||
// Quick Hack -- DebugEnabled is re-loaded with the DebugConfig's API,
|
||||
// so we need to override it here:
|
||||
|
||||
bool dbgtmp = DebugEnabled;
|
||||
DebugConfig::OpenDialog();
|
||||
DebugEnabled = dbgtmp;
|
||||
} break;
|
||||
|
||||
case IDC_SYNCHMODE: {
|
||||
if (wmEvent == CBN_SELCHANGE) {
|
||||
int sMode = (int)SendDialogMsg(hWnd, IDC_SYNCHMODE, CB_GETCURSEL, 0, 0);
|
||||
double minlat = (sMode == 0) ? LATENCY_MIN_TS : LATENCY_MIN;
|
||||
int minexp = (int)(pow(minlat + 1, 1.0 / 3.0) * 128.0);
|
||||
int maxexp = (int)(pow((double)LATENCY_MAX + 2, 1.0 / 3.0) * 128.0);
|
||||
INIT_SLIDER(IDC_LATENCY_SLIDER, minexp, maxexp, 200, 42, 1);
|
||||
|
||||
int curpos = (int)SendMessage(GetDlgItem(hWnd, IDC_LATENCY_SLIDER), TBM_GETPOS, 0, 0);
|
||||
double res = pow(curpos / 128.0, 3.0);
|
||||
curpos = (int)res;
|
||||
swprintf_s(temp, L"%d ms (avg)", curpos);
|
||||
SetDlgItemText(hWnd, IDC_LATENCY_LABEL, temp);
|
||||
bool soundtouch = sMode == 0;
|
||||
EnableWindow(GetDlgItem(hWnd, IDC_OPEN_CONFIG_SOUNDTOUCH), soundtouch);
|
||||
}
|
||||
} break;
|
||||
|
||||
|
||||
case IDC_OPEN_CONFIG_SOUNDTOUCH:
|
||||
SoundtouchCfg::OpenDialog( hWnd );
|
||||
break;
|
||||
case IDC_OPEN_CONFIG_SOUNDTOUCH:
|
||||
SoundtouchCfg::OpenDialog(hWnd);
|
||||
break;
|
||||
|
||||
HANDLE_CHECK(IDC_EFFECTS_DISABLE,EffectsDisabled);
|
||||
HANDLE_CHECK(IDC_DEALIASFILTER,postprocess_filter_dealias);
|
||||
HANDLE_CHECK(IDC_DSP_ENABLE,dspPluginEnabled);
|
||||
HANDLE_CHECKNB(IDC_DEBUG_ENABLE,DebugEnabled);
|
||||
DebugConfig::EnableControls( hWnd );
|
||||
EnableWindow( GetDlgItem( hWnd, IDC_OPEN_CONFIG_DEBUG ), DebugEnabled );
|
||||
break;
|
||||
HANDLE_CHECK(IDC_EFFECTS_DISABLE, EffectsDisabled);
|
||||
HANDLE_CHECK(IDC_DEALIASFILTER, postprocess_filter_dealias);
|
||||
HANDLE_CHECK(IDC_DSP_ENABLE, dspPluginEnabled);
|
||||
HANDLE_CHECKNB(IDC_DEBUG_ENABLE, DebugEnabled);
|
||||
DebugConfig::EnableControls(hWnd);
|
||||
EnableWindow(GetDlgItem(hWnd, IDC_OPEN_CONFIG_DEBUG), DebugEnabled);
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_HSCROLL:
|
||||
{
|
||||
wmEvent = LOWORD(wParam);
|
||||
HWND hwndDlg = (HWND)lParam;
|
||||
case WM_HSCROLL: {
|
||||
wmEvent = LOWORD(wParam);
|
||||
HWND hwndDlg = (HWND)lParam;
|
||||
|
||||
// TB_THUMBTRACK passes the curpos in wParam. Other messages
|
||||
// have to use TBM_GETPOS, so they will override this assignment (see below)
|
||||
// TB_THUMBTRACK passes the curpos in wParam. Other messages
|
||||
// have to use TBM_GETPOS, so they will override this assignment (see below)
|
||||
|
||||
int curpos = HIWORD( wParam );
|
||||
int curpos = HIWORD(wParam);
|
||||
|
||||
switch( wmEvent )
|
||||
{
|
||||
//case TB_ENDTRACK:
|
||||
//case TB_THUMBPOSITION:
|
||||
case TB_LINEUP:
|
||||
case TB_LINEDOWN:
|
||||
case TB_PAGEUP:
|
||||
case TB_PAGEDOWN:
|
||||
curpos = (int)SendMessage(hwndDlg,TBM_GETPOS,0,0);
|
||||
switch (wmEvent) {
|
||||
//case TB_ENDTRACK:
|
||||
//case TB_THUMBPOSITION:
|
||||
case TB_LINEUP:
|
||||
case TB_LINEDOWN:
|
||||
case TB_PAGEUP:
|
||||
case TB_PAGEDOWN:
|
||||
curpos = (int)SendMessage(hwndDlg, TBM_GETPOS, 0, 0);
|
||||
|
||||
case TB_THUMBTRACK:
|
||||
Clampify( curpos,
|
||||
(int)SendMessage(hwndDlg,TBM_GETRANGEMIN,0,0),
|
||||
(int)SendMessage(hwndDlg,TBM_GETRANGEMAX,0,0)
|
||||
);
|
||||
case TB_THUMBTRACK:
|
||||
Clampify(curpos,
|
||||
(int)SendMessage(hwndDlg, TBM_GETRANGEMIN, 0, 0),
|
||||
(int)SendMessage(hwndDlg, TBM_GETRANGEMAX, 0, 0));
|
||||
|
||||
SendMessage((HWND)lParam,TBM_SETPOS,TRUE,curpos);
|
||||
SendMessage((HWND)lParam, TBM_SETPOS, TRUE, curpos);
|
||||
|
||||
if( hwndDlg == GetDlgItem( hWnd, IDC_LATENCY_SLIDER ) )
|
||||
{
|
||||
double res = pow( curpos / 128.0, 3.0 );
|
||||
curpos = (int)res;
|
||||
swprintf_s(temp,L"%d ms (avg)",curpos);
|
||||
SetDlgItemText(hWnd,IDC_LATENCY_LABEL,temp);
|
||||
}
|
||||
|
||||
if( hwndDlg == GetDlgItem( hWnd, IDC_VOLUME_SLIDER ) )
|
||||
{
|
||||
swprintf_s(temp,L"%d%%",curpos);
|
||||
SetDlgItemText(hWnd,IDC_VOLUME_LABEL,temp);
|
||||
}
|
||||
break;
|
||||
if (hwndDlg == GetDlgItem(hWnd, IDC_LATENCY_SLIDER)) {
|
||||
double res = pow(curpos / 128.0, 3.0);
|
||||
curpos = (int)res;
|
||||
swprintf_s(temp, L"%d ms (avg)", curpos);
|
||||
SetDlgItemText(hWnd, IDC_LATENCY_LABEL, temp);
|
||||
}
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
if (hwndDlg == GetDlgItem(hWnd, IDC_VOLUME_SLIDER)) {
|
||||
swprintf_s(temp, L"%d%%", curpos);
|
||||
SetDlgItemText(hWnd, IDC_VOLUME_LABEL, temp);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void configure()
|
||||
{
|
||||
INT_PTR ret;
|
||||
ReadSettings();
|
||||
ret = DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_CONFIG),GetActiveWindow(),(DLGPROC)ConfigProc,1);
|
||||
if(ret==-1)
|
||||
{
|
||||
MessageBox(GetActiveWindow(),L"Error Opening the config dialog.",L"OMG ERROR!",MB_OK | MB_SETFOREGROUND);
|
||||
return;
|
||||
}
|
||||
ReadSettings();
|
||||
INT_PTR ret;
|
||||
ReadSettings();
|
||||
ret = DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_CONFIG), GetActiveWindow(), (DLGPROC)ConfigProc, 1);
|
||||
if (ret == -1) {
|
||||
MessageBox(GetActiveWindow(), L"Error Opening the config dialog.", L"OMG ERROR!", MB_OK | MB_SETFOREGROUND);
|
||||
return;
|
||||
}
|
||||
ReadSettings();
|
||||
}
|
||||
|
|
|
@ -20,24 +20,24 @@
|
|||
#include "Utilities\Path.h"
|
||||
|
||||
|
||||
bool DebugEnabled=false;
|
||||
bool _MsgToConsole=false;
|
||||
bool _MsgKeyOnOff=false;
|
||||
bool _MsgVoiceOff=false;
|
||||
bool _MsgDMA=false;
|
||||
bool _MsgAutoDMA=false;
|
||||
bool _MsgOverruns=false;
|
||||
bool _MsgCache=false;
|
||||
bool DebugEnabled = false;
|
||||
bool _MsgToConsole = false;
|
||||
bool _MsgKeyOnOff = false;
|
||||
bool _MsgVoiceOff = false;
|
||||
bool _MsgDMA = false;
|
||||
bool _MsgAutoDMA = false;
|
||||
bool _MsgOverruns = false;
|
||||
bool _MsgCache = false;
|
||||
|
||||
bool _AccessLog=false;
|
||||
bool _DMALog=false;
|
||||
bool _WaveLog=false;
|
||||
bool _AccessLog = false;
|
||||
bool _DMALog = false;
|
||||
bool _WaveLog = false;
|
||||
|
||||
bool _CoresDump=false;
|
||||
bool _MemDump=false;
|
||||
bool _RegDump=false;
|
||||
bool _CoresDump = false;
|
||||
bool _MemDump = false;
|
||||
bool _RegDump = false;
|
||||
|
||||
bool _visual_debug_enabled=false;
|
||||
bool _visual_debug_enabled = false;
|
||||
|
||||
// this is set true if PCSX2 invokes the SetLogDir callback, which tells SPU2-X to use that over
|
||||
// the configured crap in the ini file.
|
||||
|
@ -57,220 +57,213 @@ wxString CoresDumpFileName;
|
|||
wxString MemDumpFileName;
|
||||
wxString RegDumpFileName;
|
||||
|
||||
void CfgSetLogDir( const char* dir )
|
||||
void CfgSetLogDir(const char *dir)
|
||||
{
|
||||
LogsFolder = (dir==NULL) ? wxString(L"logs") : wxString(dir, wxConvFile);
|
||||
DumpsFolder = (dir==NULL) ? wxString(L"logs") : wxString(dir, wxConvFile);
|
||||
LogLocationSetByPcsx2 = (dir!=NULL);
|
||||
LogsFolder = (dir == NULL) ? wxString(L"logs") : wxString(dir, wxConvFile);
|
||||
DumpsFolder = (dir == NULL) ? wxString(L"logs") : wxString(dir, wxConvFile);
|
||||
LogLocationSetByPcsx2 = (dir != NULL);
|
||||
}
|
||||
|
||||
FILE* OpenBinaryLog( const wxString& logfile )
|
||||
FILE *OpenBinaryLog(const wxString &logfile)
|
||||
{
|
||||
return wxFopen( Path::Combine(LogsFolder, logfile), L"wb" );
|
||||
return wxFopen(Path::Combine(LogsFolder, logfile), L"wb");
|
||||
}
|
||||
|
||||
FILE* OpenLog( const wxString& logfile )
|
||||
FILE *OpenLog(const wxString &logfile)
|
||||
{
|
||||
return wxFopen( Path::Combine(LogsFolder, logfile), L"w" );
|
||||
return wxFopen(Path::Combine(LogsFolder, logfile), L"w");
|
||||
}
|
||||
|
||||
FILE* OpenDump( const wxString& logfile )
|
||||
FILE *OpenDump(const wxString &logfile)
|
||||
{
|
||||
return wxFopen( Path::Combine(DumpsFolder, logfile), L"w" );
|
||||
return wxFopen(Path::Combine(DumpsFolder, logfile), L"w");
|
||||
}
|
||||
|
||||
namespace DebugConfig {
|
||||
namespace DebugConfig
|
||||
{
|
||||
|
||||
static const wxChar* Section = L"DEBUG";
|
||||
static const wxChar *Section = L"DEBUG";
|
||||
|
||||
void ReadSettings()
|
||||
{
|
||||
DebugEnabled = CfgReadBool(Section, L"Global_Enable",0);
|
||||
_MsgToConsole= CfgReadBool(Section, L"Show_Messages",0);
|
||||
_MsgKeyOnOff = CfgReadBool(Section, L"Show_Messages_Key_On_Off",0);
|
||||
_MsgVoiceOff = CfgReadBool(Section, L"Show_Messages_Voice_Off",0);
|
||||
_MsgDMA = CfgReadBool(Section, L"Show_Messages_DMA_Transfer",0);
|
||||
_MsgAutoDMA = CfgReadBool(Section, L"Show_Messages_AutoDMA",0);
|
||||
_MsgOverruns = CfgReadBool(Section, L"Show_Messages_Overruns",0);
|
||||
_MsgCache = CfgReadBool(Section, L"Show_Messages_CacheStats",0);
|
||||
DebugEnabled = CfgReadBool(Section, L"Global_Enable", 0);
|
||||
_MsgToConsole = CfgReadBool(Section, L"Show_Messages", 0);
|
||||
_MsgKeyOnOff = CfgReadBool(Section, L"Show_Messages_Key_On_Off", 0);
|
||||
_MsgVoiceOff = CfgReadBool(Section, L"Show_Messages_Voice_Off", 0);
|
||||
_MsgDMA = CfgReadBool(Section, L"Show_Messages_DMA_Transfer", 0);
|
||||
_MsgAutoDMA = CfgReadBool(Section, L"Show_Messages_AutoDMA", 0);
|
||||
_MsgOverruns = CfgReadBool(Section, L"Show_Messages_Overruns", 0);
|
||||
_MsgCache = CfgReadBool(Section, L"Show_Messages_CacheStats", 0);
|
||||
|
||||
_AccessLog = CfgReadBool(Section, L"Log_Register_Access",0);
|
||||
_DMALog = CfgReadBool(Section, L"Log_DMA_Transfers",0);
|
||||
_WaveLog = CfgReadBool(Section, L"Log_WAVE_Output",0);
|
||||
_AccessLog = CfgReadBool(Section, L"Log_Register_Access", 0);
|
||||
_DMALog = CfgReadBool(Section, L"Log_DMA_Transfers", 0);
|
||||
_WaveLog = CfgReadBool(Section, L"Log_WAVE_Output", 0);
|
||||
|
||||
_CoresDump = CfgReadBool(Section, L"Dump_Info",0);
|
||||
_MemDump = CfgReadBool(Section, L"Dump_Memory",0);
|
||||
_RegDump = CfgReadBool(Section, L"Dump_Regs",0);
|
||||
_CoresDump = CfgReadBool(Section, L"Dump_Info", 0);
|
||||
_MemDump = CfgReadBool(Section, L"Dump_Memory", 0);
|
||||
_RegDump = CfgReadBool(Section, L"Dump_Regs", 0);
|
||||
|
||||
_visual_debug_enabled = CfgReadBool(Section, L"Visual_Debug_Enabled",0);
|
||||
_visual_debug_enabled = CfgReadBool(Section, L"Visual_Debug_Enabled", 0);
|
||||
|
||||
CfgReadStr(Section,L"Logs_Folder", CfgLogsFolder, L"logs");
|
||||
CfgReadStr(Section,L"Dumps_Folder",CfgDumpsFolder,L"logs");
|
||||
CfgReadStr(Section, L"Logs_Folder", CfgLogsFolder, L"logs");
|
||||
CfgReadStr(Section, L"Dumps_Folder", CfgDumpsFolder, L"logs");
|
||||
|
||||
CfgReadStr(Section,L"Access_Log_Filename",AccessLogFileName, L"SPU2Log.txt");
|
||||
CfgReadStr(Section,L"DMA4Log_Filename", DMA4LogFileName, L"SPU2dma4.dat");
|
||||
CfgReadStr(Section,L"DMA7Log_Filename", DMA7LogFileName, L"SPU2dma7.dat");
|
||||
CfgReadStr(Section, L"Access_Log_Filename", AccessLogFileName, L"SPU2Log.txt");
|
||||
CfgReadStr(Section, L"DMA4Log_Filename", DMA4LogFileName, L"SPU2dma4.dat");
|
||||
CfgReadStr(Section, L"DMA7Log_Filename", DMA7LogFileName, L"SPU2dma7.dat");
|
||||
|
||||
CfgReadStr(Section,L"Info_Dump_Filename", CoresDumpFileName, L"SPU2Cores.txt");
|
||||
CfgReadStr(Section,L"Mem_Dump_Filename", MemDumpFileName, L"SPU2mem.dat");
|
||||
CfgReadStr(Section,L"Reg_Dump_Filename", RegDumpFileName, L"SPU2regs.dat");
|
||||
CfgReadStr(Section, L"Info_Dump_Filename", CoresDumpFileName, L"SPU2Cores.txt");
|
||||
CfgReadStr(Section, L"Mem_Dump_Filename", MemDumpFileName, L"SPU2mem.dat");
|
||||
CfgReadStr(Section, L"Reg_Dump_Filename", RegDumpFileName, L"SPU2regs.dat");
|
||||
|
||||
if( !LogLocationSetByPcsx2 )
|
||||
{
|
||||
LogsFolder = CfgLogsFolder;
|
||||
DumpsFolder = CfgLogsFolder;
|
||||
}
|
||||
if (!LogLocationSetByPcsx2) {
|
||||
LogsFolder = CfgLogsFolder;
|
||||
DumpsFolder = CfgLogsFolder;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void WriteSettings()
|
||||
{
|
||||
CfgWriteBool(Section,L"Global_Enable",DebugEnabled);
|
||||
CfgWriteBool(Section, L"Global_Enable", DebugEnabled);
|
||||
|
||||
CfgWriteBool(Section,L"Show_Messages", _MsgToConsole);
|
||||
CfgWriteBool(Section,L"Show_Messages_Key_On_Off", _MsgKeyOnOff);
|
||||
CfgWriteBool(Section,L"Show_Messages_Voice_Off", _MsgVoiceOff);
|
||||
CfgWriteBool(Section,L"Show_Messages_DMA_Transfer",_MsgDMA);
|
||||
CfgWriteBool(Section,L"Show_Messages_AutoDMA", _MsgAutoDMA);
|
||||
CfgWriteBool(Section,L"Show_Messages_Overruns", _MsgOverruns);
|
||||
CfgWriteBool(Section,L"Show_Messages_CacheStats", _MsgCache);
|
||||
CfgWriteBool(Section, L"Show_Messages", _MsgToConsole);
|
||||
CfgWriteBool(Section, L"Show_Messages_Key_On_Off", _MsgKeyOnOff);
|
||||
CfgWriteBool(Section, L"Show_Messages_Voice_Off", _MsgVoiceOff);
|
||||
CfgWriteBool(Section, L"Show_Messages_DMA_Transfer", _MsgDMA);
|
||||
CfgWriteBool(Section, L"Show_Messages_AutoDMA", _MsgAutoDMA);
|
||||
CfgWriteBool(Section, L"Show_Messages_Overruns", _MsgOverruns);
|
||||
CfgWriteBool(Section, L"Show_Messages_CacheStats", _MsgCache);
|
||||
|
||||
CfgWriteBool(Section,L"Log_Register_Access",_AccessLog);
|
||||
CfgWriteBool(Section,L"Log_DMA_Transfers", _DMALog);
|
||||
CfgWriteBool(Section,L"Log_WAVE_Output", _WaveLog);
|
||||
CfgWriteBool(Section, L"Log_Register_Access", _AccessLog);
|
||||
CfgWriteBool(Section, L"Log_DMA_Transfers", _DMALog);
|
||||
CfgWriteBool(Section, L"Log_WAVE_Output", _WaveLog);
|
||||
|
||||
CfgWriteBool(Section,L"Dump_Info", _CoresDump);
|
||||
CfgWriteBool(Section,L"Dump_Memory",_MemDump);
|
||||
CfgWriteBool(Section,L"Dump_Regs", _RegDump);
|
||||
CfgWriteBool(Section, L"Dump_Info", _CoresDump);
|
||||
CfgWriteBool(Section, L"Dump_Memory", _MemDump);
|
||||
CfgWriteBool(Section, L"Dump_Regs", _RegDump);
|
||||
|
||||
CfgWriteBool(Section,L"Visual_Debug_Enabled", _visual_debug_enabled);
|
||||
CfgWriteBool(Section, L"Visual_Debug_Enabled", _visual_debug_enabled);
|
||||
|
||||
// None of the logs strings are changable via GUI, so no point in bothering to
|
||||
// write them back out.
|
||||
CfgWriteStr(Section,L"Logs_Folder", CfgLogsFolder);
|
||||
CfgWriteStr(Section,L"Dumps_Folder",CfgDumpsFolder);
|
||||
// None of the logs strings are changable via GUI, so no point in bothering to
|
||||
// write them back out.
|
||||
CfgWriteStr(Section, L"Logs_Folder", CfgLogsFolder);
|
||||
CfgWriteStr(Section, L"Dumps_Folder", CfgDumpsFolder);
|
||||
|
||||
CfgWriteStr(Section,L"Access_Log_Filename",AccessLogFileName);
|
||||
CfgWriteStr(Section,L"DMA4Log_Filename", DMA4LogFileName);
|
||||
CfgWriteStr(Section,L"DMA7Log_Filename", DMA7LogFileName);
|
||||
CfgWriteStr(Section, L"Access_Log_Filename", AccessLogFileName);
|
||||
CfgWriteStr(Section, L"DMA4Log_Filename", DMA4LogFileName);
|
||||
CfgWriteStr(Section, L"DMA7Log_Filename", DMA7LogFileName);
|
||||
|
||||
CfgWriteStr(Section,L"Info_Dump_Filename",CoresDumpFileName);
|
||||
CfgWriteStr(Section,L"Mem_Dump_Filename", MemDumpFileName);
|
||||
CfgWriteStr(Section,L"Reg_Dump_Filename", RegDumpFileName);
|
||||
CfgWriteStr(Section, L"Info_Dump_Filename", CoresDumpFileName);
|
||||
CfgWriteStr(Section, L"Mem_Dump_Filename", MemDumpFileName);
|
||||
CfgWriteStr(Section, L"Reg_Dump_Filename", RegDumpFileName);
|
||||
}
|
||||
|
||||
static void EnableMessages( HWND hWnd )
|
||||
static void EnableMessages(HWND hWnd)
|
||||
{
|
||||
ENABLE_CONTROL(IDC_MSGSHOW, DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_MSGKEY, MsgToConsole());
|
||||
ENABLE_CONTROL(IDC_MSGVOICE,MsgToConsole());
|
||||
ENABLE_CONTROL(IDC_MSGDMA, MsgToConsole());
|
||||
ENABLE_CONTROL(IDC_MSGADMA, MsgToConsole());
|
||||
ENABLE_CONTROL(IDC_DBG_OVERRUNS, MsgToConsole());
|
||||
ENABLE_CONTROL(IDC_DBG_CACHE, MsgToConsole());
|
||||
ENABLE_CONTROL(IDC_MSGSHOW, DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_MSGKEY, MsgToConsole());
|
||||
ENABLE_CONTROL(IDC_MSGVOICE, MsgToConsole());
|
||||
ENABLE_CONTROL(IDC_MSGDMA, MsgToConsole());
|
||||
ENABLE_CONTROL(IDC_MSGADMA, MsgToConsole());
|
||||
ENABLE_CONTROL(IDC_DBG_OVERRUNS, MsgToConsole());
|
||||
ENABLE_CONTROL(IDC_DBG_CACHE, MsgToConsole());
|
||||
}
|
||||
|
||||
void EnableControls( HWND hWnd )
|
||||
void EnableControls(HWND hWnd)
|
||||
{
|
||||
EnableMessages( hWnd );
|
||||
ENABLE_CONTROL(IDC_LOGDMA, DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_LOGREGS, IsDevBuild ? DebugEnabled : false);
|
||||
ENABLE_CONTROL(IDC_LOGWAVE, IsDevBuild ? DebugEnabled : false);
|
||||
ENABLE_CONTROL(IDC_DUMPCORE,DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_DUMPMEM, DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_DUMPREGS,DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_DEBUG_VISUAL, IsDevBuild ? DebugEnabled : false);
|
||||
EnableMessages(hWnd);
|
||||
ENABLE_CONTROL(IDC_LOGDMA, DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_LOGREGS, IsDevBuild ? DebugEnabled : false);
|
||||
ENABLE_CONTROL(IDC_LOGWAVE, IsDevBuild ? DebugEnabled : false);
|
||||
ENABLE_CONTROL(IDC_DUMPCORE, DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_DUMPMEM, DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_DUMPREGS, DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_DEBUG_VISUAL, IsDevBuild ? DebugEnabled : false);
|
||||
}
|
||||
|
||||
static BOOL CALLBACK DialogProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
|
||||
static BOOL CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
int wmId;
|
||||
//wchar_t temp[384]={0};
|
||||
int wmId;
|
||||
//wchar_t temp[384]={0};
|
||||
|
||||
switch(uMsg)
|
||||
{
|
||||
case WM_PAINT:
|
||||
return FALSE;
|
||||
switch (uMsg) {
|
||||
case WM_PAINT:
|
||||
return FALSE;
|
||||
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
EnableControls( hWnd );
|
||||
case WM_INITDIALOG: {
|
||||
EnableControls(hWnd);
|
||||
|
||||
// Debugging / Logging Flags:
|
||||
SET_CHECK(IDC_DEBUG, DebugEnabled);
|
||||
SET_CHECK(IDC_MSGSHOW, _MsgToConsole);
|
||||
SET_CHECK(IDC_MSGKEY, _MsgKeyOnOff);
|
||||
SET_CHECK(IDC_MSGVOICE,_MsgVoiceOff);
|
||||
SET_CHECK(IDC_MSGDMA, _MsgDMA);
|
||||
SET_CHECK(IDC_MSGADMA, _MsgAutoDMA);
|
||||
SET_CHECK(IDC_DBG_OVERRUNS, _MsgOverruns );
|
||||
SET_CHECK(IDC_DBG_CACHE, _MsgCache );
|
||||
SET_CHECK(IDC_LOGREGS, _AccessLog);
|
||||
SET_CHECK(IDC_LOGDMA, _DMALog);
|
||||
SET_CHECK(IDC_LOGWAVE, _WaveLog);
|
||||
SET_CHECK(IDC_DUMPCORE,_CoresDump);
|
||||
SET_CHECK(IDC_DUMPMEM, _MemDump);
|
||||
SET_CHECK(IDC_DUMPREGS,_RegDump);
|
||||
SET_CHECK(IDC_DEBUG_VISUAL,_visual_debug_enabled);
|
||||
// Debugging / Logging Flags:
|
||||
SET_CHECK(IDC_DEBUG, DebugEnabled);
|
||||
SET_CHECK(IDC_MSGSHOW, _MsgToConsole);
|
||||
SET_CHECK(IDC_MSGKEY, _MsgKeyOnOff);
|
||||
SET_CHECK(IDC_MSGVOICE, _MsgVoiceOff);
|
||||
SET_CHECK(IDC_MSGDMA, _MsgDMA);
|
||||
SET_CHECK(IDC_MSGADMA, _MsgAutoDMA);
|
||||
SET_CHECK(IDC_DBG_OVERRUNS, _MsgOverruns);
|
||||
SET_CHECK(IDC_DBG_CACHE, _MsgCache);
|
||||
SET_CHECK(IDC_LOGREGS, _AccessLog);
|
||||
SET_CHECK(IDC_LOGDMA, _DMALog);
|
||||
SET_CHECK(IDC_LOGWAVE, _WaveLog);
|
||||
SET_CHECK(IDC_DUMPCORE, _CoresDump);
|
||||
SET_CHECK(IDC_DUMPMEM, _MemDump);
|
||||
SET_CHECK(IDC_DUMPREGS, _RegDump);
|
||||
SET_CHECK(IDC_DEBUG_VISUAL, _visual_debug_enabled);
|
||||
|
||||
ShowWindow( GetDlgItem( hWnd, IDC_MSG_PUBLIC_BUILD ), !IsDevBuild );
|
||||
}
|
||||
break;
|
||||
ShowWindow(GetDlgItem(hWnd, IDC_MSG_PUBLIC_BUILD), !IsDevBuild);
|
||||
} break;
|
||||
|
||||
case WM_COMMAND:
|
||||
wmId = LOWORD(wParam);
|
||||
// Parse the menu selections:
|
||||
switch (wmId)
|
||||
{
|
||||
case IDOK:
|
||||
WriteSettings();
|
||||
EndDialog(hWnd,0);
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
wmId = LOWORD(wParam);
|
||||
// Parse the menu selections:
|
||||
switch (wmId) {
|
||||
case IDOK:
|
||||
WriteSettings();
|
||||
EndDialog(hWnd, 0);
|
||||
break;
|
||||
|
||||
case IDCANCEL:
|
||||
EndDialog(hWnd,0);
|
||||
break;
|
||||
case IDCANCEL:
|
||||
EndDialog(hWnd, 0);
|
||||
break;
|
||||
|
||||
HANDLE_CHECKNB(IDC_MSGSHOW,_MsgToConsole);
|
||||
EnableMessages( hWnd );
|
||||
break;
|
||||
HANDLE_CHECKNB(IDC_MSGSHOW, _MsgToConsole);
|
||||
EnableMessages(hWnd);
|
||||
break;
|
||||
|
||||
HANDLE_CHECK(IDC_MSGKEY,_MsgKeyOnOff);
|
||||
HANDLE_CHECK(IDC_MSGVOICE,_MsgVoiceOff);
|
||||
HANDLE_CHECK(IDC_MSGDMA,_MsgDMA);
|
||||
HANDLE_CHECK(IDC_MSGADMA,_MsgAutoDMA);
|
||||
break;
|
||||
HANDLE_CHECK(IDC_MSGKEY, _MsgKeyOnOff);
|
||||
HANDLE_CHECK(IDC_MSGVOICE, _MsgVoiceOff);
|
||||
HANDLE_CHECK(IDC_MSGDMA, _MsgDMA);
|
||||
HANDLE_CHECK(IDC_MSGADMA, _MsgAutoDMA);
|
||||
break;
|
||||
|
||||
HANDLE_CHECK(IDC_DBG_OVERRUNS,_MsgOverruns);
|
||||
HANDLE_CHECK(IDC_DBG_CACHE,_MsgCache);
|
||||
HANDLE_CHECK(IDC_LOGREGS,_AccessLog);
|
||||
HANDLE_CHECK(IDC_LOGDMA, _DMALog);
|
||||
HANDLE_CHECK(IDC_LOGWAVE,_WaveLog);
|
||||
HANDLE_CHECK(IDC_DUMPCORE,_CoresDump);
|
||||
HANDLE_CHECK(IDC_DUMPMEM, _MemDump);
|
||||
HANDLE_CHECK(IDC_DUMPREGS,_RegDump);
|
||||
HANDLE_CHECK(IDC_DEBUG_VISUAL,_visual_debug_enabled);
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
HANDLE_CHECK(IDC_DBG_OVERRUNS, _MsgOverruns);
|
||||
HANDLE_CHECK(IDC_DBG_CACHE, _MsgCache);
|
||||
HANDLE_CHECK(IDC_LOGREGS, _AccessLog);
|
||||
HANDLE_CHECK(IDC_LOGDMA, _DMALog);
|
||||
HANDLE_CHECK(IDC_LOGWAVE, _WaveLog);
|
||||
HANDLE_CHECK(IDC_DUMPCORE, _CoresDump);
|
||||
HANDLE_CHECK(IDC_DUMPMEM, _MemDump);
|
||||
HANDLE_CHECK(IDC_DUMPREGS, _RegDump);
|
||||
HANDLE_CHECK(IDC_DEBUG_VISUAL, _visual_debug_enabled);
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void OpenDialog()
|
||||
{
|
||||
INT_PTR ret = DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_CONFIG_DEBUG),GetActiveWindow(),(DLGPROC)DialogProc,1);
|
||||
if(ret == -1)
|
||||
{
|
||||
MessageBox(GetActiveWindow(),L"Error Opening the debug configuration dialog.",L"OMG ERROR!",MB_OK | MB_SETFOREGROUND);
|
||||
return;
|
||||
}
|
||||
ReadSettings();
|
||||
INT_PTR ret = DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_CONFIG_DEBUG), GetActiveWindow(), (DLGPROC)DialogProc, 1);
|
||||
if (ret == -1) {
|
||||
MessageBox(GetActiveWindow(), L"Error Opening the debug configuration dialog.", L"OMG ERROR!", MB_OK | MB_SETFOREGROUND);
|
||||
return;
|
||||
}
|
||||
ReadSettings();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -34,106 +34,98 @@ static const int SeekWindow_Max = 30;
|
|||
static const int Overlap_Min = 5;
|
||||
static const int Overlap_Max = 15;
|
||||
|
||||
void SoundtouchCfg::ApplySettings( soundtouch::SoundTouch& sndtouch )
|
||||
void SoundtouchCfg::ApplySettings(soundtouch::SoundTouch &sndtouch)
|
||||
{
|
||||
sndtouch.setSetting( SETTING_SEQUENCE_MS, SequenceLenMS );
|
||||
sndtouch.setSetting( SETTING_SEEKWINDOW_MS, SeekWindowMS );
|
||||
sndtouch.setSetting( SETTING_OVERLAP_MS, OverlapMS );
|
||||
sndtouch.setSetting(SETTING_SEQUENCE_MS, SequenceLenMS);
|
||||
sndtouch.setSetting(SETTING_SEEKWINDOW_MS, SeekWindowMS);
|
||||
sndtouch.setSetting(SETTING_OVERLAP_MS, OverlapMS);
|
||||
}
|
||||
|
||||
static void ClampValues()
|
||||
{
|
||||
Clampify( SequenceLenMS, SequenceLen_Min, SequenceLen_Max );
|
||||
Clampify( SeekWindowMS, SeekWindow_Min, SeekWindow_Max );
|
||||
Clampify( OverlapMS, Overlap_Min, Overlap_Max );
|
||||
Clampify(SequenceLenMS, SequenceLen_Min, SequenceLen_Max);
|
||||
Clampify(SeekWindowMS, SeekWindow_Min, SeekWindow_Max);
|
||||
Clampify(OverlapMS, Overlap_Min, Overlap_Max);
|
||||
}
|
||||
|
||||
void SoundtouchCfg::ReadSettings()
|
||||
{
|
||||
SequenceLenMS = CfgReadInt( L"SOUNDTOUCH", L"SequenceLengthMS", 30 );
|
||||
SeekWindowMS = CfgReadInt( L"SOUNDTOUCH", L"SeekWindowMS", 20 );
|
||||
OverlapMS = CfgReadInt( L"SOUNDTOUCH", L"OverlapMS", 10 );
|
||||
SequenceLenMS = CfgReadInt(L"SOUNDTOUCH", L"SequenceLengthMS", 30);
|
||||
SeekWindowMS = CfgReadInt(L"SOUNDTOUCH", L"SeekWindowMS", 20);
|
||||
OverlapMS = CfgReadInt(L"SOUNDTOUCH", L"OverlapMS", 10);
|
||||
|
||||
ClampValues();
|
||||
ClampValues();
|
||||
}
|
||||
|
||||
void SoundtouchCfg::WriteSettings()
|
||||
{
|
||||
CfgWriteInt( L"SOUNDTOUCH", L"SequenceLengthMS", SequenceLenMS );
|
||||
CfgWriteInt( L"SOUNDTOUCH", L"SeekWindowMS", SeekWindowMS );
|
||||
CfgWriteInt( L"SOUNDTOUCH", L"OverlapMS", OverlapMS );
|
||||
CfgWriteInt(L"SOUNDTOUCH", L"SequenceLengthMS", SequenceLenMS);
|
||||
CfgWriteInt(L"SOUNDTOUCH", L"SeekWindowMS", SeekWindowMS);
|
||||
CfgWriteInt(L"SOUNDTOUCH", L"OverlapMS", OverlapMS);
|
||||
}
|
||||
|
||||
BOOL CALLBACK SoundtouchCfg::DialogProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
|
||||
BOOL CALLBACK SoundtouchCfg::DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
int wmId;
|
||||
//wchar_t temp[384]={0};
|
||||
int wmId;
|
||||
//wchar_t temp[384]={0};
|
||||
|
||||
switch(uMsg)
|
||||
{
|
||||
case WM_PAINT:
|
||||
return FALSE;
|
||||
switch (uMsg) {
|
||||
case WM_PAINT:
|
||||
return FALSE;
|
||||
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
INIT_SLIDER( IDC_SEQLEN_SLIDER, SequenceLen_Min, SequenceLen_Max, 20, 5, 1 );
|
||||
INIT_SLIDER( IDC_SEEKWIN_SLIDER, SeekWindow_Min, SeekWindow_Max, 5, 2, 1 );
|
||||
INIT_SLIDER( IDC_OVERLAP_SLIDER, Overlap_Min, Overlap_Max, 3, 2, 1 );
|
||||
case WM_INITDIALOG: {
|
||||
INIT_SLIDER(IDC_SEQLEN_SLIDER, SequenceLen_Min, SequenceLen_Max, 20, 5, 1);
|
||||
INIT_SLIDER(IDC_SEEKWIN_SLIDER, SeekWindow_Min, SeekWindow_Max, 5, 2, 1);
|
||||
INIT_SLIDER(IDC_OVERLAP_SLIDER, Overlap_Min, Overlap_Max, 3, 2, 1);
|
||||
|
||||
SendDialogMsg( hWnd, IDC_SEQLEN_SLIDER, TBM_SETPOS, TRUE, SequenceLenMS );
|
||||
SendDialogMsg( hWnd, IDC_SEEKWIN_SLIDER, TBM_SETPOS, TRUE, SeekWindowMS );
|
||||
SendDialogMsg( hWnd, IDC_OVERLAP_SLIDER, TBM_SETPOS, TRUE, OverlapMS );
|
||||
}
|
||||
SendDialogMsg(hWnd, IDC_SEQLEN_SLIDER, TBM_SETPOS, TRUE, SequenceLenMS);
|
||||
SendDialogMsg(hWnd, IDC_SEEKWIN_SLIDER, TBM_SETPOS, TRUE, SeekWindowMS);
|
||||
SendDialogMsg(hWnd, IDC_OVERLAP_SLIDER, TBM_SETPOS, TRUE, OverlapMS);
|
||||
}
|
||||
|
||||
case WM_COMMAND:
|
||||
wmId = LOWORD(wParam);
|
||||
// Parse the menu selections:
|
||||
if( wmId == IDOK )
|
||||
{
|
||||
SequenceLenMS = (int)SendDialogMsg( hWnd, IDC_SEQLEN_SLIDER, TBM_GETPOS, 0, 0 );
|
||||
SeekWindowMS = (int)SendDialogMsg( hWnd, IDC_SEEKWIN_SLIDER, TBM_GETPOS, 0, 0 );
|
||||
OverlapMS = (int)SendDialogMsg( hWnd, IDC_OVERLAP_SLIDER, TBM_GETPOS, 0, 0 );
|
||||
case WM_COMMAND:
|
||||
wmId = LOWORD(wParam);
|
||||
// Parse the menu selections:
|
||||
if (wmId == IDOK) {
|
||||
SequenceLenMS = (int)SendDialogMsg(hWnd, IDC_SEQLEN_SLIDER, TBM_GETPOS, 0, 0);
|
||||
SeekWindowMS = (int)SendDialogMsg(hWnd, IDC_SEEKWIN_SLIDER, TBM_GETPOS, 0, 0);
|
||||
OverlapMS = (int)SendDialogMsg(hWnd, IDC_OVERLAP_SLIDER, TBM_GETPOS, 0, 0);
|
||||
|
||||
ClampValues();
|
||||
WriteSettings();
|
||||
EndDialog(hWnd,0);
|
||||
}
|
||||
else if( wmId == IDC_RESET_DEFAULTS )
|
||||
{
|
||||
SequenceLenMS = 30;
|
||||
SeekWindowMS = 20;
|
||||
OverlapMS = 10;
|
||||
ClampValues();
|
||||
WriteSettings();
|
||||
EndDialog(hWnd, 0);
|
||||
} else if (wmId == IDC_RESET_DEFAULTS) {
|
||||
SequenceLenMS = 30;
|
||||
SeekWindowMS = 20;
|
||||
OverlapMS = 10;
|
||||
|
||||
SendDialogMsg( hWnd, IDC_SEQLEN_SLIDER, TBM_SETPOS, TRUE, SequenceLenMS );
|
||||
SendDialogMsg( hWnd, IDC_SEEKWIN_SLIDER, TBM_SETPOS, TRUE, SeekWindowMS );
|
||||
SendDialogMsg( hWnd, IDC_OVERLAP_SLIDER, TBM_SETPOS, TRUE, OverlapMS );
|
||||
SendDialogMsg(hWnd, IDC_SEQLEN_SLIDER, TBM_SETPOS, TRUE, SequenceLenMS);
|
||||
SendDialogMsg(hWnd, IDC_SEEKWIN_SLIDER, TBM_SETPOS, TRUE, SeekWindowMS);
|
||||
SendDialogMsg(hWnd, IDC_OVERLAP_SLIDER, TBM_SETPOS, TRUE, OverlapMS);
|
||||
|
||||
AssignSliderValue((HWND)lParam, hWnd, SequenceLenMS);
|
||||
}
|
||||
else if( wmId == IDCANCEL )
|
||||
{
|
||||
EndDialog(hWnd,0);
|
||||
}
|
||||
break;
|
||||
AssignSliderValue((HWND)lParam, hWnd, SequenceLenMS);
|
||||
} else if (wmId == IDCANCEL) {
|
||||
EndDialog(hWnd, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_HSCROLL:
|
||||
DoHandleScrollMessage( hWnd, wParam, lParam );
|
||||
break;
|
||||
case WM_HSCROLL:
|
||||
DoHandleScrollMessage(hWnd, wParam, lParam);
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void SoundtouchCfg::OpenDialog( HWND hWnd )
|
||||
void SoundtouchCfg::OpenDialog(HWND hWnd)
|
||||
{
|
||||
INT_PTR ret;
|
||||
ret = DialogBox( hInstance, MAKEINTRESOURCE(IDD_CONFIG_SOUNDTOUCH), hWnd, (DLGPROC)DialogProc );
|
||||
if(ret==-1)
|
||||
{
|
||||
MessageBox(GetActiveWindow(), L"Error Opening the Soundtouch advanced dialog.", L"OMG ERROR!", MB_OK | MB_SETFOREGROUND);
|
||||
return;
|
||||
}
|
||||
ReadSettings();
|
||||
INT_PTR ret;
|
||||
ret = DialogBox(hInstance, MAKEINTRESOURCE(IDD_CONFIG_SOUNDTOUCH), hWnd, (DLGPROC)DialogProc);
|
||||
if (ret == -1) {
|
||||
MessageBox(GetActiveWindow(), L"Error Opening the Soundtouch advanced dialog.", L"OMG ERROR!", MB_OK | MB_SETFOREGROUND);
|
||||
return;
|
||||
}
|
||||
ReadSettings();
|
||||
}
|
||||
|
|
|
@ -18,61 +18,60 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef _WIN32
|
||||
# include "WinConfig.h"
|
||||
#include "WinConfig.h"
|
||||
#else
|
||||
# include "LnxConfig.h"
|
||||
#include "LnxConfig.h"
|
||||
#endif
|
||||
|
||||
namespace DebugConfig
|
||||
{
|
||||
extern void ReadSettings();
|
||||
extern void WriteSettings();
|
||||
extern void OpenDialog();
|
||||
extern void EnableControls( HWND hWnd );
|
||||
extern void ReadSettings();
|
||||
extern void WriteSettings();
|
||||
extern void OpenDialog();
|
||||
extern void EnableControls(HWND hWnd);
|
||||
}
|
||||
|
||||
namespace SoundtouchCfg
|
||||
{
|
||||
extern void ReadSettings();
|
||||
extern void WriteSettings();
|
||||
extern void OpenDialog( HWND hWnd );
|
||||
extern BOOL CALLBACK DialogProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
|
||||
extern void ReadSettings();
|
||||
extern void WriteSettings();
|
||||
extern void OpenDialog(HWND hWnd);
|
||||
extern BOOL CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
}
|
||||
|
||||
extern int SendDialogMsg( HWND hwnd, int dlgId, UINT code, WPARAM wParam, LPARAM lParam);
|
||||
extern HRESULT GUIDFromString( const wchar_t *str, LPGUID guid );
|
||||
extern int SendDialogMsg(HWND hwnd, int dlgId, UINT code, WPARAM wParam, LPARAM lParam);
|
||||
extern HRESULT GUIDFromString(const wchar_t *str, LPGUID guid);
|
||||
|
||||
extern void AssignSliderValue( HWND idcwnd, HWND hwndDisplay, int value );
|
||||
extern void AssignSliderValue( HWND hWnd, int idc, int editbox, int value );
|
||||
extern int GetSliderValue( HWND hWnd, int idc );
|
||||
extern BOOL DoHandleScrollMessage( HWND hwndDisplay, WPARAM wParam, LPARAM lParam );
|
||||
extern void AssignSliderValue(HWND idcwnd, HWND hwndDisplay, int value);
|
||||
extern void AssignSliderValue(HWND hWnd, int idc, int editbox, int value);
|
||||
extern int GetSliderValue(HWND hWnd, int idc);
|
||||
extern BOOL DoHandleScrollMessage(HWND hwndDisplay, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
extern void CfgSetSettingsDir( const char* dir );
|
||||
extern void CfgSetLogDir( const char* dir );
|
||||
extern void CfgSetSettingsDir(const char *dir);
|
||||
extern void CfgSetLogDir(const char *dir);
|
||||
|
||||
extern bool CfgFindName( const TCHAR *Section, const TCHAR* Name);
|
||||
extern bool CfgFindName(const TCHAR *Section, const TCHAR *Name);
|
||||
|
||||
extern void CfgWriteBool(const TCHAR* Section, const TCHAR* Name, bool Value);
|
||||
extern void CfgWriteInt(const TCHAR* Section, const TCHAR* Name, int Value);
|
||||
extern void CfgWriteFloat(const TCHAR* Section, const TCHAR* Name, float Value);
|
||||
extern void CfgWriteStr(const TCHAR* Section, const TCHAR* Name, const wxString& Data);
|
||||
extern void CfgWriteBool(const TCHAR *Section, const TCHAR *Name, bool Value);
|
||||
extern void CfgWriteInt(const TCHAR *Section, const TCHAR *Name, int Value);
|
||||
extern void CfgWriteFloat(const TCHAR *Section, const TCHAR *Name, float Value);
|
||||
extern void CfgWriteStr(const TCHAR *Section, const TCHAR *Name, const wxString &Data);
|
||||
|
||||
extern bool CfgReadBool(const TCHAR *Section,const TCHAR* Name, bool Default);
|
||||
extern void CfgReadStr(const TCHAR* Section, const TCHAR* Name, wxString& Data, const TCHAR* Default);
|
||||
extern void CfgReadStr(const TCHAR* Section, const TCHAR* Name, TCHAR* Data, int DataSize, const TCHAR* Default);
|
||||
extern int CfgReadInt(const TCHAR* Section, const TCHAR* Name, int Default);
|
||||
extern float CfgReadFloat(const TCHAR* Section, const TCHAR* Name, float Default);
|
||||
extern bool CfgReadBool(const TCHAR *Section, const TCHAR *Name, bool Default);
|
||||
extern void CfgReadStr(const TCHAR *Section, const TCHAR *Name, wxString &Data, const TCHAR *Default);
|
||||
extern void CfgReadStr(const TCHAR *Section, const TCHAR *Name, TCHAR *Data, int DataSize, const TCHAR *Default);
|
||||
extern int CfgReadInt(const TCHAR *Section, const TCHAR *Name, int Default);
|
||||
extern float CfgReadFloat(const TCHAR *Section, const TCHAR *Name, float Default);
|
||||
|
||||
// Items Specific to DirectSound
|
||||
#define STRFY(x) #x
|
||||
#define verifyc(x) Verifyc(x,STRFY(x))
|
||||
#define verifyc(x) Verifyc(x, STRFY(x))
|
||||
|
||||
extern void Verifyc(HRESULT hr, const char* fn);
|
||||
extern void Verifyc(HRESULT hr, const char *fn);
|
||||
|
||||
struct ds_device_data
|
||||
{
|
||||
wxString name;
|
||||
GUID guid;
|
||||
bool hasGuid;
|
||||
wxString name;
|
||||
GUID guid;
|
||||
bool hasGuid;
|
||||
};
|
||||
|
||||
|
|
|
@ -18,75 +18,72 @@
|
|||
#include "Global.h"
|
||||
#include "Dialogs.h"
|
||||
|
||||
bool debugDialogOpen=false;
|
||||
HWND hDebugDialog=NULL;
|
||||
bool debugDialogOpen = false;
|
||||
HWND hDebugDialog = NULL;
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
|
||||
int FillRectangle(HDC dc, int left, int top, int width, int height)
|
||||
{
|
||||
RECT r = { left, top, left+width, top+height };
|
||||
RECT r = {left, top, left + width, top + height};
|
||||
|
||||
return FillRect(dc, &r, (HBRUSH)GetStockObject(DC_BRUSH));
|
||||
return FillRect(dc, &r, (HBRUSH)GetStockObject(DC_BRUSH));
|
||||
}
|
||||
|
||||
BOOL DrawRectangle(HDC dc, int left, int top, int width, int height)
|
||||
{
|
||||
RECT r = { left, top, left+width, top+height };
|
||||
RECT r = {left, top, left + width, top + height};
|
||||
|
||||
POINT p[5] = {
|
||||
{ r.left, r.top },
|
||||
{ r.right, r.top },
|
||||
{ r.right, r.bottom },
|
||||
{ r.left, r.bottom },
|
||||
{ r.left, r.top },
|
||||
};
|
||||
POINT p[5] = {
|
||||
{r.left, r.top},
|
||||
{r.right, r.top},
|
||||
{r.right, r.bottom},
|
||||
{r.left, r.bottom},
|
||||
{r.left, r.top},
|
||||
};
|
||||
|
||||
return Polyline(dc, p, 5);
|
||||
return Polyline(dc, p, 5);
|
||||
}
|
||||
|
||||
|
||||
HFONT hf = NULL;
|
||||
int lCount=0;
|
||||
int lCount = 0;
|
||||
void UpdateDebugDialog()
|
||||
{
|
||||
if(!debugDialogOpen) return;
|
||||
if (!debugDialogOpen)
|
||||
return;
|
||||
|
||||
lCount++;
|
||||
if(lCount>=(SampleRate/100)) // Increase to SampleRate/200 for smooth display.
|
||||
{
|
||||
HDC hdc = GetDC(hDebugDialog);
|
||||
lCount++;
|
||||
if (lCount >= (SampleRate / 100)) // Increase to SampleRate/200 for smooth display.
|
||||
{
|
||||
HDC hdc = GetDC(hDebugDialog);
|
||||
|
||||
if(!hf)
|
||||
{
|
||||
hf = CreateFont( 12, 0, 0, 0, 0, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
|
||||
DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, L"Lucida Console" );
|
||||
}
|
||||
if (!hf) {
|
||||
hf = CreateFont(12, 0, 0, 0, 0, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
|
||||
DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, L"Lucida Console");
|
||||
}
|
||||
|
||||
SelectObject(hdc,hf);
|
||||
SelectObject(hdc,GetStockObject(DC_BRUSH));
|
||||
SelectObject(hdc,GetStockObject(DC_PEN));
|
||||
SelectObject(hdc, hf);
|
||||
SelectObject(hdc, GetStockObject(DC_BRUSH));
|
||||
SelectObject(hdc, GetStockObject(DC_PEN));
|
||||
|
||||
for(int c=0;c<2;c++)
|
||||
{
|
||||
V_Core& cx(Cores[c]);
|
||||
V_CoreDebug& cd(DebugCores[c]);
|
||||
for (int c = 0; c < 2; c++) {
|
||||
V_Core &cx(Cores[c]);
|
||||
V_CoreDebug &cd(DebugCores[c]);
|
||||
|
||||
for(int v=0;v<24;v++)
|
||||
{
|
||||
int cc = c*2 + (v/12);
|
||||
int vv = v % 12;
|
||||
int IX = 8+128*cc;
|
||||
int IY = 8+ 48*vv;
|
||||
V_Voice& vc(cx.Voices[v]);
|
||||
V_VoiceDebug& vcd(cd.Voices[v] );
|
||||
for (int v = 0; v < 24; v++) {
|
||||
int cc = c * 2 + (v / 12);
|
||||
int vv = v % 12;
|
||||
int IX = 8 + 128 * cc;
|
||||
int IY = 8 + 48 * vv;
|
||||
V_Voice &vc(cx.Voices[v]);
|
||||
V_VoiceDebug &vcd(cd.Voices[v]);
|
||||
|
||||
SetDCBrushColor(hdc,RGB( 0, 0, 0));
|
||||
if((vc.ADSR.Phase>0)&&(vc.ADSR.Phase<6))
|
||||
{
|
||||
SetDCBrushColor(hdc,RGB( 0, 0,128));
|
||||
}
|
||||
/*
|
||||
SetDCBrushColor(hdc, RGB(0, 0, 0));
|
||||
if ((vc.ADSR.Phase > 0) && (vc.ADSR.Phase < 6)) {
|
||||
SetDCBrushColor(hdc, RGB(0, 0, 128));
|
||||
}
|
||||
/*
|
||||
else
|
||||
{
|
||||
if(vcd.lastStopReason==1)
|
||||
|
@ -99,181 +96,168 @@ void UpdateDebugDialog()
|
|||
}
|
||||
}*/
|
||||
|
||||
FillRectangle(hdc,IX,IY,124,46);
|
||||
FillRectangle(hdc, IX, IY, 124, 46);
|
||||
|
||||
SetDCPenColor(hdc,RGB( 255, 128, 32));
|
||||
SetDCPenColor(hdc, RGB(255, 128, 32));
|
||||
|
||||
DrawRectangle(hdc,IX,IY,124,46);
|
||||
DrawRectangle(hdc, IX, IY, 124, 46);
|
||||
|
||||
SetDCBrushColor(hdc,RGB( 0,255, 0));
|
||||
SetDCBrushColor(hdc, RGB(0, 255, 0));
|
||||
|
||||
int vl = abs(((vc.Volume.Left.Value >> 16) * 38) >> 15);
|
||||
int vr = abs(((vc.Volume.Right.Value >> 16) * 38) >> 15);
|
||||
int vl = abs(((vc.Volume.Left.Value >> 16) * 38) >> 15);
|
||||
int vr = abs(((vc.Volume.Right.Value >> 16) * 38) >> 15);
|
||||
|
||||
FillRectangle(hdc,IX+58,IY+42 - vl, 4, vl);
|
||||
FillRectangle(hdc,IX+62,IY+42 - vr, 4, vr);
|
||||
FillRectangle(hdc, IX + 58, IY + 42 - vl, 4, vl);
|
||||
FillRectangle(hdc, IX + 62, IY + 42 - vr, 4, vr);
|
||||
|
||||
int adsr = ((vc.ADSR.Value>>16) * 38) / 32768;
|
||||
int adsr = ((vc.ADSR.Value >> 16) * 38) / 32768;
|
||||
|
||||
FillRectangle(hdc,IX+66,IY+42 - adsr, 4, adsr);
|
||||
FillRectangle(hdc, IX + 66, IY + 42 - adsr, 4, adsr);
|
||||
|
||||
int peak = (vcd.displayPeak * 38) / 32768;
|
||||
int peak = (vcd.displayPeak * 38) / 32768;
|
||||
|
||||
if(vcd.displayPeak >= 32700) // leave a little bit of margin
|
||||
{
|
||||
SetDCBrushColor(hdc,RGB( 255, 0, 0));
|
||||
}
|
||||
if (vcd.displayPeak >= 32700) // leave a little bit of margin
|
||||
{
|
||||
SetDCBrushColor(hdc, RGB(255, 0, 0));
|
||||
}
|
||||
|
||||
FillRectangle(hdc,IX+70,IY+42 - peak, 4, peak);
|
||||
FillRectangle(hdc, IX + 70, IY + 42 - peak, 4, peak);
|
||||
|
||||
if(vc.ADSR.Value>0)
|
||||
{
|
||||
if(vc.SBuffer)
|
||||
for(int i=0;i<28;i++)
|
||||
{
|
||||
int val = ((int)vc.SBuffer[i] * 20) / 32768;
|
||||
if (vc.ADSR.Value > 0) {
|
||||
if (vc.SBuffer)
|
||||
for (int i = 0; i < 28; i++) {
|
||||
int val = ((int)vc.SBuffer[i] * 20) / 32768;
|
||||
|
||||
int y=0;
|
||||
int y = 0;
|
||||
|
||||
if(val>0)
|
||||
{
|
||||
y=val;
|
||||
}
|
||||
else
|
||||
val=-val;
|
||||
|
||||
if(val!=0)
|
||||
{
|
||||
FillRectangle(hdc,IX+90+i,IY+24-y, 1, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (val > 0) {
|
||||
y = val;
|
||||
} else
|
||||
val = -val;
|
||||
|
||||
SetTextColor(hdc,RGB( 0,255, 0));
|
||||
SetBkColor (hdc,RGB( 0, 0, 0));
|
||||
if (val != 0) {
|
||||
FillRectangle(hdc, IX + 90 + i, IY + 24 - y, 1, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static wchar_t t[256];
|
||||
SetTextColor(hdc, RGB(0, 255, 0));
|
||||
SetBkColor(hdc, RGB(0, 0, 0));
|
||||
|
||||
swprintf_s(t,L"%06x",vc.StartA);
|
||||
TextOut(hdc,IX+4,IY+4,t,6);
|
||||
static wchar_t t[256];
|
||||
|
||||
swprintf_s(t,L"%06x",vc.NextA);
|
||||
TextOut(hdc,IX+4,IY+18,t,6);
|
||||
swprintf_s(t, L"%06x", vc.StartA);
|
||||
TextOut(hdc, IX + 4, IY + 4, t, 6);
|
||||
|
||||
swprintf_s(t,L"%06x",vc.LoopStartA);
|
||||
TextOut(hdc,IX+4,IY+32,t,6);
|
||||
swprintf_s(t, L"%06x", vc.NextA);
|
||||
TextOut(hdc, IX + 4, IY + 18, t, 6);
|
||||
|
||||
vcd.displayPeak = 0;
|
||||
}
|
||||
swprintf_s(t, L"%06x", vc.LoopStartA);
|
||||
TextOut(hdc, IX + 4, IY + 32, t, 6);
|
||||
|
||||
// top now: 400
|
||||
int JX = 8 + c * 256;
|
||||
int JY = 584;
|
||||
vcd.displayPeak = 0;
|
||||
}
|
||||
|
||||
SetDCBrushColor(hdc,RGB( 0, 0, 0));
|
||||
SetDCPenColor(hdc,RGB( 255, 128, 32));
|
||||
// top now: 400
|
||||
int JX = 8 + c * 256;
|
||||
int JY = 584;
|
||||
|
||||
FillRectangle(hdc,JX,JY,252,60);
|
||||
DrawRectangle(hdc,JX,JY,252,60);
|
||||
SetDCBrushColor(hdc, RGB(0, 0, 0));
|
||||
SetDCPenColor(hdc, RGB(255, 128, 32));
|
||||
|
||||
SetTextColor(hdc,RGB(255,255,255));
|
||||
SetBkColor (hdc,RGB( 0, 0, 0));
|
||||
FillRectangle(hdc, JX, JY, 252, 60);
|
||||
DrawRectangle(hdc, JX, JY, 252, 60);
|
||||
|
||||
static wchar_t t[256];
|
||||
TextOut(hdc,JX+4,JY+ 4,L"REVB",4);
|
||||
TextOut(hdc,JX+4,JY+18,L"IRQE",4);
|
||||
TextOut(hdc,JX+4,JY+32,L"ADMA",4);
|
||||
swprintf_s(t,L"DMA%s",c==0 ? L"4" : L"7");
|
||||
TextOut(hdc,JX+4,JY+46,t, 4);
|
||||
|
||||
SetTextColor(hdc,RGB( 0,255, 0));
|
||||
memset(t, 0, sizeof(t));
|
||||
swprintf_s(t,L"ESA %x",cx.EffectsStartA);
|
||||
TextOut(hdc,JX+56,JY+ 4,t, 9);
|
||||
memset(t, 0, sizeof(t));
|
||||
swprintf_s(t,L"EEA %x",cx.EffectsEndA);
|
||||
TextOut(hdc,JX+128,JY+ 4,t, 9);
|
||||
SetTextColor(hdc, RGB(255, 255, 255));
|
||||
SetBkColor(hdc, RGB(0, 0, 0));
|
||||
|
||||
static wchar_t t[256];
|
||||
TextOut(hdc, JX + 4, JY + 4, L"REVB", 4);
|
||||
TextOut(hdc, JX + 4, JY + 18, L"IRQE", 4);
|
||||
TextOut(hdc, JX + 4, JY + 32, L"ADMA", 4);
|
||||
swprintf_s(t, L"DMA%s", c == 0 ? L"4" : L"7");
|
||||
TextOut(hdc, JX + 4, JY + 46, t, 4);
|
||||
|
||||
SetTextColor(hdc, RGB(0, 255, 0));
|
||||
memset(t, 0, sizeof(t));
|
||||
swprintf_s(t,L"(%x)",cx.EffectsBufferSize);
|
||||
TextOut(hdc,JX+200,JY+ 4,t,7);
|
||||
swprintf_s(t, L"ESA %x", cx.EffectsStartA);
|
||||
TextOut(hdc, JX + 56, JY + 4, t, 9);
|
||||
memset(t, 0, sizeof(t));
|
||||
swprintf_s(t, L"EEA %x", cx.EffectsEndA);
|
||||
TextOut(hdc, JX + 128, JY + 4, t, 9);
|
||||
memset(t, 0, sizeof(t));
|
||||
swprintf_s(t, L"(%x)", cx.EffectsBufferSize);
|
||||
TextOut(hdc, JX + 200, JY + 4, t, 7);
|
||||
|
||||
memset(t, 0, sizeof(t));
|
||||
swprintf_s(t,L"IRQA %x",cx.IRQA);
|
||||
TextOut(hdc,JX+56,JY+18,t, 12);
|
||||
swprintf_s(t, L"IRQA %x", cx.IRQA);
|
||||
TextOut(hdc, JX + 56, JY + 18, t, 12);
|
||||
|
||||
SetTextColor(hdc,RGB(255,255,255));
|
||||
SetDCBrushColor(hdc,RGB( 255,0, 0));
|
||||
SetTextColor(hdc, RGB(255, 255, 255));
|
||||
SetDCBrushColor(hdc, RGB(255, 0, 0));
|
||||
|
||||
if(cx.FxEnable)
|
||||
{
|
||||
FillRectangle(hdc,JX+40,JY+4,10,10);
|
||||
}
|
||||
if(cx.IRQEnable)
|
||||
{
|
||||
FillRectangle(hdc,JX+40,JY+18,10,10);
|
||||
}
|
||||
if(cx.AutoDMACtrl != 0)
|
||||
{
|
||||
FillRectangle(hdc,JX+40,JY+32,10,10);
|
||||
if (cx.FxEnable) {
|
||||
FillRectangle(hdc, JX + 40, JY + 4, 10, 10);
|
||||
}
|
||||
if (cx.IRQEnable) {
|
||||
FillRectangle(hdc, JX + 40, JY + 18, 10, 10);
|
||||
}
|
||||
if (cx.AutoDMACtrl != 0) {
|
||||
FillRectangle(hdc, JX + 40, JY + 32, 10, 10);
|
||||
|
||||
for(int j=0;j<64;j++)
|
||||
{
|
||||
int i=j*256/64;
|
||||
int val = (cd.admaWaveformL[i] * 26) / 32768;
|
||||
int y=0;
|
||||
for (int j = 0; j < 64; j++) {
|
||||
int i = j * 256 / 64;
|
||||
int val = (cd.admaWaveformL[i] * 26) / 32768;
|
||||
int y = 0;
|
||||
|
||||
if(val>0)
|
||||
y=val;
|
||||
else
|
||||
val=-val;
|
||||
if (val > 0)
|
||||
y = val;
|
||||
else
|
||||
val = -val;
|
||||
|
||||
if(val!=0)
|
||||
{
|
||||
FillRectangle(hdc,JX+60+j,JY+30-y, 1, val);
|
||||
}
|
||||
}
|
||||
if (val != 0) {
|
||||
FillRectangle(hdc, JX + 60 + j, JY + 30 - y, 1, val);
|
||||
}
|
||||
}
|
||||
|
||||
for(int j=0;j<64;j++)
|
||||
{
|
||||
int i=j*256/64;
|
||||
int val = (cd.admaWaveformR[i] * 26) / 32768;
|
||||
int y=0;
|
||||
for (int j = 0; j < 64; j++) {
|
||||
int i = j * 256 / 64;
|
||||
int val = (cd.admaWaveformR[i] * 26) / 32768;
|
||||
int y = 0;
|
||||
|
||||
if(val>0)
|
||||
y=val;
|
||||
else
|
||||
val=-val;
|
||||
if (val > 0)
|
||||
y = val;
|
||||
else
|
||||
val = -val;
|
||||
|
||||
if(val!=0)
|
||||
{
|
||||
FillRectangle(hdc,JX+136+j,JY+30-y, 1, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(cd.dmaFlag > 0) // So it shows x times this is called, since dmas are so fast
|
||||
{
|
||||
swprintf_s(t,L"size = %d",cd.lastsize);
|
||||
|
||||
TextOut(hdc,JX+64,JY+46,t,wcslen(t));
|
||||
FillRectangle(hdc,JX+40,JY+46,10,10);
|
||||
cd.dmaFlag--;
|
||||
}
|
||||
}
|
||||
if (val != 0) {
|
||||
FillRectangle(hdc, JX + 136 + j, JY + 30 - y, 1, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cd.dmaFlag > 0) // So it shows x times this is called, since dmas are so fast
|
||||
{
|
||||
swprintf_s(t, L"size = %d", cd.lastsize);
|
||||
|
||||
ReleaseDC(hDebugDialog,hdc);
|
||||
lCount=0;
|
||||
}
|
||||
TextOut(hdc, JX + 64, JY + 46, t, wcslen(t));
|
||||
FillRectangle(hdc, JX + 40, JY + 46, 10, 10);
|
||||
cd.dmaFlag--;
|
||||
}
|
||||
}
|
||||
|
||||
MSG msg;
|
||||
while(PeekMessage(&msg,hDebugDialog,0,0,PM_REMOVE))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
ReleaseDC(hDebugDialog, hdc);
|
||||
lCount = 0;
|
||||
}
|
||||
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg, hDebugDialog, 0, 0, PM_REMOVE)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
#else
|
||||
void UpdateDebugDialog()
|
||||
{
|
||||
// Release mode. Nothing to do
|
||||
// Release mode. Nothing to do
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -26,458 +26,431 @@
|
|||
class DSound : public SndOutModule
|
||||
{
|
||||
private:
|
||||
static const uint MAX_BUFFER_COUNT = 8;
|
||||
static const int PacketsPerBuffer = 8;
|
||||
static const int BufferSize = SndOutPacketSize * PacketsPerBuffer;
|
||||
static const uint MAX_BUFFER_COUNT = 8;
|
||||
static const int PacketsPerBuffer = 8;
|
||||
static const int BufferSize = SndOutPacketSize * PacketsPerBuffer;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Configuration Vars
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Configuration Vars
|
||||
|
||||
wxString m_Device;
|
||||
u8 m_NumBuffers;
|
||||
bool m_DisableGlobalFocus;
|
||||
bool m_UseHardware;
|
||||
wxString m_Device;
|
||||
u8 m_NumBuffers;
|
||||
bool m_DisableGlobalFocus;
|
||||
bool m_UseHardware;
|
||||
|
||||
ds_device_data m_devices[32];
|
||||
int ndevs;
|
||||
GUID DevGuid; // currently employed GUID.
|
||||
bool haveGuid;
|
||||
ds_device_data m_devices[32];
|
||||
int ndevs;
|
||||
GUID DevGuid; // currently employed GUID.
|
||||
bool haveGuid;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Instance vars
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Instance vars
|
||||
|
||||
int channel;
|
||||
int myLastWrite; // last write position, in bytes
|
||||
int channel;
|
||||
int myLastWrite; // last write position, in bytes
|
||||
|
||||
bool dsound_running;
|
||||
HANDLE thread;
|
||||
DWORD tid;
|
||||
bool dsound_running;
|
||||
HANDLE thread;
|
||||
DWORD tid;
|
||||
|
||||
IDirectSound8* dsound;
|
||||
IDirectSoundBuffer8* buffer;
|
||||
IDirectSoundNotify8* buffer_notify;
|
||||
HANDLE buffer_events[MAX_BUFFER_COUNT];
|
||||
IDirectSound8 *dsound;
|
||||
IDirectSoundBuffer8 *buffer;
|
||||
IDirectSoundNotify8 *buffer_notify;
|
||||
HANDLE buffer_events[MAX_BUFFER_COUNT];
|
||||
|
||||
WAVEFORMATEX wfx;
|
||||
WAVEFORMATEX wfx;
|
||||
|
||||
HANDLE waitEvent;
|
||||
HANDLE waitEvent;
|
||||
|
||||
template< typename T >
|
||||
static DWORD CALLBACK RThread( DSound* obj )
|
||||
{
|
||||
return obj->Thread<T>();
|
||||
}
|
||||
template <typename T>
|
||||
static DWORD CALLBACK RThread(DSound *obj)
|
||||
{
|
||||
return obj->Thread<T>();
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
DWORD CALLBACK Thread()
|
||||
{
|
||||
static const int BufferSizeBytes = BufferSize * sizeof( T );
|
||||
template <typename T>
|
||||
DWORD CALLBACK Thread()
|
||||
{
|
||||
static const int BufferSizeBytes = BufferSize * sizeof(T);
|
||||
|
||||
while( dsound_running )
|
||||
{
|
||||
u32 rv = WaitForMultipleObjects(m_NumBuffers,buffer_events,FALSE,200);
|
||||
while (dsound_running) {
|
||||
u32 rv = WaitForMultipleObjects(m_NumBuffers, buffer_events, FALSE, 200);
|
||||
|
||||
T* p1, *oldp1;
|
||||
LPVOID p2;
|
||||
DWORD s1,s2;
|
||||
T *p1, *oldp1;
|
||||
LPVOID p2;
|
||||
DWORD s1, s2;
|
||||
|
||||
u32 poffset = BufferSizeBytes * rv;
|
||||
u32 poffset = BufferSizeBytes * rv;
|
||||
|
||||
if( FAILED(buffer->Lock(poffset,BufferSizeBytes,(LPVOID*)&p1,&s1,&p2,&s2,0) ) )
|
||||
{
|
||||
assert( 0 );
|
||||
fputs( "* SPU2-X: Directsound Warning > Buffer lock failure. You may need to increase\n\tyour configured DSound buffer count.\n", stderr );
|
||||
continue;
|
||||
}
|
||||
oldp1 = p1;
|
||||
if (FAILED(buffer->Lock(poffset, BufferSizeBytes, (LPVOID *)&p1, &s1, &p2, &s2, 0))) {
|
||||
assert(0);
|
||||
fputs("* SPU2-X: Directsound Warning > Buffer lock failure. You may need to increase\n\tyour configured DSound buffer count.\n", stderr);
|
||||
continue;
|
||||
}
|
||||
oldp1 = p1;
|
||||
|
||||
for(int p=0; p<PacketsPerBuffer; p++, p1+=SndOutPacketSize )
|
||||
SndBuffer::ReadSamples( p1 );
|
||||
for (int p = 0; p < PacketsPerBuffer; p++, p1 += SndOutPacketSize)
|
||||
SndBuffer::ReadSamples(p1);
|
||||
|
||||
buffer->Unlock( oldp1, s1, p2, s2 );
|
||||
buffer->Unlock(oldp1, s1, p2, s2);
|
||||
|
||||
// Set the write pointer to the beginning of the next block.
|
||||
myLastWrite = (poffset + BufferSizeBytes) & ~BufferSizeBytes;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
// Set the write pointer to the beginning of the next block.
|
||||
myLastWrite = (poffset + BufferSizeBytes) & ~BufferSizeBytes;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public:
|
||||
s32 Init()
|
||||
{
|
||||
CoInitializeEx( NULL, COINIT_MULTITHREADED );
|
||||
s32 Init()
|
||||
{
|
||||
CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||||
|
||||
//
|
||||
// Initialize DSound
|
||||
//
|
||||
GUID cGuid;
|
||||
//
|
||||
// Initialize DSound
|
||||
//
|
||||
GUID cGuid;
|
||||
|
||||
try
|
||||
{
|
||||
if( m_Device.empty() )
|
||||
throw std::runtime_error( "screw it" );
|
||||
try {
|
||||
if (m_Device.empty())
|
||||
throw std::runtime_error("screw it");
|
||||
|
||||
if ((FAILED(GUIDFromString(m_Device, &cGuid))) ||
|
||||
FAILED( DirectSoundCreate8(&cGuid,&dsound,NULL) ) )
|
||||
throw std::runtime_error( "try again?" );
|
||||
}
|
||||
catch( std::runtime_error& )
|
||||
{
|
||||
// if the GUID failed, just open up the default dsound driver:
|
||||
if( FAILED(DirectSoundCreate8(NULL,&dsound,NULL) ) )
|
||||
throw std::runtime_error( "DirectSound failed to initialize!" );
|
||||
}
|
||||
if ((FAILED(GUIDFromString(m_Device, &cGuid))) ||
|
||||
FAILED(DirectSoundCreate8(&cGuid, &dsound, NULL)))
|
||||
throw std::runtime_error("try again?");
|
||||
} catch (std::runtime_error &) {
|
||||
// if the GUID failed, just open up the default dsound driver:
|
||||
if (FAILED(DirectSoundCreate8(NULL, &dsound, NULL)))
|
||||
throw std::runtime_error("DirectSound failed to initialize!");
|
||||
}
|
||||
|
||||
if( FAILED(dsound->SetCooperativeLevel(GetDesktopWindow(),DSSCL_PRIORITY)) )
|
||||
throw std::runtime_error( "DirectSound Error: Cooperative level could not be set." );
|
||||
if (FAILED(dsound->SetCooperativeLevel(GetDesktopWindow(), DSSCL_PRIORITY)))
|
||||
throw std::runtime_error("DirectSound Error: Cooperative level could not be set.");
|
||||
|
||||
// Determine the user's speaker configuration, and select an expansion option as needed.
|
||||
// FAIL : Directsound doesn't appear to support audio expansion >_<
|
||||
// Determine the user's speaker configuration, and select an expansion option as needed.
|
||||
// FAIL : Directsound doesn't appear to support audio expansion >_<
|
||||
|
||||
DWORD speakerConfig = 2;
|
||||
//dsound->GetSpeakerConfig( &speakerConfig );
|
||||
DWORD speakerConfig = 2;
|
||||
//dsound->GetSpeakerConfig( &speakerConfig );
|
||||
|
||||
IDirectSoundBuffer* buffer_;
|
||||
DSBUFFERDESC desc;
|
||||
IDirectSoundBuffer *buffer_;
|
||||
DSBUFFERDESC desc;
|
||||
|
||||
// Set up WAV format structure.
|
||||
// Set up WAV format structure.
|
||||
|
||||
memset(&wfx, 0, sizeof(WAVEFORMATEX));
|
||||
wfx.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wfx.nSamplesPerSec = SampleRate;
|
||||
wfx.nChannels = (WORD)speakerConfig;
|
||||
wfx.wBitsPerSample = 16;
|
||||
wfx.nBlockAlign = 2*(WORD)speakerConfig;
|
||||
wfx.nAvgBytesPerSec = SampleRate * wfx.nBlockAlign;
|
||||
wfx.cbSize = 0;
|
||||
memset(&wfx, 0, sizeof(WAVEFORMATEX));
|
||||
wfx.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wfx.nSamplesPerSec = SampleRate;
|
||||
wfx.nChannels = (WORD)speakerConfig;
|
||||
wfx.wBitsPerSample = 16;
|
||||
wfx.nBlockAlign = 2 * (WORD)speakerConfig;
|
||||
wfx.nAvgBytesPerSec = SampleRate * wfx.nBlockAlign;
|
||||
wfx.cbSize = 0;
|
||||
|
||||
uint BufferSizeBytes = BufferSize * wfx.nBlockAlign;
|
||||
uint BufferSizeBytes = BufferSize * wfx.nBlockAlign;
|
||||
|
||||
// Set up DSBUFFERDESC structure.
|
||||
// Set up DSBUFFERDESC structure.
|
||||
|
||||
memset(&desc, 0, sizeof(DSBUFFERDESC));
|
||||
desc.dwSize = sizeof(DSBUFFERDESC);
|
||||
desc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY;
|
||||
desc.dwBufferBytes = BufferSizeBytes * m_NumBuffers;
|
||||
desc.lpwfxFormat = &wfx;
|
||||
memset(&desc, 0, sizeof(DSBUFFERDESC));
|
||||
desc.dwSize = sizeof(DSBUFFERDESC);
|
||||
desc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY;
|
||||
desc.dwBufferBytes = BufferSizeBytes * m_NumBuffers;
|
||||
desc.lpwfxFormat = &wfx;
|
||||
|
||||
// Try a hardware buffer first, and then fall back on a software buffer if
|
||||
// that one fails.
|
||||
// Try a hardware buffer first, and then fall back on a software buffer if
|
||||
// that one fails.
|
||||
|
||||
desc.dwFlags |= m_UseHardware ? DSBCAPS_LOCHARDWARE : DSBCAPS_LOCSOFTWARE;
|
||||
desc.dwFlags |= m_DisableGlobalFocus ? DSBCAPS_STICKYFOCUS : DSBCAPS_GLOBALFOCUS;
|
||||
desc.dwFlags |= m_UseHardware ? DSBCAPS_LOCHARDWARE : DSBCAPS_LOCSOFTWARE;
|
||||
desc.dwFlags |= m_DisableGlobalFocus ? DSBCAPS_STICKYFOCUS : DSBCAPS_GLOBALFOCUS;
|
||||
|
||||
if( FAILED(dsound->CreateSoundBuffer(&desc, &buffer_, 0) ) )
|
||||
{
|
||||
if( m_UseHardware )
|
||||
{
|
||||
desc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_LOCSOFTWARE;
|
||||
desc.dwFlags |= m_DisableGlobalFocus ? DSBCAPS_STICKYFOCUS : DSBCAPS_GLOBALFOCUS;
|
||||
if (FAILED(dsound->CreateSoundBuffer(&desc, &buffer_, 0))) {
|
||||
if (m_UseHardware) {
|
||||
desc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_LOCSOFTWARE;
|
||||
desc.dwFlags |= m_DisableGlobalFocus ? DSBCAPS_STICKYFOCUS : DSBCAPS_GLOBALFOCUS;
|
||||
|
||||
if( FAILED(dsound->CreateSoundBuffer(&desc, &buffer_, 0) ) )
|
||||
throw std::runtime_error( "DirectSound Error: Buffer could not be created." );
|
||||
}
|
||||
if (FAILED(dsound->CreateSoundBuffer(&desc, &buffer_, 0)))
|
||||
throw std::runtime_error("DirectSound Error: Buffer could not be created.");
|
||||
}
|
||||
|
||||
throw std::runtime_error( "DirectSound Error: Buffer could not be created." );
|
||||
}
|
||||
if( FAILED(buffer_->QueryInterface(IID_IDirectSoundBuffer8,(void**)&buffer)) || buffer == NULL )
|
||||
throw std::runtime_error( "DirectSound Error: Interface could not be queried." );
|
||||
throw std::runtime_error("DirectSound Error: Buffer could not be created.");
|
||||
}
|
||||
if (FAILED(buffer_->QueryInterface(IID_IDirectSoundBuffer8, (void **)&buffer)) || buffer == NULL)
|
||||
throw std::runtime_error("DirectSound Error: Interface could not be queried.");
|
||||
|
||||
buffer_->Release();
|
||||
verifyc( buffer->QueryInterface(IID_IDirectSoundNotify8,(void**)&buffer_notify) );
|
||||
buffer_->Release();
|
||||
verifyc(buffer->QueryInterface(IID_IDirectSoundNotify8, (void **)&buffer_notify));
|
||||
|
||||
DSBPOSITIONNOTIFY not[MAX_BUFFER_COUNT];
|
||||
DSBPOSITIONNOTIFY not[MAX_BUFFER_COUNT];
|
||||
|
||||
for(uint i=0;i<m_NumBuffers;i++)
|
||||
{
|
||||
buffer_events[i] = CreateEvent(NULL,FALSE,FALSE,NULL);
|
||||
not[i].dwOffset = (wfx.nBlockAlign + BufferSizeBytes*(i+1)) % desc.dwBufferBytes;
|
||||
not[i].hEventNotify = buffer_events[i];
|
||||
}
|
||||
for (uint i = 0; i < m_NumBuffers; i++) {
|
||||
buffer_events[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
not[i].dwOffset = (wfx.nBlockAlign + BufferSizeBytes * (i + 1)) % desc.dwBufferBytes;
|
||||
not[i].hEventNotify = buffer_events[i];
|
||||
}
|
||||
|
||||
buffer_notify->SetNotificationPositions(m_NumBuffers,not);
|
||||
buffer_notify->SetNotificationPositions(m_NumBuffers, not);
|
||||
|
||||
LPVOID p1=0,p2=0;
|
||||
DWORD s1=0,s2=0;
|
||||
LPVOID p1 = 0, p2 = 0;
|
||||
DWORD s1 = 0, s2 = 0;
|
||||
|
||||
verifyc(buffer->Lock(0,desc.dwBufferBytes,&p1,&s1,&p2,&s2,0));
|
||||
assert(p2==0);
|
||||
memset(p1,0,s1);
|
||||
verifyc(buffer->Unlock(p1,s1,p2,s2));
|
||||
verifyc(buffer->Lock(0, desc.dwBufferBytes, &p1, &s1, &p2, &s2, 0));
|
||||
assert(p2 == 0);
|
||||
memset(p1, 0, s1);
|
||||
verifyc(buffer->Unlock(p1, s1, p2, s2));
|
||||
|
||||
//Play the buffer !
|
||||
verifyc(buffer->Play(0,0,DSBPLAY_LOOPING));
|
||||
//Play the buffer !
|
||||
verifyc(buffer->Play(0, 0, DSBPLAY_LOOPING));
|
||||
|
||||
// Start Thread
|
||||
myLastWrite = 0;
|
||||
dsound_running = true;
|
||||
thread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)RThread<StereoOut16>,this,0,&tid);
|
||||
SetThreadPriority(thread,THREAD_PRIORITY_ABOVE_NORMAL);
|
||||
// Start Thread
|
||||
myLastWrite = 0;
|
||||
dsound_running = true;
|
||||
thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RThread<StereoOut16>, this, 0, &tid);
|
||||
SetThreadPriority(thread, THREAD_PRIORITY_ABOVE_NORMAL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
// Stop Thread
|
||||
fprintf(stderr,"* SPU2-X: Waiting for DSound thread to finish...");
|
||||
dsound_running=false;
|
||||
void Close()
|
||||
{
|
||||
// Stop Thread
|
||||
fprintf(stderr, "* SPU2-X: Waiting for DSound thread to finish...");
|
||||
dsound_running = false;
|
||||
|
||||
WaitForSingleObject(thread,INFINITE);
|
||||
CloseHandle(thread);
|
||||
WaitForSingleObject(thread, INFINITE);
|
||||
CloseHandle(thread);
|
||||
|
||||
fprintf(stderr," Done.\n");
|
||||
fprintf(stderr, " Done.\n");
|
||||
|
||||
//
|
||||
// Clean up
|
||||
//
|
||||
if( buffer != NULL )
|
||||
{
|
||||
buffer->Stop();
|
||||
//
|
||||
// Clean up
|
||||
//
|
||||
if (buffer != NULL) {
|
||||
buffer->Stop();
|
||||
|
||||
for(u32 i=0;i<m_NumBuffers;i++)
|
||||
{
|
||||
if( buffer_events[i] != NULL )
|
||||
CloseHandle(buffer_events[i]);
|
||||
buffer_events[i] = NULL;
|
||||
}
|
||||
for (u32 i = 0; i < m_NumBuffers; i++) {
|
||||
if (buffer_events[i] != NULL)
|
||||
CloseHandle(buffer_events[i]);
|
||||
buffer_events[i] = NULL;
|
||||
}
|
||||
|
||||
safe_release( buffer_notify );
|
||||
safe_release( buffer );
|
||||
}
|
||||
safe_release(buffer_notify);
|
||||
safe_release(buffer);
|
||||
}
|
||||
|
||||
safe_release( dsound );
|
||||
CoUninitialize();
|
||||
}
|
||||
safe_release(dsound);
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
private:
|
||||
bool _DSEnumCallback(LPGUID lpGuid, LPCTSTR lpcstrDescription, LPCTSTR lpcstrModule, LPVOID lpContext)
|
||||
{
|
||||
m_devices[ndevs].name = lpcstrDescription;
|
||||
|
||||
bool _DSEnumCallback( LPGUID lpGuid, LPCTSTR lpcstrDescription, LPCTSTR lpcstrModule, LPVOID lpContext )
|
||||
{
|
||||
m_devices[ndevs].name = lpcstrDescription;
|
||||
if (lpGuid) {
|
||||
m_devices[ndevs].guid = *lpGuid;
|
||||
m_devices[ndevs].hasGuid = true;
|
||||
} else {
|
||||
m_devices[ndevs].hasGuid = false;
|
||||
}
|
||||
ndevs++;
|
||||
|
||||
if(lpGuid)
|
||||
{
|
||||
m_devices[ndevs].guid = *lpGuid;
|
||||
m_devices[ndevs].hasGuid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_devices[ndevs].hasGuid = false;
|
||||
}
|
||||
ndevs++;
|
||||
if (ndevs < 32)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(ndevs<32) return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
bool _ConfigProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
int wmId, wmEvent;
|
||||
int tSel = 0;
|
||||
|
||||
bool _ConfigProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
|
||||
{
|
||||
int wmId,wmEvent;
|
||||
int tSel = 0;
|
||||
switch (uMsg) {
|
||||
case WM_INITDIALOG: {
|
||||
wchar_t temp[128];
|
||||
|
||||
switch(uMsg)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
wchar_t temp[128];
|
||||
haveGuid = !FAILED(GUIDFromString(m_Device, &DevGuid));
|
||||
SendMessage(GetDlgItem(hWnd, IDC_DS_DEVICE), CB_RESETCONTENT, 0, 0);
|
||||
|
||||
haveGuid = !FAILED(GUIDFromString(m_Device, &DevGuid));
|
||||
SendMessage(GetDlgItem(hWnd,IDC_DS_DEVICE),CB_RESETCONTENT,0,0);
|
||||
ndevs = 0;
|
||||
DirectSoundEnumerate(DSEnumCallback, NULL);
|
||||
|
||||
ndevs=0;
|
||||
DirectSoundEnumerate( DSEnumCallback, NULL );
|
||||
tSel = -1;
|
||||
for (int i = 0; i < ndevs; i++) {
|
||||
SendMessage(GetDlgItem(hWnd, IDC_DS_DEVICE), CB_ADDSTRING, 0, (LPARAM)m_devices[i].name.wc_str());
|
||||
if (haveGuid && IsEqualGUID(m_devices[i].guid, DevGuid) || tSel < 0 && !m_devices[i].hasGuid)
|
||||
tSel = i;
|
||||
}
|
||||
|
||||
tSel=-1;
|
||||
for(int i=0;i<ndevs;i++)
|
||||
{
|
||||
SendMessage(GetDlgItem(hWnd,IDC_DS_DEVICE),CB_ADDSTRING,0,(LPARAM)m_devices[i].name.wc_str());
|
||||
if(haveGuid && IsEqualGUID(m_devices[i].guid,DevGuid) || tSel < 0 && !m_devices[i].hasGuid)
|
||||
tSel = i;
|
||||
}
|
||||
if (tSel >= 0)
|
||||
SendMessage(GetDlgItem(hWnd, IDC_DS_DEVICE), CB_SETCURSEL, tSel, 0);
|
||||
|
||||
if(tSel>=0)
|
||||
SendMessage(GetDlgItem(hWnd,IDC_DS_DEVICE),CB_SETCURSEL,tSel,0);
|
||||
INIT_SLIDER(IDC_BUFFERS_SLIDER, 2, MAX_BUFFER_COUNT, 2, 1, 1);
|
||||
SendMessage(GetDlgItem(hWnd, IDC_BUFFERS_SLIDER), TBM_SETPOS, TRUE, m_NumBuffers);
|
||||
swprintf_s(temp, L"%d (%d ms latency)", m_NumBuffers, 1000 / (96000 / (m_NumBuffers * BufferSize)));
|
||||
SetWindowText(GetDlgItem(hWnd, IDC_LATENCY_LABEL), temp);
|
||||
|
||||
INIT_SLIDER( IDC_BUFFERS_SLIDER, 2, MAX_BUFFER_COUNT, 2, 1, 1 );
|
||||
SendMessage(GetDlgItem(hWnd,IDC_BUFFERS_SLIDER),TBM_SETPOS,TRUE,m_NumBuffers);
|
||||
swprintf_s(temp, L"%d (%d ms latency)",m_NumBuffers, 1000 / (96000 / (m_NumBuffers * BufferSize)));
|
||||
SetWindowText(GetDlgItem(hWnd,IDC_LATENCY_LABEL),temp);
|
||||
SET_CHECK(IDC_GLOBALFOCUS_DISABLE, m_DisableGlobalFocus);
|
||||
SET_CHECK(IDC_USE_HARDWARE, m_UseHardware);
|
||||
} break;
|
||||
|
||||
SET_CHECK( IDC_GLOBALFOCUS_DISABLE, m_DisableGlobalFocus );
|
||||
SET_CHECK( IDC_USE_HARDWARE, m_UseHardware );
|
||||
}
|
||||
break;
|
||||
case WM_COMMAND: {
|
||||
wchar_t temp[128];
|
||||
|
||||
case WM_COMMAND:
|
||||
{
|
||||
wchar_t temp[128];
|
||||
wmId = LOWORD(wParam);
|
||||
wmEvent = HIWORD(wParam);
|
||||
// Parse the menu selections:
|
||||
switch (wmId) {
|
||||
case IDOK: {
|
||||
int i = (int)SendMessage(GetDlgItem(hWnd, IDC_DS_DEVICE), CB_GETCURSEL, 0, 0);
|
||||
|
||||
wmId = LOWORD(wParam);
|
||||
wmEvent = HIWORD(wParam);
|
||||
// Parse the menu selections:
|
||||
switch (wmId)
|
||||
{
|
||||
case IDOK:
|
||||
{
|
||||
int i = (int)SendMessage(GetDlgItem(hWnd,IDC_DS_DEVICE),CB_GETCURSEL,0,0);
|
||||
if (!m_devices[i].hasGuid) {
|
||||
m_Device[0] = 0; // clear device name to ""
|
||||
} else {
|
||||
swprintf_s(temp, L"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
|
||||
m_devices[i].guid.Data1,
|
||||
m_devices[i].guid.Data2,
|
||||
m_devices[i].guid.Data3,
|
||||
m_devices[i].guid.Data4[0],
|
||||
m_devices[i].guid.Data4[1],
|
||||
m_devices[i].guid.Data4[2],
|
||||
m_devices[i].guid.Data4[3],
|
||||
m_devices[i].guid.Data4[4],
|
||||
m_devices[i].guid.Data4[5],
|
||||
m_devices[i].guid.Data4[6],
|
||||
m_devices[i].guid.Data4[7]);
|
||||
m_Device = temp;
|
||||
}
|
||||
|
||||
if(!m_devices[i].hasGuid)
|
||||
{
|
||||
m_Device[0] = 0; // clear device name to ""
|
||||
}
|
||||
else
|
||||
{
|
||||
swprintf_s(temp, L"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
|
||||
m_devices[i].guid.Data1,
|
||||
m_devices[i].guid.Data2,
|
||||
m_devices[i].guid.Data3,
|
||||
m_devices[i].guid.Data4[0],
|
||||
m_devices[i].guid.Data4[1],
|
||||
m_devices[i].guid.Data4[2],
|
||||
m_devices[i].guid.Data4[3],
|
||||
m_devices[i].guid.Data4[4],
|
||||
m_devices[i].guid.Data4[5],
|
||||
m_devices[i].guid.Data4[6],
|
||||
m_devices[i].guid.Data4[7]
|
||||
);
|
||||
m_Device = temp;
|
||||
}
|
||||
m_NumBuffers = (int)SendMessage(GetDlgItem(hWnd, IDC_BUFFERS_SLIDER), TBM_GETPOS, 0, 0);
|
||||
|
||||
m_NumBuffers = (int)SendMessage( GetDlgItem( hWnd, IDC_BUFFERS_SLIDER ), TBM_GETPOS, 0, 0 );
|
||||
if (m_NumBuffers < 2)
|
||||
m_NumBuffers = 2;
|
||||
if (m_NumBuffers > MAX_BUFFER_COUNT)
|
||||
m_NumBuffers = MAX_BUFFER_COUNT;
|
||||
|
||||
if( m_NumBuffers < 2 ) m_NumBuffers = 2;
|
||||
if( m_NumBuffers > MAX_BUFFER_COUNT ) m_NumBuffers = MAX_BUFFER_COUNT;
|
||||
EndDialog(hWnd, 0);
|
||||
} break;
|
||||
|
||||
EndDialog(hWnd,0);
|
||||
}
|
||||
break;
|
||||
case IDCANCEL:
|
||||
EndDialog(hWnd, 0);
|
||||
break;
|
||||
|
||||
case IDCANCEL:
|
||||
EndDialog(hWnd,0);
|
||||
break;
|
||||
HANDLE_CHECK(IDC_GLOBALFOCUS_DISABLE, m_DisableGlobalFocus);
|
||||
HANDLE_CHECK(IDC_USE_HARDWARE, m_UseHardware);
|
||||
|
||||
HANDLE_CHECK( IDC_GLOBALFOCUS_DISABLE, m_DisableGlobalFocus );
|
||||
HANDLE_CHECK( IDC_USE_HARDWARE, m_UseHardware );
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_HSCROLL: {
|
||||
wmId = LOWORD(wParam);
|
||||
wmEvent = HIWORD(wParam);
|
||||
switch (wmId) {
|
||||
//case TB_ENDTRACK:
|
||||
//case TB_THUMBPOSITION:
|
||||
case TB_LINEUP:
|
||||
case TB_LINEDOWN:
|
||||
case TB_PAGEUP:
|
||||
case TB_PAGEDOWN:
|
||||
wmEvent = (int)SendMessage((HWND)lParam, TBM_GETPOS, 0, 0);
|
||||
case TB_THUMBTRACK: {
|
||||
wchar_t temp[128];
|
||||
if (wmEvent < 2)
|
||||
wmEvent = 2;
|
||||
if (wmEvent > MAX_BUFFER_COUNT)
|
||||
wmEvent = MAX_BUFFER_COUNT;
|
||||
SendMessage((HWND)lParam, TBM_SETPOS, TRUE, wmEvent);
|
||||
swprintf_s(temp, L"%d (%d ms latency)", wmEvent, 1000 / (96000 / (wmEvent * BufferSize)));
|
||||
SetWindowText(GetDlgItem(hWnd, IDC_LATENCY_LABEL), temp);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
} break;
|
||||
|
||||
case WM_HSCROLL:
|
||||
{
|
||||
wmId = LOWORD(wParam);
|
||||
wmEvent = HIWORD(wParam);
|
||||
switch(wmId)
|
||||
{
|
||||
//case TB_ENDTRACK:
|
||||
//case TB_THUMBPOSITION:
|
||||
case TB_LINEUP:
|
||||
case TB_LINEDOWN:
|
||||
case TB_PAGEUP:
|
||||
case TB_PAGEDOWN:
|
||||
wmEvent = (int)SendMessage((HWND)lParam,TBM_GETPOS,0,0);
|
||||
case TB_THUMBTRACK:
|
||||
{
|
||||
wchar_t temp[128];
|
||||
if( wmEvent < 2 ) wmEvent = 2;
|
||||
if( wmEvent > MAX_BUFFER_COUNT ) wmEvent = MAX_BUFFER_COUNT;
|
||||
SendMessage((HWND)lParam,TBM_SETPOS,TRUE,wmEvent);
|
||||
swprintf_s(temp,L"%d (%d ms latency)",wmEvent, 1000 / (96000 / (wmEvent * BufferSize)));
|
||||
SetWindowText(GetDlgItem(hWnd,IDC_LATENCY_LABEL),temp);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK ConfigProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
|
||||
static BOOL CALLBACK DSEnumCallback( LPGUID lpGuid, LPCTSTR lpcstrDescription, LPCTSTR lpcstrModule, LPVOID lpContext );
|
||||
static BOOL CALLBACK ConfigProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
static BOOL CALLBACK DSEnumCallback(LPGUID lpGuid, LPCTSTR lpcstrDescription, LPCTSTR lpcstrModule, LPVOID lpContext);
|
||||
|
||||
public:
|
||||
virtual void Configure(uptr parent)
|
||||
{
|
||||
INT_PTR ret;
|
||||
ret=DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_DSOUND),(HWND)parent,(DLGPROC)ConfigProc,1);
|
||||
if(ret==-1)
|
||||
{
|
||||
MessageBox((HWND)parent,L"Error Opening the config dialog.",L"OMG ERROR!",MB_OK | MB_SETFOREGROUND);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
s32 Test() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
virtual void Configure(uptr parent)
|
||||
{
|
||||
INT_PTR ret;
|
||||
ret = DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_DSOUND), (HWND)parent, (DLGPROC)ConfigProc, 1);
|
||||
if (ret == -1) {
|
||||
MessageBox((HWND)parent, L"Error Opening the config dialog.", L"OMG ERROR!", MB_OK | MB_SETFOREGROUND);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int GetEmptySampleCount()
|
||||
{
|
||||
DWORD play, write;
|
||||
buffer->GetCurrentPosition( &play, &write );
|
||||
s32 Test() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Note: Dsound's write cursor is bogus. Use our own instead:
|
||||
int GetEmptySampleCount()
|
||||
{
|
||||
DWORD play, write;
|
||||
buffer->GetCurrentPosition(&play, &write);
|
||||
|
||||
int empty = play - myLastWrite;
|
||||
if( empty < 0 )
|
||||
empty = -empty;
|
||||
// Note: Dsound's write cursor is bogus. Use our own instead:
|
||||
|
||||
return empty / 2;
|
||||
}
|
||||
int empty = play - myLastWrite;
|
||||
if (empty < 0)
|
||||
empty = -empty;
|
||||
|
||||
const wchar_t* GetIdent() const
|
||||
{
|
||||
return L"dsound";
|
||||
}
|
||||
return empty / 2;
|
||||
}
|
||||
|
||||
const wchar_t* GetLongName() const
|
||||
{
|
||||
return L"DirectSound (nice)";
|
||||
}
|
||||
const wchar_t *GetIdent() const
|
||||
{
|
||||
return L"dsound";
|
||||
}
|
||||
|
||||
void ReadSettings()
|
||||
{
|
||||
CfgReadStr( L"DSOUNDOUT", L"Device", m_Device, L"default" );
|
||||
m_NumBuffers = CfgReadInt( L"DSOUNDOUT", L"Buffer_Count", 5 );
|
||||
m_DisableGlobalFocus = CfgReadBool( L"DSOUNDOUT", L"Disable_Global_Focus", false );
|
||||
m_UseHardware = CfgReadBool( L"DSOUNDOUT", L"Use_Hardware", false );
|
||||
const wchar_t *GetLongName() const
|
||||
{
|
||||
return L"DirectSound (nice)";
|
||||
}
|
||||
|
||||
Clampify( m_NumBuffers, (u8)3, (u8)8 );
|
||||
}
|
||||
void ReadSettings()
|
||||
{
|
||||
CfgReadStr(L"DSOUNDOUT", L"Device", m_Device, L"default");
|
||||
m_NumBuffers = CfgReadInt(L"DSOUNDOUT", L"Buffer_Count", 5);
|
||||
m_DisableGlobalFocus = CfgReadBool(L"DSOUNDOUT", L"Disable_Global_Focus", false);
|
||||
m_UseHardware = CfgReadBool(L"DSOUNDOUT", L"Use_Hardware", false);
|
||||
|
||||
void SetApiSettings(wxString api)
|
||||
{
|
||||
}
|
||||
Clampify(m_NumBuffers, (u8)3, (u8)8);
|
||||
}
|
||||
|
||||
void WriteSettings() const
|
||||
{
|
||||
CfgWriteStr( L"DSOUNDOUT", L"Device", m_Device.empty() ? L"default" : m_Device );
|
||||
CfgWriteInt( L"DSOUNDOUT", L"Buffer_Count", m_NumBuffers );
|
||||
CfgWriteBool( L"DSOUNDOUT", L"Disable_Global_Focus", m_DisableGlobalFocus );
|
||||
CfgWriteBool( L"DSOUNDOUT", L"Use_Hardware", m_UseHardware );
|
||||
}
|
||||
void SetApiSettings(wxString api)
|
||||
{
|
||||
}
|
||||
|
||||
void WriteSettings() const
|
||||
{
|
||||
CfgWriteStr(L"DSOUNDOUT", L"Device", m_Device.empty() ? L"default" : m_Device);
|
||||
CfgWriteInt(L"DSOUNDOUT", L"Buffer_Count", m_NumBuffers);
|
||||
CfgWriteBool(L"DSOUNDOUT", L"Disable_Global_Focus", m_DisableGlobalFocus);
|
||||
CfgWriteBool(L"DSOUNDOUT", L"Use_Hardware", m_UseHardware);
|
||||
}
|
||||
|
||||
} static DS;
|
||||
|
||||
BOOL CALLBACK DSound::ConfigProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
|
||||
BOOL CALLBACK DSound::ConfigProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
return DS._ConfigProc( hWnd, uMsg, wParam, lParam );
|
||||
return DS._ConfigProc(hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
BOOL CALLBACK DSound::DSEnumCallback( LPGUID lpGuid, LPCTSTR lpcstrDescription, LPCTSTR lpcstrModule, LPVOID lpContext )
|
||||
BOOL CALLBACK DSound::DSEnumCallback(LPGUID lpGuid, LPCTSTR lpcstrDescription, LPCTSTR lpcstrModule, LPVOID lpContext)
|
||||
{
|
||||
pxAssume( DSoundOut != NULL );
|
||||
return DS._DSEnumCallback( lpGuid, lpcstrDescription, lpcstrModule, lpContext );
|
||||
pxAssume(DSoundOut != NULL);
|
||||
return DS._DSEnumCallback(lpGuid, lpcstrDescription, lpcstrModule, lpContext);
|
||||
}
|
||||
|
||||
SndOutModule *DSoundOut = &DS;
|
||||
|
|
|
@ -26,41 +26,41 @@
|
|||
|
||||
namespace Exception
|
||||
{
|
||||
class XAudio2Error : public std::runtime_error
|
||||
{
|
||||
protected:
|
||||
static const char* SomeKindaErrorString(HRESULT hr)
|
||||
{
|
||||
switch (hr) {
|
||||
case XAUDIO2_E_INVALID_CALL:
|
||||
return "Invalid call for the XA2 object state.";
|
||||
class XAudio2Error : public std::runtime_error
|
||||
{
|
||||
protected:
|
||||
static const char *SomeKindaErrorString(HRESULT hr)
|
||||
{
|
||||
switch (hr) {
|
||||
case XAUDIO2_E_INVALID_CALL:
|
||||
return "Invalid call for the XA2 object state.";
|
||||
|
||||
case XAUDIO2_E_DEVICE_INVALIDATED:
|
||||
return "Device is unavailable, unplugged, unsupported, or has been consumed by The Nothing.";
|
||||
}
|
||||
return "Unknown error code!";
|
||||
}
|
||||
case XAUDIO2_E_DEVICE_INVALIDATED:
|
||||
return "Device is unavailable, unplugged, unsupported, or has been consumed by The Nothing.";
|
||||
}
|
||||
return "Unknown error code!";
|
||||
}
|
||||
|
||||
public:
|
||||
const HRESULT ErrorCode;
|
||||
std::string m_Message;
|
||||
public:
|
||||
const HRESULT ErrorCode;
|
||||
std::string m_Message;
|
||||
|
||||
const char* CMessage() const
|
||||
{
|
||||
return m_Message.c_str();
|
||||
}
|
||||
const char *CMessage() const
|
||||
{
|
||||
return m_Message.c_str();
|
||||
}
|
||||
|
||||
virtual ~XAudio2Error() throw() {}
|
||||
XAudio2Error(const HRESULT result, const std::string& msg) :
|
||||
runtime_error(msg),
|
||||
ErrorCode(result),
|
||||
m_Message()
|
||||
{
|
||||
char omg[1024];
|
||||
sprintf_s(omg, "%s (code 0x%x)\n\n%s", what(), ErrorCode, SomeKindaErrorString(ErrorCode));
|
||||
m_Message = omg;
|
||||
}
|
||||
};
|
||||
virtual ~XAudio2Error() throw() {}
|
||||
XAudio2Error(const HRESULT result, const std::string &msg)
|
||||
: runtime_error(msg)
|
||||
, ErrorCode(result)
|
||||
, m_Message()
|
||||
{
|
||||
char omg[1024];
|
||||
sprintf_s(omg, "%s (code 0x%x)\n\n%s", what(), ErrorCode, SomeKindaErrorString(ErrorCode));
|
||||
m_Message = omg;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static const double SndOutNormalizer = (double)(1UL << (SndOutVolumeShift + 16));
|
||||
|
@ -68,334 +68,364 @@ static const double SndOutNormalizer = (double)(1UL << (SndOutVolumeShift + 16))
|
|||
class XAudio2Mod : public SndOutModule
|
||||
{
|
||||
private:
|
||||
static const int PacketsPerBuffer = 8;
|
||||
static const int MAX_BUFFER_COUNT = 3;
|
||||
static const int PacketsPerBuffer = 8;
|
||||
static const int MAX_BUFFER_COUNT = 3;
|
||||
|
||||
class BaseStreamingVoice : public IXAudio2VoiceCallback
|
||||
{
|
||||
protected:
|
||||
IXAudio2SourceVoice* pSourceVoice;
|
||||
s16* qbuffer;
|
||||
class BaseStreamingVoice : public IXAudio2VoiceCallback
|
||||
{
|
||||
protected:
|
||||
IXAudio2SourceVoice *pSourceVoice;
|
||||
s16 *qbuffer;
|
||||
|
||||
const uint m_nBuffers;
|
||||
const uint m_nChannels;
|
||||
const uint m_BufferSize;
|
||||
const uint m_BufferSizeBytes;
|
||||
const uint m_nBuffers;
|
||||
const uint m_nChannels;
|
||||
const uint m_BufferSize;
|
||||
const uint m_BufferSizeBytes;
|
||||
|
||||
CRITICAL_SECTION cs;
|
||||
CRITICAL_SECTION cs;
|
||||
|
||||
public:
|
||||
int GetEmptySampleCount()
|
||||
{
|
||||
XAUDIO2_VOICE_STATE state;
|
||||
pSourceVoice->GetState(&state);
|
||||
return state.SamplesPlayed & (m_BufferSize - 1);
|
||||
}
|
||||
public:
|
||||
int GetEmptySampleCount()
|
||||
{
|
||||
XAUDIO2_VOICE_STATE state;
|
||||
pSourceVoice->GetState(&state);
|
||||
return state.SamplesPlayed & (m_BufferSize - 1);
|
||||
}
|
||||
|
||||
virtual ~BaseStreamingVoice()
|
||||
{
|
||||
}
|
||||
virtual ~BaseStreamingVoice()
|
||||
{
|
||||
}
|
||||
|
||||
BaseStreamingVoice(uint numChannels) :
|
||||
m_nBuffers(Config_XAudio2.NumBuffers),
|
||||
m_nChannels(numChannels),
|
||||
m_BufferSize(SndOutPacketSize * m_nChannels * PacketsPerBuffer),
|
||||
m_BufferSizeBytes(m_BufferSize * sizeof(s16))
|
||||
{
|
||||
}
|
||||
BaseStreamingVoice(uint numChannels)
|
||||
: m_nBuffers(Config_XAudio2.NumBuffers)
|
||||
, m_nChannels(numChannels)
|
||||
, m_BufferSize(SndOutPacketSize * m_nChannels * PacketsPerBuffer)
|
||||
, m_BufferSizeBytes(m_BufferSize * sizeof(s16))
|
||||
{
|
||||
}
|
||||
|
||||
virtual void Init(IXAudio2* pXAudio2) = 0;
|
||||
virtual void Init(IXAudio2 *pXAudio2) = 0;
|
||||
|
||||
protected:
|
||||
// Several things must be initialized separate of the constructor, due to the fact that
|
||||
// virtual calls can't be made from the constructor's context.
|
||||
void _init(IXAudio2* pXAudio2, uint chanConfig)
|
||||
{
|
||||
WAVEFORMATEXTENSIBLE wfx;
|
||||
protected:
|
||||
// Several things must be initialized separate of the constructor, due to the fact that
|
||||
// virtual calls can't be made from the constructor's context.
|
||||
void _init(IXAudio2 *pXAudio2, uint chanConfig)
|
||||
{
|
||||
WAVEFORMATEXTENSIBLE wfx;
|
||||
|
||||
memset(&wfx, 0, sizeof(WAVEFORMATEXTENSIBLE));
|
||||
wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
|
||||
wfx.Format.nSamplesPerSec = SampleRate;
|
||||
wfx.Format.nChannels = m_nChannels;
|
||||
wfx.Format.wBitsPerSample = 16;
|
||||
wfx.Format.nBlockAlign = wfx.Format.nChannels * wfx.Format.wBitsPerSample / 8;
|
||||
wfx.Format.nAvgBytesPerSec = SampleRate * wfx.Format.nBlockAlign;
|
||||
wfx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
|
||||
wfx.Samples.wValidBitsPerSample = 16;
|
||||
wfx.dwChannelMask = chanConfig;
|
||||
wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
|
||||
memset(&wfx, 0, sizeof(WAVEFORMATEXTENSIBLE));
|
||||
wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
|
||||
wfx.Format.nSamplesPerSec = SampleRate;
|
||||
wfx.Format.nChannels = m_nChannels;
|
||||
wfx.Format.wBitsPerSample = 16;
|
||||
wfx.Format.nBlockAlign = wfx.Format.nChannels * wfx.Format.wBitsPerSample / 8;
|
||||
wfx.Format.nAvgBytesPerSec = SampleRate * wfx.Format.nBlockAlign;
|
||||
wfx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
|
||||
wfx.Samples.wValidBitsPerSample = 16;
|
||||
wfx.dwChannelMask = chanConfig;
|
||||
wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
|
||||
|
||||
//
|
||||
// Create an XAudio2 voice to stream this wave
|
||||
//
|
||||
HRESULT hr;
|
||||
if (FAILED(hr = pXAudio2->CreateSourceVoice(&pSourceVoice, (WAVEFORMATEX*)&wfx,
|
||||
XAUDIO2_VOICE_NOSRC, 1.0f, this))) {
|
||||
throw Exception::XAudio2Error(hr, "XAudio2 CreateSourceVoice failure.");
|
||||
}
|
||||
//
|
||||
// Create an XAudio2 voice to stream this wave
|
||||
//
|
||||
HRESULT hr;
|
||||
if (FAILED(hr = pXAudio2->CreateSourceVoice(&pSourceVoice, (WAVEFORMATEX *)&wfx,
|
||||
XAUDIO2_VOICE_NOSRC, 1.0f, this))) {
|
||||
throw Exception::XAudio2Error(hr, "XAudio2 CreateSourceVoice failure.");
|
||||
}
|
||||
|
||||
InitializeCriticalSection(&cs);
|
||||
EnterCriticalSection(&cs);
|
||||
InitializeCriticalSection(&cs);
|
||||
EnterCriticalSection(&cs);
|
||||
|
||||
pSourceVoice->FlushSourceBuffers();
|
||||
pSourceVoice->Start(0, 0);
|
||||
pSourceVoice->FlushSourceBuffers();
|
||||
pSourceVoice->Start(0, 0);
|
||||
|
||||
qbuffer = new s16[m_nBuffers * m_BufferSize];
|
||||
ZeroMemory(qbuffer, m_BufferSizeBytes * m_nBuffers);
|
||||
qbuffer = new s16[m_nBuffers * m_BufferSize];
|
||||
ZeroMemory(qbuffer, m_BufferSizeBytes * m_nBuffers);
|
||||
|
||||
// Start some buffers.
|
||||
// Start some buffers.
|
||||
|
||||
for (uint i = 0; i < m_nBuffers; i++) {
|
||||
XAUDIO2_BUFFER buf = { 0 };
|
||||
buf.AudioBytes = m_BufferSizeBytes;
|
||||
buf.pContext = &qbuffer[i*m_BufferSize];
|
||||
buf.pAudioData = (BYTE*)buf.pContext;
|
||||
pSourceVoice->SubmitSourceBuffer(&buf);
|
||||
}
|
||||
for (uint i = 0; i < m_nBuffers; i++) {
|
||||
XAUDIO2_BUFFER buf = {0};
|
||||
buf.AudioBytes = m_BufferSizeBytes;
|
||||
buf.pContext = &qbuffer[i * m_BufferSize];
|
||||
buf.pAudioData = (BYTE *)buf.pContext;
|
||||
pSourceVoice->SubmitSourceBuffer(&buf);
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&cs);
|
||||
}
|
||||
LeaveCriticalSection(&cs);
|
||||
}
|
||||
|
||||
STDMETHOD_(void, OnVoiceProcessingPassStart) () {}
|
||||
STDMETHOD_(void, OnVoiceProcessingPassStart) (UINT32) {}
|
||||
STDMETHOD_(void, OnVoiceProcessingPassEnd) () {}
|
||||
STDMETHOD_(void, OnStreamEnd) () {}
|
||||
STDMETHOD_(void, OnBufferStart) (void*) {}
|
||||
STDMETHOD_(void, OnLoopEnd) (void*) {}
|
||||
STDMETHOD_(void, OnVoiceError) (THIS_ void* pBufferContext, HRESULT Error) {}
|
||||
};
|
||||
STDMETHOD_(void, OnVoiceProcessingPassStart)
|
||||
() {}
|
||||
STDMETHOD_(void, OnVoiceProcessingPassStart)
|
||||
(UINT32) {}
|
||||
STDMETHOD_(void, OnVoiceProcessingPassEnd)
|
||||
() {}
|
||||
STDMETHOD_(void, OnStreamEnd)
|
||||
() {}
|
||||
STDMETHOD_(void, OnBufferStart)
|
||||
(void *) {}
|
||||
STDMETHOD_(void, OnLoopEnd)
|
||||
(void *) {}
|
||||
STDMETHOD_(void, OnVoiceError)
|
||||
(THIS_ void *pBufferContext, HRESULT Error) {}
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
class StreamingVoice : public BaseStreamingVoice
|
||||
{
|
||||
public:
|
||||
StreamingVoice(IXAudio2* pXAudio2) :
|
||||
BaseStreamingVoice(sizeof(T) / sizeof(s16))
|
||||
{
|
||||
}
|
||||
template <typename T>
|
||||
class StreamingVoice : public BaseStreamingVoice
|
||||
{
|
||||
public:
|
||||
StreamingVoice(IXAudio2 *pXAudio2)
|
||||
: BaseStreamingVoice(sizeof(T) / sizeof(s16))
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~StreamingVoice()
|
||||
{
|
||||
IXAudio2SourceVoice* killMe = pSourceVoice;
|
||||
pSourceVoice = NULL;
|
||||
killMe->FlushSourceBuffers();
|
||||
killMe->DestroyVoice();
|
||||
virtual ~StreamingVoice()
|
||||
{
|
||||
IXAudio2SourceVoice *killMe = pSourceVoice;
|
||||
pSourceVoice = NULL;
|
||||
killMe->FlushSourceBuffers();
|
||||
killMe->DestroyVoice();
|
||||
|
||||
EnterCriticalSection(&cs);
|
||||
safe_delete_array(qbuffer);
|
||||
LeaveCriticalSection(&cs);
|
||||
DeleteCriticalSection(&cs);
|
||||
}
|
||||
EnterCriticalSection(&cs);
|
||||
safe_delete_array(qbuffer);
|
||||
LeaveCriticalSection(&cs);
|
||||
DeleteCriticalSection(&cs);
|
||||
}
|
||||
|
||||
void Init(IXAudio2* pXAudio2)
|
||||
{
|
||||
int chanMask = 0;
|
||||
switch (m_nChannels) {
|
||||
case 1: chanMask |= SPEAKER_FRONT_CENTER; break;
|
||||
case 2: chanMask |= SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; break;
|
||||
case 3: chanMask |= SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY; break;
|
||||
case 4: chanMask |= SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT; break;
|
||||
case 5: chanMask |= SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT; break;
|
||||
case 6: chanMask |= SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_LOW_FREQUENCY; break;
|
||||
case 8: chanMask |= SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT | SPEAKER_LOW_FREQUENCY; break;
|
||||
}
|
||||
_init(pXAudio2, chanMask);
|
||||
}
|
||||
void Init(IXAudio2 *pXAudio2)
|
||||
{
|
||||
int chanMask = 0;
|
||||
switch (m_nChannels) {
|
||||
case 1:
|
||||
chanMask |= SPEAKER_FRONT_CENTER;
|
||||
break;
|
||||
case 2:
|
||||
chanMask |= SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
|
||||
break;
|
||||
case 3:
|
||||
chanMask |= SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY;
|
||||
break;
|
||||
case 4:
|
||||
chanMask |= SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
|
||||
break;
|
||||
case 5:
|
||||
chanMask |= SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
|
||||
break;
|
||||
case 6:
|
||||
chanMask |= SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_LOW_FREQUENCY;
|
||||
break;
|
||||
case 8:
|
||||
chanMask |= SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT | SPEAKER_LOW_FREQUENCY;
|
||||
break;
|
||||
}
|
||||
_init(pXAudio2, chanMask);
|
||||
}
|
||||
|
||||
protected:
|
||||
STDMETHOD_(void, OnBufferEnd) (void* context)
|
||||
{
|
||||
EnterCriticalSection(&cs);
|
||||
protected:
|
||||
STDMETHOD_(void, OnBufferEnd)
|
||||
(void *context)
|
||||
{
|
||||
EnterCriticalSection(&cs);
|
||||
|
||||
// All of these checks are necessary because XAudio2 is wonky shizat.
|
||||
if (pSourceVoice == NULL || context == NULL) {
|
||||
LeaveCriticalSection(&cs);
|
||||
return;
|
||||
}
|
||||
// All of these checks are necessary because XAudio2 is wonky shizat.
|
||||
if (pSourceVoice == NULL || context == NULL) {
|
||||
LeaveCriticalSection(&cs);
|
||||
return;
|
||||
}
|
||||
|
||||
T* qb = (T*)context;
|
||||
T *qb = (T *)context;
|
||||
|
||||
for (int p = 0; p < PacketsPerBuffer; p++, qb += SndOutPacketSize)
|
||||
SndBuffer::ReadSamples(qb);
|
||||
for (int p = 0; p < PacketsPerBuffer; p++, qb += SndOutPacketSize)
|
||||
SndBuffer::ReadSamples(qb);
|
||||
|
||||
XAUDIO2_BUFFER buf = { 0 };
|
||||
buf.AudioBytes = m_BufferSizeBytes;
|
||||
buf.pAudioData = (BYTE*)context;
|
||||
buf.pContext = context;
|
||||
XAUDIO2_BUFFER buf = {0};
|
||||
buf.AudioBytes = m_BufferSizeBytes;
|
||||
buf.pAudioData = (BYTE *)context;
|
||||
buf.pContext = context;
|
||||
|
||||
pSourceVoice->SubmitSourceBuffer(&buf);
|
||||
LeaveCriticalSection(&cs);
|
||||
}
|
||||
pSourceVoice->SubmitSourceBuffer(&buf);
|
||||
LeaveCriticalSection(&cs);
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
HMODULE xAudio2DLL;
|
||||
decltype(&XAudio2Create) pXAudio2Create;
|
||||
CComPtr<IXAudio2> pXAudio2;
|
||||
IXAudio2MasteringVoice* pMasteringVoice;
|
||||
BaseStreamingVoice* voiceContext;
|
||||
HMODULE xAudio2DLL;
|
||||
decltype(&XAudio2Create) pXAudio2Create;
|
||||
CComPtr<IXAudio2> pXAudio2;
|
||||
IXAudio2MasteringVoice *pMasteringVoice;
|
||||
BaseStreamingVoice *voiceContext;
|
||||
|
||||
public:
|
||||
s32 Init()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
s32 Init()
|
||||
{
|
||||
HRESULT hr;
|
||||
pxAssume(pXAudio2 == NULL);
|
||||
|
||||
pxAssume(pXAudio2 == NULL);
|
||||
xAudio2DLL = LoadLibraryEx(XAUDIO2_DLL, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
|
||||
if (xAudio2DLL == nullptr)
|
||||
throw std::runtime_error("Could not load " XAUDIO2_DLL_A ". Error code:" + std::to_string(GetLastError()));
|
||||
|
||||
xAudio2DLL = LoadLibraryEx(XAUDIO2_DLL, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
|
||||
if (xAudio2DLL == nullptr)
|
||||
throw std::runtime_error("Could not load " XAUDIO2_DLL_A ". Error code:" + std::to_string(GetLastError()));
|
||||
pXAudio2Create = reinterpret_cast<decltype(&XAudio2Create)>(GetProcAddress(xAudio2DLL, "XAudio2Create"));
|
||||
if (pXAudio2Create == nullptr)
|
||||
throw std::runtime_error("XAudio2Create not found. Error code: " + std::to_string(GetLastError()));
|
||||
|
||||
pXAudio2Create = reinterpret_cast<decltype(&XAudio2Create)>(GetProcAddress(xAudio2DLL, "XAudio2Create"));
|
||||
if (pXAudio2Create == nullptr)
|
||||
throw std::runtime_error("XAudio2Create not found. Error code: " + std::to_string(GetLastError()));
|
||||
//
|
||||
// Initialize XAudio2
|
||||
//
|
||||
CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||||
|
||||
//
|
||||
// Initialize XAudio2
|
||||
//
|
||||
CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||||
try {
|
||||
if (FAILED(hr = pXAudio2Create(&pXAudio2, 0, XAUDIO2_DEFAULT_PROCESSOR)))
|
||||
throw Exception::XAudio2Error(hr, "Failed to init XAudio2 engine. Error Details:");
|
||||
|
||||
try {
|
||||
if (FAILED(hr = pXAudio2Create(&pXAudio2, 0, XAUDIO2_DEFAULT_PROCESSOR)))
|
||||
throw Exception::XAudio2Error(hr, "Failed to init XAudio2 engine. Error Details:");
|
||||
// Stereo Expansion was planned to grab the currently configured number of
|
||||
// Speakers from Windows's audio config.
|
||||
// This doesn't always work though, so let it be a user configurable option.
|
||||
|
||||
// Stereo Expansion was planned to grab the currently configured number of
|
||||
// Speakers from Windows's audio config.
|
||||
// This doesn't always work though, so let it be a user configurable option.
|
||||
int speakers;
|
||||
switch (numSpeakers) // speakers = (numSpeakers + 1) *2; ?
|
||||
{
|
||||
case 0:
|
||||
speakers = 2;
|
||||
break; // Stereo
|
||||
case 1:
|
||||
speakers = 4;
|
||||
break; // Quadrafonic
|
||||
case 2:
|
||||
speakers = 6;
|
||||
break; // Surround 5.1
|
||||
case 3:
|
||||
speakers = 8;
|
||||
break; // Surround 7.1
|
||||
default:
|
||||
speakers = 2;
|
||||
}
|
||||
|
||||
int speakers;
|
||||
switch (numSpeakers) // speakers = (numSpeakers + 1) *2; ?
|
||||
{
|
||||
case 0: speakers = 2; break; // Stereo
|
||||
case 1: speakers = 4; break; // Quadrafonic
|
||||
case 2: speakers = 6; break; // Surround 5.1
|
||||
case 3: speakers = 8; break; // Surround 7.1
|
||||
default: speakers = 2;
|
||||
}
|
||||
//
|
||||
// Create a mastering voice
|
||||
//
|
||||
if (FAILED(hr = pXAudio2->CreateMasteringVoice(&pMasteringVoice, speakers, SampleRate))) {
|
||||
SysMessage("Failed creating mastering voice: %#X\n", hr);
|
||||
CoUninitialize();
|
||||
return -1;
|
||||
}
|
||||
|
||||
//
|
||||
// Create a mastering voice
|
||||
//
|
||||
if (FAILED(hr = pXAudio2->CreateMasteringVoice(&pMasteringVoice, speakers, SampleRate))) {
|
||||
SysMessage("Failed creating mastering voice: %#X\n", hr);
|
||||
CoUninitialize();
|
||||
return -1;
|
||||
}
|
||||
switch (speakers) {
|
||||
case 2:
|
||||
ConLog("* SPU2 > Using normal 2 speaker stereo output.\n");
|
||||
voiceContext = new StreamingVoice<StereoOut16>(pXAudio2);
|
||||
break;
|
||||
|
||||
switch (speakers) {
|
||||
case 2:
|
||||
ConLog("* SPU2 > Using normal 2 speaker stereo output.\n");
|
||||
voiceContext = new StreamingVoice<StereoOut16>(pXAudio2);
|
||||
break;
|
||||
case 3:
|
||||
ConLog("* SPU2 > 2.1 speaker expansion enabled.\n");
|
||||
voiceContext = new StreamingVoice<Stereo21Out16>(pXAudio2);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
ConLog("* SPU2 > 2.1 speaker expansion enabled.\n");
|
||||
voiceContext = new StreamingVoice<Stereo21Out16>(pXAudio2);
|
||||
break;
|
||||
case 4:
|
||||
ConLog("* SPU2 > 4 speaker expansion enabled [quadraphenia]\n");
|
||||
voiceContext = new StreamingVoice<Stereo40Out16>(pXAudio2);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
ConLog("* SPU2 > 4 speaker expansion enabled [quadraphenia]\n");
|
||||
voiceContext = new StreamingVoice<Stereo40Out16>(pXAudio2);
|
||||
break;
|
||||
case 5:
|
||||
ConLog("* SPU2 > 4.1 speaker expansion enabled.\n");
|
||||
voiceContext = new StreamingVoice<Stereo41Out16>(pXAudio2);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
ConLog("* SPU2 > 4.1 speaker expansion enabled.\n");
|
||||
voiceContext = new StreamingVoice<Stereo41Out16>(pXAudio2);
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
switch (dplLevel) {
|
||||
case 0:
|
||||
ConLog("* SPU2 > 5.1 speaker expansion enabled.\n");
|
||||
voiceContext = new StreamingVoice<Stereo51Out16>(pXAudio2); //"normal" stereo upmix
|
||||
break;
|
||||
case 1:
|
||||
ConLog("* SPU2 > 5.1 speaker expansion with basic ProLogic dematrixing enabled.\n");
|
||||
voiceContext = new StreamingVoice<Stereo51Out16Dpl>(pXAudio2); // basic Dpl decoder without rear stereo balancing
|
||||
break;
|
||||
case 2:
|
||||
ConLog("* SPU2 > 5.1 speaker expansion with experimental ProLogicII dematrixing enabled.\n");
|
||||
voiceContext = new StreamingVoice<Stereo51Out16DplII>(pXAudio2); //gigas PLII
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 6:
|
||||
case 7:
|
||||
switch (dplLevel) {
|
||||
case 0:
|
||||
ConLog("* SPU2 > 5.1 speaker expansion enabled.\n");
|
||||
voiceContext = new StreamingVoice<Stereo51Out16>(pXAudio2); //"normal" stereo upmix
|
||||
break;
|
||||
case 1:
|
||||
ConLog("* SPU2 > 5.1 speaker expansion with basic ProLogic dematrixing enabled.\n");
|
||||
voiceContext = new StreamingVoice<Stereo51Out16Dpl>(pXAudio2); // basic Dpl decoder without rear stereo balancing
|
||||
break;
|
||||
case 2:
|
||||
ConLog("* SPU2 > 5.1 speaker expansion with experimental ProLogicII dematrixing enabled.\n");
|
||||
voiceContext = new StreamingVoice<Stereo51Out16DplII>(pXAudio2); //gigas PLII
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default: // anything 8 or more gets the 7.1 treatment!
|
||||
ConLog("* SPU2 > 7.1 speaker expansion enabled.\n");
|
||||
voiceContext = new StreamingVoice<Stereo51Out16>(pXAudio2);
|
||||
break;
|
||||
}
|
||||
|
||||
default: // anything 8 or more gets the 7.1 treatment!
|
||||
ConLog("* SPU2 > 7.1 speaker expansion enabled.\n");
|
||||
voiceContext = new StreamingVoice<Stereo51Out16>(pXAudio2);
|
||||
break;
|
||||
}
|
||||
voiceContext->Init(pXAudio2);
|
||||
} catch (Exception::XAudio2Error &ex) {
|
||||
SysMessage(ex.CMessage());
|
||||
pXAudio2.Release();
|
||||
CoUninitialize();
|
||||
return -1;
|
||||
}
|
||||
|
||||
voiceContext->Init(pXAudio2);
|
||||
} catch (Exception::XAudio2Error& ex) {
|
||||
SysMessage(ex.CMessage());
|
||||
pXAudio2.Release();
|
||||
CoUninitialize();
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
void Close()
|
||||
{
|
||||
safe_delete(voiceContext);
|
||||
|
||||
void Close()
|
||||
{
|
||||
safe_delete(voiceContext);
|
||||
voiceContext = NULL;
|
||||
|
||||
voiceContext = NULL;
|
||||
if (pMasteringVoice != NULL)
|
||||
pMasteringVoice->DestroyVoice();
|
||||
|
||||
if (pMasteringVoice != NULL)
|
||||
pMasteringVoice->DestroyVoice();
|
||||
pMasteringVoice = NULL;
|
||||
|
||||
pMasteringVoice = NULL;
|
||||
pXAudio2.Release();
|
||||
CoUninitialize();
|
||||
|
||||
pXAudio2.Release();
|
||||
CoUninitialize();
|
||||
if (xAudio2DLL) {
|
||||
FreeLibrary(xAudio2DLL);
|
||||
xAudio2DLL = nullptr;
|
||||
pXAudio2Create = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (xAudio2DLL) {
|
||||
FreeLibrary(xAudio2DLL);
|
||||
xAudio2DLL = nullptr;
|
||||
pXAudio2Create = nullptr;
|
||||
}
|
||||
}
|
||||
virtual void Configure(uptr parent)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void Configure(uptr parent)
|
||||
{
|
||||
}
|
||||
s32 Test() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 Test() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int GetEmptySampleCount()
|
||||
{
|
||||
if (voiceContext == NULL)
|
||||
return 0;
|
||||
return voiceContext->GetEmptySampleCount();
|
||||
}
|
||||
|
||||
int GetEmptySampleCount()
|
||||
{
|
||||
if (voiceContext == NULL) return 0;
|
||||
return voiceContext->GetEmptySampleCount();
|
||||
}
|
||||
const wchar_t *GetIdent() const
|
||||
{
|
||||
return L"xaudio2";
|
||||
}
|
||||
|
||||
const wchar_t* GetIdent() const
|
||||
{
|
||||
return L"xaudio2";
|
||||
}
|
||||
const wchar_t *GetLongName() const
|
||||
{
|
||||
return L"XAudio 2 (Recommended)";
|
||||
}
|
||||
|
||||
const wchar_t* GetLongName() const
|
||||
{
|
||||
return L"XAudio 2 (Recommended)";
|
||||
}
|
||||
void ReadSettings()
|
||||
{
|
||||
}
|
||||
|
||||
void ReadSettings()
|
||||
{
|
||||
}
|
||||
void SetApiSettings(wxString api)
|
||||
{
|
||||
}
|
||||
|
||||
void SetApiSettings(wxString api)
|
||||
{
|
||||
}
|
||||
|
||||
void WriteSettings() const
|
||||
{
|
||||
}
|
||||
void WriteSettings() const
|
||||
{
|
||||
}
|
||||
|
||||
} static XA2;
|
||||
|
||||
|
|
|
@ -24,410 +24,428 @@
|
|||
|
||||
namespace Exception
|
||||
{
|
||||
class XAudio2_27Error : public std::runtime_error
|
||||
{
|
||||
protected:
|
||||
static const char* SomeKindaErrorString( HRESULT hr )
|
||||
{
|
||||
switch( hr )
|
||||
{
|
||||
case XAUDIO2_E_INVALID_CALL:
|
||||
return "Invalid call for the XA2 object state.";
|
||||
|
||||
case XAUDIO2_E_DEVICE_INVALIDATED:
|
||||
return "Device is unavailable, unplugged, unsupported, or has been consumed by The Nothing.";
|
||||
}
|
||||
return "Unknown error code!";
|
||||
}
|
||||
|
||||
public:
|
||||
const HRESULT ErrorCode;
|
||||
std::string m_Message;
|
||||
|
||||
const char* CMessage() const
|
||||
{
|
||||
return m_Message.c_str();
|
||||
}
|
||||
|
||||
virtual ~XAudio2_27Error() throw() {}
|
||||
XAudio2_27Error( const HRESULT result, const std::string& msg ) :
|
||||
runtime_error( msg ),
|
||||
ErrorCode( result ),
|
||||
m_Message()
|
||||
{
|
||||
char omg[1024];
|
||||
sprintf_s( omg, "%s (code 0x%x)\n\n%s", what(), ErrorCode, SomeKindaErrorString( ErrorCode ) );
|
||||
m_Message = omg;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static const double SndOutNormalizer = (double)(1UL<<(SndOutVolumeShift+16));
|
||||
|
||||
class XAudio2_27_Mod: public SndOutModule
|
||||
class XAudio2_27Error : public std::runtime_error
|
||||
{
|
||||
private:
|
||||
static const int PacketsPerBuffer = 8;
|
||||
static const int MAX_BUFFER_COUNT = 3;
|
||||
protected:
|
||||
static const char *SomeKindaErrorString(HRESULT hr)
|
||||
{
|
||||
switch (hr) {
|
||||
case XAUDIO2_E_INVALID_CALL:
|
||||
return "Invalid call for the XA2 object state.";
|
||||
|
||||
class BaseStreamingVoice : public IXAudio2VoiceCallback
|
||||
{
|
||||
protected:
|
||||
IXAudio2SourceVoice* pSourceVoice;
|
||||
s16* qbuffer;
|
||||
|
||||
const uint m_nBuffers;
|
||||
const uint m_nChannels;
|
||||
const uint m_BufferSize;
|
||||
const uint m_BufferSizeBytes;
|
||||
|
||||
CRITICAL_SECTION cs;
|
||||
|
||||
public:
|
||||
int GetEmptySampleCount()
|
||||
{
|
||||
XAUDIO2_VOICE_STATE state;
|
||||
pSourceVoice->GetState( &state );
|
||||
return state.SamplesPlayed & (m_BufferSize-1);
|
||||
}
|
||||
|
||||
virtual ~BaseStreamingVoice()
|
||||
{
|
||||
}
|
||||
|
||||
BaseStreamingVoice( uint numChannels ) :
|
||||
m_nBuffers( Config_XAudio2.NumBuffers ),
|
||||
m_nChannels( numChannels ),
|
||||
m_BufferSize( SndOutPacketSize * m_nChannels * PacketsPerBuffer ),
|
||||
m_BufferSizeBytes( m_BufferSize * sizeof(s16) )
|
||||
{
|
||||
}
|
||||
|
||||
virtual void Init( IXAudio2* pXAudio2 ) = 0;
|
||||
|
||||
protected:
|
||||
// Several things must be initialized separate of the constructor, due to the fact that
|
||||
// virtual calls can't be made from the constructor's context.
|
||||
void _init( IXAudio2* pXAudio2, uint chanConfig )
|
||||
{
|
||||
WAVEFORMATEXTENSIBLE wfx;
|
||||
|
||||
memset(&wfx, 0, sizeof(WAVEFORMATEXTENSIBLE));
|
||||
wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
|
||||
wfx.Format.nSamplesPerSec = SampleRate;
|
||||
wfx.Format.nChannels = m_nChannels;
|
||||
wfx.Format.wBitsPerSample = 16;
|
||||
wfx.Format.nBlockAlign = wfx.Format.nChannels*wfx.Format.wBitsPerSample/8;
|
||||
wfx.Format.nAvgBytesPerSec = SampleRate * wfx.Format.nBlockAlign;
|
||||
wfx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
|
||||
wfx.Samples.wValidBitsPerSample = 16;
|
||||
wfx.dwChannelMask = chanConfig;
|
||||
wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
|
||||
|
||||
//
|
||||
// Create an XAudio2 voice to stream this wave
|
||||
//
|
||||
HRESULT hr;
|
||||
if( FAILED(hr = pXAudio2->CreateSourceVoice( &pSourceVoice, (WAVEFORMATEX*)&wfx,
|
||||
XAUDIO2_VOICE_NOSRC, 1.0f, this ) ) )
|
||||
{
|
||||
throw Exception::XAudio2_27Error( hr, "XAudio2 CreateSourceVoice failure." );
|
||||
}
|
||||
|
||||
InitializeCriticalSection( &cs );
|
||||
EnterCriticalSection( &cs );
|
||||
|
||||
pSourceVoice->FlushSourceBuffers();
|
||||
pSourceVoice->Start( 0, 0 );
|
||||
|
||||
qbuffer = new s16[m_nBuffers * m_BufferSize];
|
||||
ZeroMemory( qbuffer, m_BufferSizeBytes * m_nBuffers );
|
||||
|
||||
// Start some buffers.
|
||||
|
||||
for( uint i=0; i<m_nBuffers; i++ )
|
||||
{
|
||||
XAUDIO2_BUFFER buf = {0};
|
||||
buf.AudioBytes = m_BufferSizeBytes;
|
||||
buf.pContext = &qbuffer[i*m_BufferSize];
|
||||
buf.pAudioData = (BYTE*)buf.pContext;
|
||||
pSourceVoice->SubmitSourceBuffer( &buf );
|
||||
}
|
||||
|
||||
LeaveCriticalSection( &cs );
|
||||
}
|
||||
|
||||
STDMETHOD_(void, OnVoiceProcessingPassStart) () {}
|
||||
STDMETHOD_(void, OnVoiceProcessingPassStart) (UINT32) { };
|
||||
STDMETHOD_(void, OnVoiceProcessingPassEnd) () {}
|
||||
STDMETHOD_(void, OnStreamEnd) () {}
|
||||
STDMETHOD_(void, OnBufferStart) ( void* ) {}
|
||||
STDMETHOD_(void, OnLoopEnd) ( void* ) {}
|
||||
STDMETHOD_(void, OnVoiceError) (THIS_ void* pBufferContext, HRESULT Error) { };
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
class StreamingVoice : public BaseStreamingVoice
|
||||
{
|
||||
public:
|
||||
StreamingVoice( IXAudio2* pXAudio2 ) :
|
||||
BaseStreamingVoice( sizeof(T) / sizeof( s16 ) )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~StreamingVoice()
|
||||
{
|
||||
IXAudio2SourceVoice* killMe = pSourceVoice;
|
||||
pSourceVoice = NULL;
|
||||
killMe->FlushSourceBuffers();
|
||||
killMe->DestroyVoice();
|
||||
|
||||
EnterCriticalSection( &cs );
|
||||
safe_delete_array( qbuffer );
|
||||
LeaveCriticalSection( &cs );
|
||||
DeleteCriticalSection( &cs );
|
||||
}
|
||||
|
||||
void Init( IXAudio2* pXAudio2 )
|
||||
{
|
||||
int chanMask = 0;
|
||||
switch(m_nChannels)
|
||||
{
|
||||
case 1: chanMask |= SPEAKER_FRONT_CENTER; break;
|
||||
case 2: chanMask |= SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; break;
|
||||
case 3: chanMask |= SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY; break;
|
||||
case 4: chanMask |= SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT; break;
|
||||
case 5: chanMask |= SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT; break;
|
||||
case 6: chanMask |= SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_LOW_FREQUENCY; break;
|
||||
case 8: chanMask |= SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT | SPEAKER_LOW_FREQUENCY; break;
|
||||
}
|
||||
_init( pXAudio2, chanMask );
|
||||
}
|
||||
|
||||
protected:
|
||||
STDMETHOD_(void, OnBufferEnd) ( void* context )
|
||||
{
|
||||
EnterCriticalSection( &cs );
|
||||
|
||||
// All of these checks are necessary because XAudio2 is wonky shizat.
|
||||
if( pSourceVoice == NULL || context == NULL )
|
||||
{
|
||||
LeaveCriticalSection( &cs );
|
||||
return;
|
||||
}
|
||||
|
||||
T* qb = (T*)context;
|
||||
|
||||
for(int p=0; p<PacketsPerBuffer; p++, qb+=SndOutPacketSize )
|
||||
SndBuffer::ReadSamples( qb );
|
||||
|
||||
XAUDIO2_BUFFER buf = {0};
|
||||
buf.AudioBytes = m_BufferSizeBytes;
|
||||
buf.pAudioData = (BYTE*)context;
|
||||
buf.pContext = context;
|
||||
|
||||
pSourceVoice->SubmitSourceBuffer( &buf );
|
||||
LeaveCriticalSection( &cs );
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
HMODULE xAudio2DLL;
|
||||
CComPtr<IXAudio2> pXAudio2;
|
||||
IXAudio2MasteringVoice* pMasteringVoice;
|
||||
BaseStreamingVoice* voiceContext;
|
||||
case XAUDIO2_E_DEVICE_INVALIDATED:
|
||||
return "Device is unavailable, unplugged, unsupported, or has been consumed by The Nothing.";
|
||||
}
|
||||
return "Unknown error code!";
|
||||
}
|
||||
|
||||
public:
|
||||
const HRESULT ErrorCode;
|
||||
std::string m_Message;
|
||||
|
||||
s32 Init()
|
||||
{
|
||||
HRESULT hr;
|
||||
const char *CMessage() const
|
||||
{
|
||||
return m_Message.c_str();
|
||||
}
|
||||
|
||||
pxAssume( pXAudio2 == NULL );
|
||||
virtual ~XAudio2_27Error() throw() {}
|
||||
XAudio2_27Error(const HRESULT result, const std::string &msg)
|
||||
: runtime_error(msg)
|
||||
, ErrorCode(result)
|
||||
, m_Message()
|
||||
{
|
||||
char omg[1024];
|
||||
sprintf_s(omg, "%s (code 0x%x)\n\n%s", what(), ErrorCode, SomeKindaErrorString(ErrorCode));
|
||||
m_Message = omg;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// On some systems XAudio2.7 can unload itself and cause PCSX2 to crash.
|
||||
// Maintain an extra library reference so it can't do so. Does not
|
||||
// affect XAudio 2.8+, but that's Win8+. See
|
||||
// http://blogs.msdn.com/b/chuckw/archive/2015/10/09/known-issues-xaudio-2-7.aspx
|
||||
static const double SndOutNormalizer = (double)(1UL << (SndOutVolumeShift + 16));
|
||||
|
||||
class XAudio2_27_Mod : public SndOutModule
|
||||
{
|
||||
private:
|
||||
static const int PacketsPerBuffer = 8;
|
||||
static const int MAX_BUFFER_COUNT = 3;
|
||||
|
||||
class BaseStreamingVoice : public IXAudio2VoiceCallback
|
||||
{
|
||||
protected:
|
||||
IXAudio2SourceVoice *pSourceVoice;
|
||||
s16 *qbuffer;
|
||||
|
||||
const uint m_nBuffers;
|
||||
const uint m_nChannels;
|
||||
const uint m_BufferSize;
|
||||
const uint m_BufferSizeBytes;
|
||||
|
||||
CRITICAL_SECTION cs;
|
||||
|
||||
public:
|
||||
int GetEmptySampleCount()
|
||||
{
|
||||
XAUDIO2_VOICE_STATE state;
|
||||
pSourceVoice->GetState(&state);
|
||||
return state.SamplesPlayed & (m_BufferSize - 1);
|
||||
}
|
||||
|
||||
virtual ~BaseStreamingVoice()
|
||||
{
|
||||
}
|
||||
|
||||
BaseStreamingVoice(uint numChannels)
|
||||
: m_nBuffers(Config_XAudio2.NumBuffers)
|
||||
, m_nChannels(numChannels)
|
||||
, m_BufferSize(SndOutPacketSize * m_nChannels * PacketsPerBuffer)
|
||||
, m_BufferSizeBytes(m_BufferSize * sizeof(s16))
|
||||
{
|
||||
}
|
||||
|
||||
virtual void Init(IXAudio2 *pXAudio2) = 0;
|
||||
|
||||
protected:
|
||||
// Several things must be initialized separate of the constructor, due to the fact that
|
||||
// virtual calls can't be made from the constructor's context.
|
||||
void _init(IXAudio2 *pXAudio2, uint chanConfig)
|
||||
{
|
||||
WAVEFORMATEXTENSIBLE wfx;
|
||||
|
||||
memset(&wfx, 0, sizeof(WAVEFORMATEXTENSIBLE));
|
||||
wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
|
||||
wfx.Format.nSamplesPerSec = SampleRate;
|
||||
wfx.Format.nChannels = m_nChannels;
|
||||
wfx.Format.wBitsPerSample = 16;
|
||||
wfx.Format.nBlockAlign = wfx.Format.nChannels * wfx.Format.wBitsPerSample / 8;
|
||||
wfx.Format.nAvgBytesPerSec = SampleRate * wfx.Format.nBlockAlign;
|
||||
wfx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
|
||||
wfx.Samples.wValidBitsPerSample = 16;
|
||||
wfx.dwChannelMask = chanConfig;
|
||||
wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
|
||||
|
||||
//
|
||||
// Create an XAudio2 voice to stream this wave
|
||||
//
|
||||
HRESULT hr;
|
||||
if (FAILED(hr = pXAudio2->CreateSourceVoice(&pSourceVoice, (WAVEFORMATEX *)&wfx,
|
||||
XAUDIO2_VOICE_NOSRC, 1.0f, this))) {
|
||||
throw Exception::XAudio2_27Error(hr, "XAudio2 CreateSourceVoice failure.");
|
||||
}
|
||||
|
||||
InitializeCriticalSection(&cs);
|
||||
EnterCriticalSection(&cs);
|
||||
|
||||
pSourceVoice->FlushSourceBuffers();
|
||||
pSourceVoice->Start(0, 0);
|
||||
|
||||
qbuffer = new s16[m_nBuffers * m_BufferSize];
|
||||
ZeroMemory(qbuffer, m_BufferSizeBytes * m_nBuffers);
|
||||
|
||||
// Start some buffers.
|
||||
|
||||
for (uint i = 0; i < m_nBuffers; i++) {
|
||||
XAUDIO2_BUFFER buf = {0};
|
||||
buf.AudioBytes = m_BufferSizeBytes;
|
||||
buf.pContext = &qbuffer[i * m_BufferSize];
|
||||
buf.pAudioData = (BYTE *)buf.pContext;
|
||||
pSourceVoice->SubmitSourceBuffer(&buf);
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&cs);
|
||||
}
|
||||
|
||||
STDMETHOD_(void, OnVoiceProcessingPassStart)
|
||||
() {}
|
||||
STDMETHOD_(void, OnVoiceProcessingPassStart)
|
||||
(UINT32){};
|
||||
STDMETHOD_(void, OnVoiceProcessingPassEnd)
|
||||
() {}
|
||||
STDMETHOD_(void, OnStreamEnd)
|
||||
() {}
|
||||
STDMETHOD_(void, OnBufferStart)
|
||||
(void *) {}
|
||||
STDMETHOD_(void, OnLoopEnd)
|
||||
(void *) {}
|
||||
STDMETHOD_(void, OnVoiceError)
|
||||
(THIS_ void *pBufferContext, HRESULT Error){};
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class StreamingVoice : public BaseStreamingVoice
|
||||
{
|
||||
public:
|
||||
StreamingVoice(IXAudio2 *pXAudio2)
|
||||
: BaseStreamingVoice(sizeof(T) / sizeof(s16))
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~StreamingVoice()
|
||||
{
|
||||
IXAudio2SourceVoice *killMe = pSourceVoice;
|
||||
pSourceVoice = NULL;
|
||||
killMe->FlushSourceBuffers();
|
||||
killMe->DestroyVoice();
|
||||
|
||||
EnterCriticalSection(&cs);
|
||||
safe_delete_array(qbuffer);
|
||||
LeaveCriticalSection(&cs);
|
||||
DeleteCriticalSection(&cs);
|
||||
}
|
||||
|
||||
void Init(IXAudio2 *pXAudio2)
|
||||
{
|
||||
int chanMask = 0;
|
||||
switch (m_nChannels) {
|
||||
case 1:
|
||||
chanMask |= SPEAKER_FRONT_CENTER;
|
||||
break;
|
||||
case 2:
|
||||
chanMask |= SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
|
||||
break;
|
||||
case 3:
|
||||
chanMask |= SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY;
|
||||
break;
|
||||
case 4:
|
||||
chanMask |= SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
|
||||
break;
|
||||
case 5:
|
||||
chanMask |= SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
|
||||
break;
|
||||
case 6:
|
||||
chanMask |= SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_LOW_FREQUENCY;
|
||||
break;
|
||||
case 8:
|
||||
chanMask |= SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT | SPEAKER_LOW_FREQUENCY;
|
||||
break;
|
||||
}
|
||||
_init(pXAudio2, chanMask);
|
||||
}
|
||||
|
||||
protected:
|
||||
STDMETHOD_(void, OnBufferEnd)
|
||||
(void *context)
|
||||
{
|
||||
EnterCriticalSection(&cs);
|
||||
|
||||
// All of these checks are necessary because XAudio2 is wonky shizat.
|
||||
if (pSourceVoice == NULL || context == NULL) {
|
||||
LeaveCriticalSection(&cs);
|
||||
return;
|
||||
}
|
||||
|
||||
T *qb = (T *)context;
|
||||
|
||||
for (int p = 0; p < PacketsPerBuffer; p++, qb += SndOutPacketSize)
|
||||
SndBuffer::ReadSamples(qb);
|
||||
|
||||
XAUDIO2_BUFFER buf = {0};
|
||||
buf.AudioBytes = m_BufferSizeBytes;
|
||||
buf.pAudioData = (BYTE *)context;
|
||||
buf.pContext = context;
|
||||
|
||||
pSourceVoice->SubmitSourceBuffer(&buf);
|
||||
LeaveCriticalSection(&cs);
|
||||
}
|
||||
};
|
||||
|
||||
HMODULE xAudio2DLL;
|
||||
CComPtr<IXAudio2> pXAudio2;
|
||||
IXAudio2MasteringVoice *pMasteringVoice;
|
||||
BaseStreamingVoice *voiceContext;
|
||||
|
||||
public:
|
||||
s32 Init()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
pxAssume(pXAudio2 == NULL);
|
||||
|
||||
// On some systems XAudio2.7 can unload itself and cause PCSX2 to crash.
|
||||
// Maintain an extra library reference so it can't do so. Does not
|
||||
// affect XAudio 2.8+, but that's Win8+. See
|
||||
// http://blogs.msdn.com/b/chuckw/archive/2015/10/09/known-issues-xaudio-2-7.aspx
|
||||
#ifdef _DEBUG
|
||||
xAudio2DLL = LoadLibrary(L"XAudioD2_7.dll");
|
||||
xAudio2DLL = LoadLibrary(L"XAudioD2_7.dll");
|
||||
#else
|
||||
xAudio2DLL = LoadLibrary(L"XAudio2_7.dll");
|
||||
xAudio2DLL = LoadLibrary(L"XAudio2_7.dll");
|
||||
#endif
|
||||
|
||||
//
|
||||
// Initialize XAudio2
|
||||
//
|
||||
CoInitializeEx( NULL, COINIT_MULTITHREADED );
|
||||
//
|
||||
// Initialize XAudio2
|
||||
//
|
||||
CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||||
|
||||
UINT32 flags = 0;
|
||||
if( IsDebugBuild )
|
||||
flags |= XAUDIO2_DEBUG_ENGINE;
|
||||
UINT32 flags = 0;
|
||||
if (IsDebugBuild)
|
||||
flags |= XAUDIO2_DEBUG_ENGINE;
|
||||
|
||||
try
|
||||
{
|
||||
if ( FAILED(hr = XAudio2Create( &pXAudio2, flags ) ) )
|
||||
throw Exception::XAudio2_27Error( hr,
|
||||
"Failed to init XAudio2 engine. XA2 may not be available on your system.\n"
|
||||
"Ensure that you have the latest DirectX runtimes installed, or use \n"
|
||||
"DirectX / WaveOut drivers instead. Error Details:"
|
||||
);
|
||||
try {
|
||||
if (FAILED(hr = XAudio2Create(&pXAudio2, flags)))
|
||||
throw Exception::XAudio2_27Error(hr,
|
||||
"Failed to init XAudio2 engine. XA2 may not be available on your system.\n"
|
||||
"Ensure that you have the latest DirectX runtimes installed, or use \n"
|
||||
"DirectX / WaveOut drivers instead. Error Details:");
|
||||
|
||||
XAUDIO2_DEVICE_DETAILS deviceDetails;
|
||||
pXAudio2->GetDeviceDetails( 0, &deviceDetails );
|
||||
XAUDIO2_DEVICE_DETAILS deviceDetails;
|
||||
pXAudio2->GetDeviceDetails(0, &deviceDetails);
|
||||
|
||||
// Stereo Expansion was planned to grab the currently configured number of
|
||||
// Speakers from Windows's audio config.
|
||||
// This doesn't always work though, so let it be a user configurable option.
|
||||
// Stereo Expansion was planned to grab the currently configured number of
|
||||
// Speakers from Windows's audio config.
|
||||
// This doesn't always work though, so let it be a user configurable option.
|
||||
|
||||
int speakers;
|
||||
switch(numSpeakers) // speakers = (numSpeakers + 1) *2; ?
|
||||
{
|
||||
case 0: speakers = 2; break; // Stereo
|
||||
case 1: speakers = 4; break; // Quadrafonic
|
||||
case 2: speakers = 6; break; // Surround 5.1
|
||||
case 3: speakers = 8; break; // Surround 7.1
|
||||
default: speakers = 2;
|
||||
}
|
||||
int speakers;
|
||||
switch (numSpeakers) // speakers = (numSpeakers + 1) *2; ?
|
||||
{
|
||||
case 0:
|
||||
speakers = 2;
|
||||
break; // Stereo
|
||||
case 1:
|
||||
speakers = 4;
|
||||
break; // Quadrafonic
|
||||
case 2:
|
||||
speakers = 6;
|
||||
break; // Surround 5.1
|
||||
case 3:
|
||||
speakers = 8;
|
||||
break; // Surround 7.1
|
||||
default:
|
||||
speakers = 2;
|
||||
}
|
||||
|
||||
// Any windows driver should support stereo at the software level, I should think!
|
||||
pxAssume( deviceDetails.OutputFormat.Format.nChannels > 1 );
|
||||
// Any windows driver should support stereo at the software level, I should think!
|
||||
pxAssume(deviceDetails.OutputFormat.Format.nChannels > 1);
|
||||
|
||||
//
|
||||
// Create a mastering voice
|
||||
//
|
||||
if ( FAILED(hr = pXAudio2->CreateMasteringVoice( &pMasteringVoice, speakers, SampleRate ) ) )
|
||||
{
|
||||
SysMessage( "Failed creating mastering voice: %#X\n", hr );
|
||||
CoUninitialize();
|
||||
return -1;
|
||||
}
|
||||
//
|
||||
// Create a mastering voice
|
||||
//
|
||||
if (FAILED(hr = pXAudio2->CreateMasteringVoice(&pMasteringVoice, speakers, SampleRate))) {
|
||||
SysMessage("Failed creating mastering voice: %#X\n", hr);
|
||||
CoUninitialize();
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch( speakers )
|
||||
{
|
||||
case 2:
|
||||
ConLog( "* SPU2 > Using normal 2 speaker stereo output.\n" );
|
||||
voiceContext = new StreamingVoice<StereoOut16>( pXAudio2 );
|
||||
break;
|
||||
switch (speakers) {
|
||||
case 2:
|
||||
ConLog("* SPU2 > Using normal 2 speaker stereo output.\n");
|
||||
voiceContext = new StreamingVoice<StereoOut16>(pXAudio2);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
ConLog( "* SPU2 > 2.1 speaker expansion enabled.\n" );
|
||||
voiceContext = new StreamingVoice<Stereo21Out16>( pXAudio2 );
|
||||
break;
|
||||
case 3:
|
||||
ConLog("* SPU2 > 2.1 speaker expansion enabled.\n");
|
||||
voiceContext = new StreamingVoice<Stereo21Out16>(pXAudio2);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
ConLog( "* SPU2 > 4 speaker expansion enabled [quadraphenia]\n" );
|
||||
voiceContext = new StreamingVoice<Stereo40Out16>( pXAudio2 );
|
||||
break;
|
||||
case 4:
|
||||
ConLog("* SPU2 > 4 speaker expansion enabled [quadraphenia]\n");
|
||||
voiceContext = new StreamingVoice<Stereo40Out16>(pXAudio2);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
ConLog( "* SPU2 > 4.1 speaker expansion enabled.\n" );
|
||||
voiceContext = new StreamingVoice<Stereo41Out16>( pXAudio2 );
|
||||
break;
|
||||
case 5:
|
||||
ConLog("* SPU2 > 4.1 speaker expansion enabled.\n");
|
||||
voiceContext = new StreamingVoice<Stereo41Out16>(pXAudio2);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
case 7:
|
||||
switch(dplLevel)
|
||||
{
|
||||
case 0:
|
||||
ConLog( "* SPU2 > 5.1 speaker expansion enabled.\n" );
|
||||
voiceContext = new StreamingVoice<Stereo51Out16>( pXAudio2 ); //"normal" stereo upmix
|
||||
break;
|
||||
case 1:
|
||||
ConLog( "* SPU2 > 5.1 speaker expansion with basic ProLogic dematrixing enabled.\n" );
|
||||
voiceContext = new StreamingVoice<Stereo51Out16Dpl>( pXAudio2 ); // basic Dpl decoder without rear stereo balancing
|
||||
break;
|
||||
case 2:
|
||||
ConLog( "* SPU2 > 5.1 speaker expansion with experimental ProLogicII dematrixing enabled.\n" );
|
||||
voiceContext = new StreamingVoice<Stereo51Out16DplII>( pXAudio2 ); //gigas PLII
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
switch (dplLevel) {
|
||||
case 0:
|
||||
ConLog("* SPU2 > 5.1 speaker expansion enabled.\n");
|
||||
voiceContext = new StreamingVoice<Stereo51Out16>(pXAudio2); //"normal" stereo upmix
|
||||
break;
|
||||
case 1:
|
||||
ConLog("* SPU2 > 5.1 speaker expansion with basic ProLogic dematrixing enabled.\n");
|
||||
voiceContext = new StreamingVoice<Stereo51Out16Dpl>(pXAudio2); // basic Dpl decoder without rear stereo balancing
|
||||
break;
|
||||
case 2:
|
||||
ConLog("* SPU2 > 5.1 speaker expansion with experimental ProLogicII dematrixing enabled.\n");
|
||||
voiceContext = new StreamingVoice<Stereo51Out16DplII>(pXAudio2); //gigas PLII
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default: // anything 8 or more gets the 7.1 treatment!
|
||||
ConLog( "* SPU2 > 7.1 speaker expansion enabled.\n" );
|
||||
voiceContext = new StreamingVoice<Stereo51Out16>( pXAudio2 );
|
||||
break;
|
||||
}
|
||||
default: // anything 8 or more gets the 7.1 treatment!
|
||||
ConLog("* SPU2 > 7.1 speaker expansion enabled.\n");
|
||||
voiceContext = new StreamingVoice<Stereo51Out16>(pXAudio2);
|
||||
break;
|
||||
}
|
||||
|
||||
voiceContext->Init( pXAudio2 );
|
||||
}
|
||||
catch( Exception::XAudio2_27Error& ex )
|
||||
{
|
||||
SysMessage( ex.CMessage() );
|
||||
pXAudio2.Release();
|
||||
CoUninitialize();
|
||||
return -1;
|
||||
}
|
||||
voiceContext->Init(pXAudio2);
|
||||
} catch (Exception::XAudio2_27Error &ex) {
|
||||
SysMessage(ex.CMessage());
|
||||
pXAudio2.Release();
|
||||
CoUninitialize();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
// Clean up?
|
||||
// All XAudio2 interfaces are released when the engine is destroyed,
|
||||
// but being tidy never hurt.
|
||||
void Close()
|
||||
{
|
||||
// Clean up?
|
||||
// All XAudio2 interfaces are released when the engine is destroyed,
|
||||
// but being tidy never hurt.
|
||||
|
||||
// Actually it can hurt. As of DXSDK Aug 2008, doing a full cleanup causes
|
||||
// XA2 on Vista to crash. Even if you copy/paste code directly from Microsoft.
|
||||
// But doing no cleanup at all causes XA2 under XP to crash. So after much trial
|
||||
// and error we found a happy compromise as follows:
|
||||
// Actually it can hurt. As of DXSDK Aug 2008, doing a full cleanup causes
|
||||
// XA2 on Vista to crash. Even if you copy/paste code directly from Microsoft.
|
||||
// But doing no cleanup at all causes XA2 under XP to crash. So after much trial
|
||||
// and error we found a happy compromise as follows:
|
||||
|
||||
safe_delete( voiceContext );
|
||||
safe_delete(voiceContext);
|
||||
|
||||
voiceContext = NULL;
|
||||
voiceContext = NULL;
|
||||
|
||||
if( pMasteringVoice != NULL )
|
||||
pMasteringVoice->DestroyVoice();
|
||||
if (pMasteringVoice != NULL)
|
||||
pMasteringVoice->DestroyVoice();
|
||||
|
||||
pMasteringVoice = NULL;
|
||||
pMasteringVoice = NULL;
|
||||
|
||||
pXAudio2.Release();
|
||||
CoUninitialize();
|
||||
pXAudio2.Release();
|
||||
CoUninitialize();
|
||||
|
||||
if (xAudio2DLL) {
|
||||
FreeLibrary(xAudio2DLL);
|
||||
xAudio2DLL = nullptr;
|
||||
}
|
||||
}
|
||||
if (xAudio2DLL) {
|
||||
FreeLibrary(xAudio2DLL);
|
||||
xAudio2DLL = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Configure(uptr parent)
|
||||
{
|
||||
}
|
||||
virtual void Configure(uptr parent)
|
||||
{
|
||||
}
|
||||
|
||||
s32 Test() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
s32 Test() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetEmptySampleCount()
|
||||
{
|
||||
if( voiceContext == NULL ) return 0;
|
||||
return voiceContext->GetEmptySampleCount();
|
||||
}
|
||||
int GetEmptySampleCount()
|
||||
{
|
||||
if (voiceContext == NULL)
|
||||
return 0;
|
||||
return voiceContext->GetEmptySampleCount();
|
||||
}
|
||||
|
||||
const wchar_t* GetIdent() const
|
||||
{
|
||||
return L"xaudio2";
|
||||
}
|
||||
const wchar_t *GetIdent() const
|
||||
{
|
||||
return L"xaudio2";
|
||||
}
|
||||
|
||||
const wchar_t* GetLongName() const
|
||||
{
|
||||
return L"XAudio 2.7 (Recommended)";
|
||||
}
|
||||
const wchar_t *GetLongName() const
|
||||
{
|
||||
return L"XAudio 2.7 (Recommended)";
|
||||
}
|
||||
|
||||
void ReadSettings()
|
||||
{
|
||||
}
|
||||
void ReadSettings()
|
||||
{
|
||||
}
|
||||
|
||||
void SetApiSettings(wxString api)
|
||||
{
|
||||
}
|
||||
void SetApiSettings(wxString api)
|
||||
{
|
||||
}
|
||||
|
||||
void WriteSettings() const
|
||||
{
|
||||
}
|
||||
void WriteSettings() const
|
||||
{
|
||||
}
|
||||
|
||||
} static XA2;
|
||||
|
||||
|
|
|
@ -19,80 +19,80 @@
|
|||
#include "Dialogs.h"
|
||||
|
||||
|
||||
class WaveOutModule: public SndOutModule
|
||||
class WaveOutModule : public SndOutModule
|
||||
{
|
||||
private:
|
||||
static const uint MAX_BUFFER_COUNT = 8;
|
||||
static const uint MAX_BUFFER_COUNT = 8;
|
||||
|
||||
static const int PacketsPerBuffer = (1024 / SndOutPacketSize);
|
||||
static const int BufferSize = SndOutPacketSize*PacketsPerBuffer;
|
||||
static const int PacketsPerBuffer = (1024 / SndOutPacketSize);
|
||||
static const int BufferSize = SndOutPacketSize * PacketsPerBuffer;
|
||||
|
||||
u32 numBuffers;
|
||||
HWAVEOUT hwodevice;
|
||||
WAVEFORMATEX wformat;
|
||||
WAVEHDR whbuffer[MAX_BUFFER_COUNT];
|
||||
u32 numBuffers;
|
||||
HWAVEOUT hwodevice;
|
||||
WAVEFORMATEX wformat;
|
||||
WAVEHDR whbuffer[MAX_BUFFER_COUNT];
|
||||
|
||||
StereoOut16* qbuffer;
|
||||
StereoOut16 *qbuffer;
|
||||
|
||||
#define QBUFFER(x) (qbuffer + BufferSize * (x))
|
||||
#define QBUFFER(x) (qbuffer + BufferSize * (x))
|
||||
|
||||
bool waveout_running;
|
||||
HANDLE thread;
|
||||
DWORD tid;
|
||||
bool waveout_running;
|
||||
HANDLE thread;
|
||||
DWORD tid;
|
||||
|
||||
wchar_t ErrText[256];
|
||||
wchar_t ErrText[256];
|
||||
|
||||
template< typename T >
|
||||
DWORD CALLBACK Thread()
|
||||
{
|
||||
static const int BufferSizeBytes = BufferSize * sizeof( T );
|
||||
template <typename T>
|
||||
DWORD CALLBACK Thread()
|
||||
{
|
||||
static const int BufferSizeBytes = BufferSize * sizeof(T);
|
||||
|
||||
while( waveout_running )
|
||||
{
|
||||
bool didsomething = false;
|
||||
for(u32 i=0;i<numBuffers;i++)
|
||||
{
|
||||
if(!(whbuffer[i].dwFlags & WHDR_DONE) ) continue;
|
||||
while (waveout_running) {
|
||||
bool didsomething = false;
|
||||
for (u32 i = 0; i < numBuffers; i++) {
|
||||
if (!(whbuffer[i].dwFlags & WHDR_DONE))
|
||||
continue;
|
||||
|
||||
WAVEHDR *buf = whbuffer+i;
|
||||
WAVEHDR *buf = whbuffer + i;
|
||||
|
||||
buf->dwBytesRecorded = buf->dwBufferLength;
|
||||
buf->dwBytesRecorded = buf->dwBufferLength;
|
||||
|
||||
T* t = (T*)buf->lpData;
|
||||
for(int p=0; p<PacketsPerBuffer; p++, t+=SndOutPacketSize )
|
||||
SndBuffer::ReadSamples( t );
|
||||
T *t = (T *)buf->lpData;
|
||||
for (int p = 0; p < PacketsPerBuffer; p++, t += SndOutPacketSize)
|
||||
SndBuffer::ReadSamples(t);
|
||||
|
||||
whbuffer[i].dwFlags &= ~WHDR_DONE;
|
||||
waveOutWrite( hwodevice, buf, sizeof(WAVEHDR) );
|
||||
didsomething = true;
|
||||
}
|
||||
whbuffer[i].dwFlags &= ~WHDR_DONE;
|
||||
waveOutWrite(hwodevice, buf, sizeof(WAVEHDR));
|
||||
didsomething = true;
|
||||
}
|
||||
|
||||
if( didsomething )
|
||||
Sleep(1);
|
||||
else
|
||||
Sleep(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (didsomething)
|
||||
Sleep(1);
|
||||
else
|
||||
Sleep(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
static DWORD CALLBACK RThread(WaveOutModule*obj)
|
||||
{
|
||||
return obj->Thread<T>();
|
||||
}
|
||||
template <typename T>
|
||||
static DWORD CALLBACK RThread(WaveOutModule *obj)
|
||||
{
|
||||
return obj->Thread<T>();
|
||||
}
|
||||
|
||||
public:
|
||||
s32 Init()
|
||||
{
|
||||
numBuffers = Config_WaveOut.NumBuffers;
|
||||
s32 Init()
|
||||
{
|
||||
numBuffers = Config_WaveOut.NumBuffers;
|
||||
|
||||
MMRESULT woores;
|
||||
MMRESULT woores;
|
||||
|
||||
if (Test()) return -1;
|
||||
if (Test())
|
||||
return -1;
|
||||
|
||||
// TODO : Use dsound to determine the speaker configuration, and expand audio from there.
|
||||
// TODO : Use dsound to determine the speaker configuration, and expand audio from there.
|
||||
|
||||
#if 0
|
||||
#if 0
|
||||
int speakerConfig;
|
||||
|
||||
//if( StereoExpansionEnabled )
|
||||
|
@ -129,197 +129,193 @@ public:
|
|||
speakerConfig = 8;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
wformat.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wformat.nSamplesPerSec = SampleRate;
|
||||
wformat.wBitsPerSample = 16;
|
||||
wformat.nChannels = 2;
|
||||
wformat.nBlockAlign = ((wformat.wBitsPerSample * wformat.nChannels) / 8);
|
||||
wformat.nAvgBytesPerSec = (wformat.nSamplesPerSec * wformat.nBlockAlign);
|
||||
wformat.cbSize = 0;
|
||||
wformat.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wformat.nSamplesPerSec = SampleRate;
|
||||
wformat.wBitsPerSample = 16;
|
||||
wformat.nChannels = 2;
|
||||
wformat.nBlockAlign = ((wformat.wBitsPerSample * wformat.nChannels) / 8);
|
||||
wformat.nAvgBytesPerSec = (wformat.nSamplesPerSec * wformat.nBlockAlign);
|
||||
wformat.cbSize = 0;
|
||||
|
||||
qbuffer = new StereoOut16[BufferSize*numBuffers];
|
||||
qbuffer = new StereoOut16[BufferSize * numBuffers];
|
||||
|
||||
woores = waveOutOpen(&hwodevice,WAVE_MAPPER,&wformat,0,0,0);
|
||||
if (woores != MMSYSERR_NOERROR)
|
||||
{
|
||||
waveOutGetErrorText(woores,(wchar_t *)&ErrText,255);
|
||||
SysMessage("WaveOut Error: %s",ErrText);
|
||||
return -1;
|
||||
}
|
||||
woores = waveOutOpen(&hwodevice, WAVE_MAPPER, &wformat, 0, 0, 0);
|
||||
if (woores != MMSYSERR_NOERROR) {
|
||||
waveOutGetErrorText(woores, (wchar_t *)&ErrText, 255);
|
||||
SysMessage("WaveOut Error: %s", ErrText);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const int BufferSizeBytes = wformat.nBlockAlign * BufferSize;
|
||||
const int BufferSizeBytes = wformat.nBlockAlign * BufferSize;
|
||||
|
||||
for(u32 i=0;i<numBuffers;i++)
|
||||
{
|
||||
whbuffer[i].dwBufferLength=BufferSizeBytes;
|
||||
whbuffer[i].dwBytesRecorded=BufferSizeBytes;
|
||||
whbuffer[i].dwFlags=0;
|
||||
whbuffer[i].dwLoops=0;
|
||||
whbuffer[i].dwUser=0;
|
||||
whbuffer[i].lpData=(LPSTR)QBUFFER(i);
|
||||
whbuffer[i].lpNext=0;
|
||||
whbuffer[i].reserved=0;
|
||||
waveOutPrepareHeader(hwodevice,whbuffer+i,sizeof(WAVEHDR));
|
||||
whbuffer[i].dwFlags|=WHDR_DONE; //avoid deadlock
|
||||
}
|
||||
for (u32 i = 0; i < numBuffers; i++) {
|
||||
whbuffer[i].dwBufferLength = BufferSizeBytes;
|
||||
whbuffer[i].dwBytesRecorded = BufferSizeBytes;
|
||||
whbuffer[i].dwFlags = 0;
|
||||
whbuffer[i].dwLoops = 0;
|
||||
whbuffer[i].dwUser = 0;
|
||||
whbuffer[i].lpData = (LPSTR)QBUFFER(i);
|
||||
whbuffer[i].lpNext = 0;
|
||||
whbuffer[i].reserved = 0;
|
||||
waveOutPrepareHeader(hwodevice, whbuffer + i, sizeof(WAVEHDR));
|
||||
whbuffer[i].dwFlags |= WHDR_DONE; //avoid deadlock
|
||||
}
|
||||
|
||||
// Start Thread
|
||||
// [Air]: The waveout code does not use wait objects, so setting a time critical
|
||||
// priority level is a bad idea. Standard priority will do fine. The buffer will get the
|
||||
// love it needs and won't suck resources idling pointlessly. Just don't try to
|
||||
// run it in uber-low-latency mode.
|
||||
waveout_running = true;
|
||||
thread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)RThread<StereoOut16>,this,0,&tid);
|
||||
// Start Thread
|
||||
// [Air]: The waveout code does not use wait objects, so setting a time critical
|
||||
// priority level is a bad idea. Standard priority will do fine. The buffer will get the
|
||||
// love it needs and won't suck resources idling pointlessly. Just don't try to
|
||||
// run it in uber-low-latency mode.
|
||||
waveout_running = true;
|
||||
thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RThread<StereoOut16>, this, 0, &tid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
// Stop Thread
|
||||
fprintf(stderr,"* SPU2-X: Waiting for waveOut thread to finish...");
|
||||
waveout_running=false;
|
||||
void Close()
|
||||
{
|
||||
// Stop Thread
|
||||
fprintf(stderr, "* SPU2-X: Waiting for waveOut thread to finish...");
|
||||
waveout_running = false;
|
||||
|
||||
WaitForSingleObject(thread,INFINITE);
|
||||
CloseHandle(thread);
|
||||
WaitForSingleObject(thread, INFINITE);
|
||||
CloseHandle(thread);
|
||||
|
||||
fprintf(stderr," Done.\n");
|
||||
fprintf(stderr, " Done.\n");
|
||||
|
||||
//
|
||||
// Clean up
|
||||
//
|
||||
waveOutReset(hwodevice);
|
||||
for(u32 i=0;i<numBuffers;i++)
|
||||
{
|
||||
waveOutUnprepareHeader(hwodevice,&whbuffer[i],sizeof(WAVEHDR));
|
||||
}
|
||||
waveOutClose(hwodevice);
|
||||
//
|
||||
// Clean up
|
||||
//
|
||||
waveOutReset(hwodevice);
|
||||
for (u32 i = 0; i < numBuffers; i++) {
|
||||
waveOutUnprepareHeader(hwodevice, &whbuffer[i], sizeof(WAVEHDR));
|
||||
}
|
||||
waveOutClose(hwodevice);
|
||||
|
||||
safe_delete_array( qbuffer );
|
||||
}
|
||||
safe_delete_array(qbuffer);
|
||||
}
|
||||
|
||||
private:
|
||||
static BOOL CALLBACK ConfigProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
int wmId, wmEvent;
|
||||
|
||||
static BOOL CALLBACK ConfigProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
|
||||
{
|
||||
int wmId,wmEvent;
|
||||
switch (uMsg) {
|
||||
case WM_INITDIALOG:
|
||||
|
||||
switch(uMsg)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
wchar_t temp[128];
|
||||
INIT_SLIDER(IDC_BUFFERS_SLIDER, 3, MAX_BUFFER_COUNT, 2, 1, 1);
|
||||
SendMessage(GetDlgItem(hWnd, IDC_BUFFERS_SLIDER), TBM_SETPOS, TRUE, Config_WaveOut.NumBuffers);
|
||||
swprintf_s(temp, 128, L"%d (%d ms latency)", Config_WaveOut.NumBuffers, 1000 / (96000 / (Config_WaveOut.NumBuffers * BufferSize)));
|
||||
SetWindowText(GetDlgItem(hWnd, IDC_LATENCY_LABEL), temp);
|
||||
break;
|
||||
|
||||
wchar_t temp[128];
|
||||
INIT_SLIDER( IDC_BUFFERS_SLIDER, 3, MAX_BUFFER_COUNT, 2, 1, 1 );
|
||||
SendMessage(GetDlgItem(hWnd,IDC_BUFFERS_SLIDER),TBM_SETPOS,TRUE,Config_WaveOut.NumBuffers);
|
||||
swprintf_s(temp, 128, L"%d (%d ms latency)",Config_WaveOut.NumBuffers, 1000 / (96000 / (Config_WaveOut.NumBuffers * BufferSize)));
|
||||
SetWindowText(GetDlgItem(hWnd,IDC_LATENCY_LABEL),temp);
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
wmId = LOWORD(wParam);
|
||||
wmEvent = HIWORD(wParam);
|
||||
// Parse the menu selections:
|
||||
switch (wmId) {
|
||||
case IDOK: {
|
||||
Config_WaveOut.NumBuffers = (int)SendMessage(GetDlgItem(hWnd, IDC_BUFFERS_SLIDER), TBM_GETPOS, 0, 0);
|
||||
|
||||
case WM_COMMAND:
|
||||
wmId = LOWORD(wParam);
|
||||
wmEvent = HIWORD(wParam);
|
||||
// Parse the menu selections:
|
||||
switch (wmId)
|
||||
{
|
||||
case IDOK:
|
||||
{
|
||||
Config_WaveOut.NumBuffers = (int)SendMessage( GetDlgItem( hWnd, IDC_BUFFERS_SLIDER ), TBM_GETPOS, 0, 0 );
|
||||
if (Config_WaveOut.NumBuffers < 3)
|
||||
Config_WaveOut.NumBuffers = 3;
|
||||
if (Config_WaveOut.NumBuffers > MAX_BUFFER_COUNT)
|
||||
Config_WaveOut.NumBuffers = MAX_BUFFER_COUNT;
|
||||
}
|
||||
EndDialog(hWnd, 0);
|
||||
break;
|
||||
case IDCANCEL:
|
||||
EndDialog(hWnd, 0);
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
if( Config_WaveOut.NumBuffers < 3 ) Config_WaveOut.NumBuffers = 3;
|
||||
if( Config_WaveOut.NumBuffers > MAX_BUFFER_COUNT ) Config_WaveOut.NumBuffers = MAX_BUFFER_COUNT;
|
||||
}
|
||||
EndDialog(hWnd,0);
|
||||
break;
|
||||
case IDCANCEL:
|
||||
EndDialog(hWnd,0);
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case WM_HSCROLL:
|
||||
wmId = LOWORD(wParam);
|
||||
wmEvent = HIWORD(wParam);
|
||||
switch (wmId) {
|
||||
//case TB_ENDTRACK:
|
||||
//case TB_THUMBPOSITION:
|
||||
case TB_LINEUP:
|
||||
case TB_LINEDOWN:
|
||||
case TB_PAGEUP:
|
||||
case TB_PAGEDOWN:
|
||||
wmEvent = (int)SendMessage((HWND)lParam, TBM_GETPOS, 0, 0);
|
||||
case TB_THUMBTRACK:
|
||||
if (wmEvent < 3)
|
||||
wmEvent = 3;
|
||||
if (wmEvent > MAX_BUFFER_COUNT)
|
||||
wmEvent = MAX_BUFFER_COUNT;
|
||||
SendMessage((HWND)lParam, TBM_SETPOS, TRUE, wmEvent);
|
||||
swprintf_s(temp, L"%d (%d ms latency)", wmEvent, 1000 / (96000 / (wmEvent * BufferSize)));
|
||||
SetWindowText(GetDlgItem(hWnd, IDC_LATENCY_LABEL), temp);
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_HSCROLL:
|
||||
wmId = LOWORD(wParam);
|
||||
wmEvent = HIWORD(wParam);
|
||||
switch(wmId) {
|
||||
//case TB_ENDTRACK:
|
||||
//case TB_THUMBPOSITION:
|
||||
case TB_LINEUP:
|
||||
case TB_LINEDOWN:
|
||||
case TB_PAGEUP:
|
||||
case TB_PAGEDOWN:
|
||||
wmEvent=(int)SendMessage((HWND)lParam,TBM_GETPOS,0,0);
|
||||
case TB_THUMBTRACK:
|
||||
if( wmEvent < 3 ) wmEvent = 3;
|
||||
if( wmEvent > MAX_BUFFER_COUNT ) wmEvent = MAX_BUFFER_COUNT;
|
||||
SendMessage((HWND)lParam,TBM_SETPOS,TRUE,wmEvent);
|
||||
swprintf_s(temp, L"%d (%d ms latency)",wmEvent, 1000 / (96000 / (wmEvent * BufferSize)));
|
||||
SetWindowText(GetDlgItem(hWnd,IDC_LATENCY_LABEL),temp);
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
public:
|
||||
virtual void Configure(uptr parent)
|
||||
{
|
||||
INT_PTR ret;
|
||||
ret=DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_WAVEOUT), (HWND)parent, (DLGPROC)ConfigProc,1);
|
||||
if(ret==-1)
|
||||
{
|
||||
MessageBox((HWND)parent, L"Error Opening the config dialog.", L"OMG ERROR!", MB_OK | MB_SETFOREGROUND);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
s32 Test() const
|
||||
{
|
||||
if (waveOutGetNumDevs() == 0) {
|
||||
SysMessage("No waveOut Devices Present\n"); return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
virtual void Configure(uptr parent)
|
||||
{
|
||||
INT_PTR ret;
|
||||
ret = DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_WAVEOUT), (HWND)parent, (DLGPROC)ConfigProc, 1);
|
||||
if (ret == -1) {
|
||||
MessageBox((HWND)parent, L"Error Opening the config dialog.", L"OMG ERROR!", MB_OK | MB_SETFOREGROUND);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int GetEmptySampleCount()
|
||||
{
|
||||
int result = 0;
|
||||
for(int i=0;i<MAX_BUFFER_COUNT;i++)
|
||||
{
|
||||
result += (whbuffer[i].dwFlags & WHDR_DONE) ? BufferSize : 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
s32 Test() const
|
||||
{
|
||||
if (waveOutGetNumDevs() == 0) {
|
||||
SysMessage("No waveOut Devices Present\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const wchar_t* GetIdent() const
|
||||
{
|
||||
return L"waveout";
|
||||
}
|
||||
int GetEmptySampleCount()
|
||||
{
|
||||
int result = 0;
|
||||
for (int i = 0; i < MAX_BUFFER_COUNT; i++) {
|
||||
result += (whbuffer[i].dwFlags & WHDR_DONE) ? BufferSize : 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const wchar_t* GetLongName() const
|
||||
{
|
||||
return L"waveOut (Laggy)";
|
||||
}
|
||||
const wchar_t *GetIdent() const
|
||||
{
|
||||
return L"waveout";
|
||||
}
|
||||
|
||||
void ReadSettings()
|
||||
{
|
||||
}
|
||||
const wchar_t *GetLongName() const
|
||||
{
|
||||
return L"waveOut (Laggy)";
|
||||
}
|
||||
|
||||
void SetApiSettings(wxString api)
|
||||
{
|
||||
}
|
||||
void ReadSettings()
|
||||
{
|
||||
}
|
||||
|
||||
void WriteSettings() const
|
||||
{
|
||||
}
|
||||
void SetApiSettings(wxString api)
|
||||
{
|
||||
}
|
||||
|
||||
void WriteSettings() const
|
||||
{
|
||||
}
|
||||
|
||||
} static WO;
|
||||
|
||||
|
|
|
@ -18,105 +18,102 @@
|
|||
#include "Global.h"
|
||||
#include "Dialogs.h"
|
||||
|
||||
int SendDialogMsg( HWND hwnd, int dlgId, UINT code, WPARAM wParam, LPARAM lParam)
|
||||
int SendDialogMsg(HWND hwnd, int dlgId, UINT code, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
return SendMessage( GetDlgItem(hwnd,dlgId), code, wParam, lParam );
|
||||
return SendMessage(GetDlgItem(hwnd, dlgId), code, wParam, lParam);
|
||||
}
|
||||
|
||||
HRESULT GUIDFromString(const wchar_t *str, LPGUID guid)
|
||||
{
|
||||
// "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"
|
||||
// "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"
|
||||
|
||||
// VS2015 supports the hh format specifier (finally). VS2013 doesn't though,
|
||||
// so this will do for now.
|
||||
u32 guid_u32;
|
||||
u16 guid_u16[2];
|
||||
u16 guid_u8[8];
|
||||
// VS2015 supports the hh format specifier (finally). VS2013 doesn't though,
|
||||
// so this will do for now.
|
||||
u32 guid_u32;
|
||||
u16 guid_u16[2];
|
||||
u16 guid_u8[8];
|
||||
|
||||
int r = swscanf_s(str,L"{%08x-%04hx-%04hx-%02hx%02hx-%02hx%02hx%02hx%02hx%02hx%02hx}",
|
||||
&guid_u32,
|
||||
&guid_u16[0],
|
||||
&guid_u16[1],
|
||||
&guid_u8[0],
|
||||
&guid_u8[1],
|
||||
&guid_u8[2],
|
||||
&guid_u8[3],
|
||||
&guid_u8[4],
|
||||
&guid_u8[5],
|
||||
&guid_u8[6],
|
||||
&guid_u8[7]
|
||||
);
|
||||
int r = swscanf_s(str, L"{%08x-%04hx-%04hx-%02hx%02hx-%02hx%02hx%02hx%02hx%02hx%02hx}",
|
||||
&guid_u32,
|
||||
&guid_u16[0],
|
||||
&guid_u16[1],
|
||||
&guid_u8[0],
|
||||
&guid_u8[1],
|
||||
&guid_u8[2],
|
||||
&guid_u8[3],
|
||||
&guid_u8[4],
|
||||
&guid_u8[5],
|
||||
&guid_u8[6],
|
||||
&guid_u8[7]);
|
||||
|
||||
if(r!=11) return -1;
|
||||
if (r != 11)
|
||||
return -1;
|
||||
|
||||
guid->Data1 = guid_u32;
|
||||
guid->Data2 = guid_u16[0];
|
||||
guid->Data3 = guid_u16[1];
|
||||
guid->Data4[0] = (u8)guid_u8[0];
|
||||
guid->Data4[1] = (u8)guid_u8[1];
|
||||
guid->Data4[2] = (u8)guid_u8[2];
|
||||
guid->Data4[3] = (u8)guid_u8[3];
|
||||
guid->Data4[4] = (u8)guid_u8[4];
|
||||
guid->Data4[5] = (u8)guid_u8[5];
|
||||
guid->Data4[6] = (u8)guid_u8[6];
|
||||
guid->Data4[7] = (u8)guid_u8[7];
|
||||
return 0;
|
||||
guid->Data1 = guid_u32;
|
||||
guid->Data2 = guid_u16[0];
|
||||
guid->Data3 = guid_u16[1];
|
||||
guid->Data4[0] = (u8)guid_u8[0];
|
||||
guid->Data4[1] = (u8)guid_u8[1];
|
||||
guid->Data4[2] = (u8)guid_u8[2];
|
||||
guid->Data4[3] = (u8)guid_u8[3];
|
||||
guid->Data4[4] = (u8)guid_u8[4];
|
||||
guid->Data4[5] = (u8)guid_u8[5];
|
||||
guid->Data4[6] = (u8)guid_u8[6];
|
||||
guid->Data4[7] = (u8)guid_u8[7];
|
||||
return 0;
|
||||
}
|
||||
|
||||
__forceinline void Verifyc(HRESULT hr, const char* fn)
|
||||
__forceinline void Verifyc(HRESULT hr, const char *fn)
|
||||
{
|
||||
if(FAILED(hr))
|
||||
{
|
||||
assert( 0 );
|
||||
throw std::runtime_error( "DirectSound returned an error from %s" );
|
||||
}
|
||||
if (FAILED(hr)) {
|
||||
assert(0);
|
||||
throw std::runtime_error("DirectSound returned an error from %s");
|
||||
}
|
||||
}
|
||||
|
||||
void AssignSliderValue( HWND idcwnd, HWND hwndDisplay, int value )
|
||||
void AssignSliderValue(HWND idcwnd, HWND hwndDisplay, int value)
|
||||
{
|
||||
value = std::min( std::max( value, 0 ), 512 );
|
||||
SendMessage(idcwnd,TBM_SETPOS,TRUE,value);
|
||||
value = std::min(std::max(value, 0), 512);
|
||||
SendMessage(idcwnd, TBM_SETPOS, TRUE, value);
|
||||
|
||||
wchar_t tbox[32];
|
||||
swprintf_s( tbox, L"%d", value );
|
||||
SetWindowText( hwndDisplay, tbox );
|
||||
wchar_t tbox[32];
|
||||
swprintf_s(tbox, L"%d", value);
|
||||
SetWindowText(hwndDisplay, tbox);
|
||||
}
|
||||
|
||||
void AssignSliderValue( HWND hWnd, int idc, int editbox, int value )
|
||||
void AssignSliderValue(HWND hWnd, int idc, int editbox, int value)
|
||||
{
|
||||
AssignSliderValue( GetDlgItem( hWnd, idc ), GetDlgItem( hWnd, editbox ), value );
|
||||
AssignSliderValue(GetDlgItem(hWnd, idc), GetDlgItem(hWnd, editbox), value);
|
||||
}
|
||||
|
||||
// Generic slider/scroller message handler. This is succient so long as you
|
||||
// don't need some kind of secondary event handling functionality, such as
|
||||
// updating a custom label.
|
||||
BOOL DoHandleScrollMessage( HWND hwndDisplay, WPARAM wParam, LPARAM lParam )
|
||||
BOOL DoHandleScrollMessage(HWND hwndDisplay, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
int wmId = LOWORD(wParam);
|
||||
int wmEvent = HIWORD(wParam);
|
||||
|
||||
switch(wmId)
|
||||
{
|
||||
//case TB_ENDTRACK:
|
||||
//case TB_THUMBPOSITION:
|
||||
case TB_LINEUP:
|
||||
case TB_LINEDOWN:
|
||||
case TB_PAGEUP:
|
||||
case TB_PAGEDOWN:
|
||||
wmEvent = (int)SendMessage((HWND)lParam,TBM_GETPOS,0,0);
|
||||
case TB_THUMBTRACK:
|
||||
AssignSliderValue( (HWND)lParam, hwndDisplay, wmEvent );
|
||||
break;
|
||||
int wmId = LOWORD(wParam);
|
||||
int wmEvent = HIWORD(wParam);
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
switch (wmId) {
|
||||
//case TB_ENDTRACK:
|
||||
//case TB_THUMBPOSITION:
|
||||
case TB_LINEUP:
|
||||
case TB_LINEDOWN:
|
||||
case TB_PAGEUP:
|
||||
case TB_PAGEDOWN:
|
||||
wmEvent = (int)SendMessage((HWND)lParam, TBM_GETPOS, 0, 0);
|
||||
case TB_THUMBTRACK:
|
||||
AssignSliderValue((HWND)lParam, hwndDisplay, wmEvent);
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int GetSliderValue( HWND hWnd, int idc )
|
||||
int GetSliderValue(HWND hWnd, int idc)
|
||||
{
|
||||
int retval = (int)SendMessage( GetDlgItem( hWnd, idc ), TBM_GETPOS, 0, 0 );
|
||||
return GetClamped( retval, 0, 512 );
|
||||
int retval = (int)SendMessage(GetDlgItem(hWnd, idc), TBM_GETPOS, 0, 0);
|
||||
return GetClamped(retval, 0, 512);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,20 +31,28 @@
|
|||
|
||||
extern HINSTANCE hInstance;
|
||||
|
||||
#define SET_CHECK(idc,value) SendMessage(GetDlgItem(hWnd,idc),BM_SETCHECK,((value)==0)?BST_UNCHECKED:BST_CHECKED,0)
|
||||
#define HANDLE_CHECK(idc,hvar) case idc: (hvar) = !(hvar); SendMessage(GetDlgItem(hWnd,idc),BM_SETCHECK,(hvar)?BST_CHECKED:BST_UNCHECKED,0); break
|
||||
#define HANDLE_CHECKNB(idc,hvar)case idc: (hvar) = !(hvar); SendMessage(GetDlgItem(hWnd,idc),BM_SETCHECK,(hvar)?BST_CHECKED:BST_UNCHECKED,0)
|
||||
#define ENABLE_CONTROL(idc,value) EnableWindow(GetDlgItem(hWnd,idc),value)
|
||||
#define SET_CHECK(idc, value) SendMessage(GetDlgItem(hWnd, idc), BM_SETCHECK, ((value) == 0) ? BST_UNCHECKED : BST_CHECKED, 0)
|
||||
#define HANDLE_CHECK(idc, hvar) \
|
||||
case idc: \
|
||||
(hvar) = !(hvar); \
|
||||
SendMessage(GetDlgItem(hWnd, idc), BM_SETCHECK, (hvar) ? BST_CHECKED : BST_UNCHECKED, 0); \
|
||||
break
|
||||
#define HANDLE_CHECKNB(idc, hvar) \
|
||||
case idc: \
|
||||
(hvar) = !(hvar); \
|
||||
SendMessage(GetDlgItem(hWnd, idc), BM_SETCHECK, (hvar) ? BST_CHECKED : BST_UNCHECKED, 0)
|
||||
#define ENABLE_CONTROL(idc, value) EnableWindow(GetDlgItem(hWnd, idc), value)
|
||||
|
||||
#define INIT_SLIDER(idc,minrange,maxrange,tickfreq,pagesize,linesize) \
|
||||
SendMessage(GetDlgItem(hWnd,idc),TBM_SETRANGEMIN,FALSE,minrange); \
|
||||
SendMessage(GetDlgItem(hWnd,idc),TBM_SETRANGEMAX,FALSE,maxrange); \
|
||||
SendMessage(GetDlgItem(hWnd,idc),TBM_SETTICFREQ,tickfreq,0); \
|
||||
SendMessage(GetDlgItem(hWnd,idc),TBM_SETPAGESIZE,0,pagesize); \
|
||||
SendMessage(GetDlgItem(hWnd,idc),TBM_SETLINESIZE,0,linesize)
|
||||
#define INIT_SLIDER(idc, minrange, maxrange, tickfreq, pagesize, linesize) \
|
||||
SendMessage(GetDlgItem(hWnd, idc), TBM_SETRANGEMIN, FALSE, minrange); \
|
||||
SendMessage(GetDlgItem(hWnd, idc), TBM_SETRANGEMAX, FALSE, maxrange); \
|
||||
SendMessage(GetDlgItem(hWnd, idc), TBM_SETTICFREQ, tickfreq, 0); \
|
||||
SendMessage(GetDlgItem(hWnd, idc), TBM_SETPAGESIZE, 0, pagesize); \
|
||||
SendMessage(GetDlgItem(hWnd, idc), TBM_SETLINESIZE, 0, linesize)
|
||||
|
||||
#define HANDLE_SCROLL_MESSAGE(idc,idcDisplay) \
|
||||
if((HWND)lParam == GetDlgItem(hWnd,idc)) return DoHandleScrollMessage( GetDlgItem(hWnd,idcDisplay), wParam, lParam )
|
||||
#define HANDLE_SCROLL_MESSAGE(idc, idcDisplay) \
|
||||
if ((HWND)lParam == GetDlgItem(hWnd, idc)) \
|
||||
return DoHandleScrollMessage(GetDlgItem(hWnd, idcDisplay), wParam, lParam)
|
||||
|
||||
|
||||
// *** BEGIN DRIVER-SPECIFIC CONFIGURATION ***
|
||||
|
@ -52,26 +60,26 @@ extern HINSTANCE hInstance;
|
|||
|
||||
struct CONFIG_XAUDIO2
|
||||
{
|
||||
wxString Device;
|
||||
s8 NumBuffers;
|
||||
wxString Device;
|
||||
s8 NumBuffers;
|
||||
|
||||
CONFIG_XAUDIO2() :
|
||||
Device(),
|
||||
NumBuffers( 2 )
|
||||
{
|
||||
}
|
||||
CONFIG_XAUDIO2()
|
||||
: Device()
|
||||
, NumBuffers(2)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct CONFIG_WAVEOUT
|
||||
{
|
||||
wxString Device;
|
||||
s8 NumBuffers;
|
||||
wxString Device;
|
||||
s8 NumBuffers;
|
||||
|
||||
CONFIG_WAVEOUT() :
|
||||
Device(),
|
||||
NumBuffers( 4 )
|
||||
{
|
||||
}
|
||||
CONFIG_WAVEOUT()
|
||||
: Device()
|
||||
, NumBuffers(4)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
extern CONFIG_WAVEOUT Config_WaveOut;
|
||||
|
|
|
@ -26,14 +26,14 @@
|
|||
extern "C" {
|
||||
#include "dsp.h"
|
||||
|
||||
typedef winampDSPHeader* (*pWinampDSPGetHeader2)();
|
||||
typedef winampDSPHeader *(*pWinampDSPGetHeader2)();
|
||||
}
|
||||
|
||||
HMODULE hLib = NULL;
|
||||
pWinampDSPGetHeader2 pGetHeader = NULL;
|
||||
winampDSPHeader* pHeader = NULL;
|
||||
winampDSPHeader *pHeader = NULL;
|
||||
|
||||
winampDSPModule* pModule = NULL;
|
||||
winampDSPModule *pModule = NULL;
|
||||
|
||||
HWND hTemp;
|
||||
|
||||
|
@ -50,92 +50,91 @@ DWORD WINAPI DspUpdateThread(PVOID param);
|
|||
s32 DspLoadLibrary(wchar_t *fileName, int modNum)
|
||||
#ifdef USE_A_THREAD
|
||||
{
|
||||
if(!dspPluginEnabled) return -1;
|
||||
if (!dspPluginEnabled)
|
||||
return -1;
|
||||
|
||||
running=true;
|
||||
hUpdateThread = CreateThread(NULL,0,DspUpdateThread,NULL,0,&UpdateThreadId);
|
||||
return (hUpdateThread==INVALID_HANDLE_VALUE);
|
||||
running = true;
|
||||
hUpdateThread = CreateThread(NULL, 0, DspUpdateThread, NULL, 0, &UpdateThreadId);
|
||||
return (hUpdateThread == INVALID_HANDLE_VALUE);
|
||||
}
|
||||
|
||||
s32 DspLoadLibrary2( wchar_t *fileName, int modNum )
|
||||
s32 DspLoadLibrary2(wchar_t *fileName, int modNum)
|
||||
#endif
|
||||
{
|
||||
if( !dspPluginEnabled ) return -1;
|
||||
if (!dspPluginEnabled)
|
||||
return -1;
|
||||
|
||||
hLib = LoadLibraryW( fileName );
|
||||
if(!hLib)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
hLib = LoadLibraryW(fileName);
|
||||
if (!hLib) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
pGetHeader = (pWinampDSPGetHeader2)GetProcAddress(hLib,"winampDSPGetHeader2");
|
||||
pGetHeader = (pWinampDSPGetHeader2)GetProcAddress(hLib, "winampDSPGetHeader2");
|
||||
|
||||
if(!pGetHeader)
|
||||
{
|
||||
FreeLibrary(hLib);
|
||||
hLib=NULL;
|
||||
return 1;
|
||||
}
|
||||
if (!pGetHeader) {
|
||||
FreeLibrary(hLib);
|
||||
hLib = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
pHeader = pGetHeader();
|
||||
pHeader = pGetHeader();
|
||||
|
||||
pModule = pHeader->getModule(modNum);
|
||||
pModule = pHeader->getModule(modNum);
|
||||
|
||||
if(!pModule)
|
||||
{
|
||||
pGetHeader=NULL;
|
||||
pHeader=NULL;
|
||||
FreeLibrary(hLib);
|
||||
hLib=NULL;
|
||||
return -1;
|
||||
}
|
||||
if (!pModule) {
|
||||
pGetHeader = NULL;
|
||||
pHeader = NULL;
|
||||
FreeLibrary(hLib);
|
||||
hLib = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
pModule->hDllInstance = hLib;
|
||||
pModule->hwndParent=0;
|
||||
pModule->Init(pModule);
|
||||
pModule->hDllInstance = hLib;
|
||||
pModule->hwndParent = 0;
|
||||
pModule->Init(pModule);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DspCloseLibrary()
|
||||
#ifdef USE_A_THREAD
|
||||
{
|
||||
if(!dspPluginEnabled) return ;
|
||||
if (!dspPluginEnabled)
|
||||
return;
|
||||
|
||||
PostThreadMessage(UpdateThreadId,WM_QUIT,0,0);
|
||||
running=false;
|
||||
if(WaitForSingleObject(hUpdateThread,1000)==WAIT_TIMEOUT)
|
||||
{
|
||||
ConLog("SPU2-X: WARNING: DSP Thread did not close itself in time. Assuming hung. Terminating.\n");
|
||||
TerminateThread(hUpdateThread,1);
|
||||
}
|
||||
PostThreadMessage(UpdateThreadId, WM_QUIT, 0, 0);
|
||||
running = false;
|
||||
if (WaitForSingleObject(hUpdateThread, 1000) == WAIT_TIMEOUT) {
|
||||
ConLog("SPU2-X: WARNING: DSP Thread did not close itself in time. Assuming hung. Terminating.\n");
|
||||
TerminateThread(hUpdateThread, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void DspCloseLibrary2()
|
||||
#endif
|
||||
{
|
||||
if(!dspPluginEnabled) return ;
|
||||
if (!dspPluginEnabled)
|
||||
return;
|
||||
|
||||
if(hLib)
|
||||
{
|
||||
pModule->Quit(pModule);
|
||||
FreeLibrary(hLib);
|
||||
}
|
||||
pModule=NULL;
|
||||
pHeader=NULL;
|
||||
pGetHeader=NULL;
|
||||
hLib=NULL;
|
||||
if (hLib) {
|
||||
pModule->Quit(pModule);
|
||||
FreeLibrary(hLib);
|
||||
}
|
||||
pModule = NULL;
|
||||
pHeader = NULL;
|
||||
pGetHeader = NULL;
|
||||
hLib = NULL;
|
||||
}
|
||||
|
||||
int DspProcess(s16 *buffer, int samples)
|
||||
{
|
||||
if(!dspPluginEnabled) return samples;
|
||||
if (!dspPluginEnabled)
|
||||
return samples;
|
||||
|
||||
if(hLib)
|
||||
{
|
||||
return pModule->ModifySamples(pModule,buffer,samples,16,2,SampleRate);
|
||||
}
|
||||
return samples;
|
||||
if (hLib) {
|
||||
return pModule->ModifySamples(pModule, buffer, samples, 16, 2, SampleRate);
|
||||
}
|
||||
return samples;
|
||||
}
|
||||
|
||||
void DspUpdate()
|
||||
|
@ -145,37 +144,36 @@ void DspUpdate()
|
|||
|
||||
DWORD WINAPI DspUpdateThread(PVOID param)
|
||||
{
|
||||
if( !dspPluginEnabled ) return -1;
|
||||
if (!dspPluginEnabled)
|
||||
return -1;
|
||||
|
||||
if( DspLoadLibrary2( dspPlugin, dspPluginModule ) )
|
||||
return -1;
|
||||
if (DspLoadLibrary2(dspPlugin, dspPluginModule))
|
||||
return -1;
|
||||
|
||||
MSG msg;
|
||||
while(running)
|
||||
{
|
||||
GetMessage(&msg,0,0,0);
|
||||
if((msg.hwnd==NULL)&&(msg.message==WM_QUIT))
|
||||
{
|
||||
break;
|
||||
}
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
MSG msg;
|
||||
while (running) {
|
||||
GetMessage(&msg, 0, 0, 0);
|
||||
if ((msg.hwnd == NULL) && (msg.message == WM_QUIT)) {
|
||||
break;
|
||||
}
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
DspCloseLibrary2();
|
||||
return 0;
|
||||
DspCloseLibrary2();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
{
|
||||
if(!dspPluginEnabled) return;
|
||||
if (!dspPluginEnabled)
|
||||
return;
|
||||
|
||||
MSG msg;
|
||||
while(PeekMessage(&msg,0,0,0,PM_REMOVE))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -27,32 +27,34 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
typedef struct winampDSPModule {
|
||||
char *description; // description
|
||||
HWND hwndParent; // parent window (filled in by calling app)
|
||||
HINSTANCE hDllInstance; // instance handle to this DLL (filled in by calling app)
|
||||
typedef struct winampDSPModule
|
||||
{
|
||||
char *description; // description
|
||||
HWND hwndParent; // parent window (filled in by calling app)
|
||||
HINSTANCE hDllInstance; // instance handle to this DLL (filled in by calling app)
|
||||
|
||||
void (*Config)(struct winampDSPModule *this_mod); // configuration dialog (if needed)
|
||||
int (*Init)(struct winampDSPModule *this_mod); // 0 on success, creates window, etc (if needed)
|
||||
void (*Config)(struct winampDSPModule *this_mod); // configuration dialog (if needed)
|
||||
int (*Init)(struct winampDSPModule *this_mod); // 0 on success, creates window, etc (if needed)
|
||||
|
||||
// modify waveform samples: returns number of samples to actually write
|
||||
// (typically numsamples, but no more than twice numsamples, and no less than half numsamples)
|
||||
// numsamples should always be at least 128. should, but I'm not sure
|
||||
int (*ModifySamples)(struct winampDSPModule *this_mod, short int *samples, int numsamples, int bps, int nch, int srate);
|
||||
// modify waveform samples: returns number of samples to actually write
|
||||
// (typically numsamples, but no more than twice numsamples, and no less than half numsamples)
|
||||
// numsamples should always be at least 128. should, but I'm not sure
|
||||
int (*ModifySamples)(struct winampDSPModule *this_mod, short int *samples, int numsamples, int bps, int nch, int srate);
|
||||
|
||||
void (*Quit)(struct winampDSPModule *this_mod); // called when unloading
|
||||
void (*Quit)(struct winampDSPModule *this_mod); // called when unloading
|
||||
|
||||
void *userData; // user data, optional
|
||||
void *userData; // user data, optional
|
||||
} winampDSPModule;
|
||||
|
||||
typedef struct {
|
||||
int version; // DSP_HDRVER
|
||||
char *description; // description of library
|
||||
winampDSPModule* (*getModule)(int); // module retrieval function
|
||||
typedef struct
|
||||
{
|
||||
int version; // DSP_HDRVER
|
||||
char *description; // description of library
|
||||
winampDSPModule *(*getModule)(int); // module retrieval function
|
||||
} winampDSPHeader;
|
||||
|
||||
// exported symbols
|
||||
typedef winampDSPHeader* (*winampDSPGetHeaderType)();
|
||||
typedef winampDSPHeader *(*winampDSPGetHeaderType)();
|
||||
|
||||
// header version: 0x20 == 0.20 == winamp 2.0
|
||||
#define DSP_HDRVER 0x20
|
||||
|
|
|
@ -23,176 +23,176 @@
|
|||
// SPU2 Memory Indexers
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
#define spu2Rs16(mmem) (*(s16 *)((s8 *)spu2regs + ((mmem) & 0x1fff)))
|
||||
#define spu2Ru16(mmem) (*(u16 *)((s8 *)spu2regs + ((mmem) & 0x1fff)))
|
||||
#define spu2Rs16(mmem) (*(s16 *)((s8 *)spu2regs + ((mmem)&0x1fff)))
|
||||
#define spu2Ru16(mmem) (*(u16 *)((s8 *)spu2regs + ((mmem)&0x1fff)))
|
||||
|
||||
extern s16* GetMemPtr(u32 addr);
|
||||
extern s16 spu2M_Read( u32 addr );
|
||||
extern void spu2M_Write( u32 addr, s16 value );
|
||||
extern void spu2M_Write( u32 addr, u16 value );
|
||||
extern s16 *GetMemPtr(u32 addr);
|
||||
extern s16 spu2M_Read(u32 addr);
|
||||
extern void spu2M_Write(u32 addr, s16 value);
|
||||
extern void spu2M_Write(u32 addr, u16 value);
|
||||
|
||||
|
||||
struct V_VolumeLR
|
||||
{
|
||||
static V_VolumeLR Max;
|
||||
static V_VolumeLR Max;
|
||||
|
||||
s32 Left;
|
||||
s32 Right;
|
||||
s32 Left;
|
||||
s32 Right;
|
||||
|
||||
V_VolumeLR() {}
|
||||
V_VolumeLR( s32 both ) :
|
||||
Left( both ),
|
||||
Right( both )
|
||||
{
|
||||
}
|
||||
V_VolumeLR() {}
|
||||
V_VolumeLR(s32 both)
|
||||
: Left(both)
|
||||
, Right(both)
|
||||
{
|
||||
}
|
||||
|
||||
void DebugDump( FILE* dump, const char* title );
|
||||
void DebugDump(FILE *dump, const char *title);
|
||||
};
|
||||
|
||||
struct V_VolumeSlide
|
||||
{
|
||||
// Holds the "original" value of the volume for this voice, prior to slides.
|
||||
// (ie, the volume as written to the register)
|
||||
// Holds the "original" value of the volume for this voice, prior to slides.
|
||||
// (ie, the volume as written to the register)
|
||||
|
||||
s16 Reg_VOL;
|
||||
s32 Value;
|
||||
s8 Increment;
|
||||
s8 Mode;
|
||||
s16 Reg_VOL;
|
||||
s32 Value;
|
||||
s8 Increment;
|
||||
s8 Mode;
|
||||
|
||||
public:
|
||||
V_VolumeSlide() {}
|
||||
V_VolumeSlide( s16 regval, s32 fullvol ) :
|
||||
Reg_VOL( regval ),
|
||||
Value( fullvol ),
|
||||
Increment( 0 ),
|
||||
Mode( 0 )
|
||||
{
|
||||
}
|
||||
V_VolumeSlide() {}
|
||||
V_VolumeSlide(s16 regval, s32 fullvol)
|
||||
: Reg_VOL(regval)
|
||||
, Value(fullvol)
|
||||
, Increment(0)
|
||||
, Mode(0)
|
||||
{
|
||||
}
|
||||
|
||||
void Update();
|
||||
void RegSet( u16 src ); // used to set the volume from a register source (16 bit signed)
|
||||
void DebugDump( FILE* dump, const char* title, const char* nameLR );
|
||||
void Update();
|
||||
void RegSet(u16 src); // used to set the volume from a register source (16 bit signed)
|
||||
void DebugDump(FILE *dump, const char *title, const char *nameLR);
|
||||
};
|
||||
|
||||
struct V_VolumeSlideLR
|
||||
{
|
||||
static V_VolumeSlideLR Max;
|
||||
static V_VolumeSlideLR Max;
|
||||
|
||||
V_VolumeSlide Left;
|
||||
V_VolumeSlide Right;
|
||||
V_VolumeSlide Left;
|
||||
V_VolumeSlide Right;
|
||||
|
||||
public:
|
||||
V_VolumeSlideLR() {}
|
||||
V_VolumeSlideLR() {}
|
||||
|
||||
V_VolumeSlideLR( s16 regval, s32 bothval ) :
|
||||
Left( regval, bothval ),
|
||||
Right( regval, bothval )
|
||||
{
|
||||
}
|
||||
V_VolumeSlideLR(s16 regval, s32 bothval)
|
||||
: Left(regval, bothval)
|
||||
, Right(regval, bothval)
|
||||
{
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
Left.Update();
|
||||
Right.Update();
|
||||
}
|
||||
void Update()
|
||||
{
|
||||
Left.Update();
|
||||
Right.Update();
|
||||
}
|
||||
|
||||
void DebugDump( FILE* dump, const char* title );
|
||||
void DebugDump(FILE *dump, const char *title);
|
||||
};
|
||||
|
||||
struct V_ADSR
|
||||
{
|
||||
union
|
||||
{
|
||||
u32 reg32;
|
||||
union
|
||||
{
|
||||
u32 reg32;
|
||||
|
||||
struct
|
||||
{
|
||||
u16 regADSR1;
|
||||
u16 regADSR2;
|
||||
};
|
||||
struct
|
||||
{
|
||||
u16 regADSR1;
|
||||
u16 regADSR2;
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
u32 SustainLevel:4,
|
||||
DecayRate:4,
|
||||
AttackRate:7,
|
||||
AttackMode:1, // 0 for linear (+lin), 1 for pseudo exponential (+exp)
|
||||
struct
|
||||
{
|
||||
u32 SustainLevel : 4,
|
||||
DecayRate : 4,
|
||||
AttackRate : 7,
|
||||
AttackMode : 1, // 0 for linear (+lin), 1 for pseudo exponential (+exp)
|
||||
|
||||
ReleaseRate:5,
|
||||
ReleaseMode:1, // 0 for linear (-lin), 1 for exponential (-exp)
|
||||
SustainRate:7,
|
||||
SustainMode:3; // 0 = +lin, 1 = -lin, 2 = +exp, 3 = -exp
|
||||
};
|
||||
};
|
||||
ReleaseRate : 5,
|
||||
ReleaseMode : 1, // 0 for linear (-lin), 1 for exponential (-exp)
|
||||
SustainRate : 7,
|
||||
SustainMode : 3; // 0 = +lin, 1 = -lin, 2 = +exp, 3 = -exp
|
||||
};
|
||||
};
|
||||
|
||||
s32 Value; // Ranges from 0 to 0x7fffffff (signed values are clamped to 0) [Reg_ENVX]
|
||||
u8 Phase; // monitors current phase of ADSR envelope
|
||||
bool Releasing; // Ready To Release, triggered by Voice.Stop();
|
||||
s32 Value; // Ranges from 0 to 0x7fffffff (signed values are clamped to 0) [Reg_ENVX]
|
||||
u8 Phase; // monitors current phase of ADSR envelope
|
||||
bool Releasing; // Ready To Release, triggered by Voice.Stop();
|
||||
|
||||
public:
|
||||
bool Calculate();
|
||||
bool Calculate();
|
||||
};
|
||||
|
||||
|
||||
struct V_Voice
|
||||
{
|
||||
u32 PlayCycle; // SPU2 cycle where the Playing started
|
||||
u32 PlayCycle; // SPU2 cycle where the Playing started
|
||||
|
||||
V_VolumeSlideLR Volume;
|
||||
V_VolumeSlideLR Volume;
|
||||
|
||||
// Envelope
|
||||
V_ADSR ADSR;
|
||||
// Pitch (also Reg_PITCH)
|
||||
u16 Pitch;
|
||||
// Loop Start address (also Reg_LSAH/L)
|
||||
u32 LoopStartA;
|
||||
// Sound Start address (also Reg_SSAH/L)
|
||||
u32 StartA;
|
||||
// Next Read Data address (also Reg_NAXH/L)
|
||||
u32 NextA;
|
||||
// Voice Decoding State
|
||||
s32 Prev1;
|
||||
s32 Prev2;
|
||||
// Envelope
|
||||
V_ADSR ADSR;
|
||||
// Pitch (also Reg_PITCH)
|
||||
u16 Pitch;
|
||||
// Loop Start address (also Reg_LSAH/L)
|
||||
u32 LoopStartA;
|
||||
// Sound Start address (also Reg_SSAH/L)
|
||||
u32 StartA;
|
||||
// Next Read Data address (also Reg_NAXH/L)
|
||||
u32 NextA;
|
||||
// Voice Decoding State
|
||||
s32 Prev1;
|
||||
s32 Prev2;
|
||||
|
||||
// Pitch Modulated by previous voice
|
||||
bool Modulated;
|
||||
// Source (Wave/Noise)
|
||||
bool Noise;
|
||||
// Pitch Modulated by previous voice
|
||||
bool Modulated;
|
||||
// Source (Wave/Noise)
|
||||
bool Noise;
|
||||
|
||||
s8 LoopMode;
|
||||
s8 LoopFlags;
|
||||
s8 LoopMode;
|
||||
s8 LoopFlags;
|
||||
|
||||
// Sample pointer (19:12 bit fixed point)
|
||||
s32 SP;
|
||||
// Sample pointer (19:12 bit fixed point)
|
||||
s32 SP;
|
||||
|
||||
// Sample pointer for Cubic Interpolation
|
||||
// Cubic interpolation mixes a sample behind Linear, so that it
|
||||
// can have sample data to either side of the end points from which
|
||||
// to extrapolate. This SP represents that late sample position.
|
||||
s32 SPc;
|
||||
// Sample pointer for Cubic Interpolation
|
||||
// Cubic interpolation mixes a sample behind Linear, so that it
|
||||
// can have sample data to either side of the end points from which
|
||||
// to extrapolate. This SP represents that late sample position.
|
||||
s32 SPc;
|
||||
|
||||
// Previous sample values - used for interpolation
|
||||
// Inverted order of these members to match the access order in the
|
||||
// code (might improve cache hits).
|
||||
s32 PV4;
|
||||
s32 PV3;
|
||||
s32 PV2;
|
||||
s32 PV1;
|
||||
// Previous sample values - used for interpolation
|
||||
// Inverted order of these members to match the access order in the
|
||||
// code (might improve cache hits).
|
||||
s32 PV4;
|
||||
s32 PV3;
|
||||
s32 PV2;
|
||||
s32 PV1;
|
||||
|
||||
// Last outputted audio value, used for voice modulation.
|
||||
s32 OutX;
|
||||
s32 NextCrest; // temp value for Crest calculation
|
||||
// Last outputted audio value, used for voice modulation.
|
||||
s32 OutX;
|
||||
s32 NextCrest; // temp value for Crest calculation
|
||||
|
||||
// SBuffer now points directly to an ADPCM cache entry.
|
||||
s16 *SBuffer;
|
||||
// SBuffer now points directly to an ADPCM cache entry.
|
||||
s16 *SBuffer;
|
||||
|
||||
// sample position within the current decoded packet.
|
||||
s32 SCurrent;
|
||||
// sample position within the current decoded packet.
|
||||
s32 SCurrent;
|
||||
|
||||
// it takes a few ticks for voices to start on the real SPU2?
|
||||
void QueueStart();
|
||||
bool Start();
|
||||
void Stop();
|
||||
// it takes a few ticks for voices to start on the real SPU2?
|
||||
void QueueStart();
|
||||
bool Start();
|
||||
void Stop();
|
||||
};
|
||||
|
||||
// ** Begin Debug-only variables section **
|
||||
|
@ -200,25 +200,25 @@ struct V_Voice
|
|||
// the Public Release build.
|
||||
struct V_VoiceDebug
|
||||
{
|
||||
s8 FirstBlock;
|
||||
s32 SampleData;
|
||||
s32 PeakX;
|
||||
s32 displayPeak;
|
||||
s32 lastSetStartA;
|
||||
s8 FirstBlock;
|
||||
s32 SampleData;
|
||||
s32 PeakX;
|
||||
s32 displayPeak;
|
||||
s32 lastSetStartA;
|
||||
};
|
||||
|
||||
struct V_CoreDebug
|
||||
{
|
||||
V_VoiceDebug Voices[24];
|
||||
// Last Transfer Size
|
||||
u32 lastsize;
|
||||
V_VoiceDebug Voices[24];
|
||||
// Last Transfer Size
|
||||
u32 lastsize;
|
||||
|
||||
// draw adma waveform in the visual debugger
|
||||
s32 admaWaveformL[0x100];
|
||||
s32 admaWaveformR[0x100];
|
||||
// draw adma waveform in the visual debugger
|
||||
s32 admaWaveformL[0x100];
|
||||
s32 admaWaveformR[0x100];
|
||||
|
||||
// Enabled when a dma write starts, disabled when the visual debugger showed it once
|
||||
s32 dmaFlag;
|
||||
// Enabled when a dma write starts, disabled when the visual debugger showed it once
|
||||
s32 dmaFlag;
|
||||
};
|
||||
|
||||
// Debug tracking information - 24 voices and 2 cores.
|
||||
|
@ -226,338 +226,343 @@ extern V_CoreDebug DebugCores[2];
|
|||
|
||||
struct V_Reverb
|
||||
{
|
||||
s16 IN_COEF_L;
|
||||
s16 IN_COEF_R;
|
||||
s16 IN_COEF_L;
|
||||
s16 IN_COEF_R;
|
||||
|
||||
u32 FB_SRC_A;
|
||||
u32 FB_SRC_B;
|
||||
u32 FB_SRC_A;
|
||||
u32 FB_SRC_B;
|
||||
|
||||
s16 FB_ALPHA;
|
||||
s16 FB_X;
|
||||
s16 FB_ALPHA;
|
||||
s16 FB_X;
|
||||
|
||||
u32 IIR_SRC_A0;
|
||||
u32 IIR_SRC_A1;
|
||||
u32 IIR_SRC_B1;
|
||||
u32 IIR_SRC_B0;
|
||||
u32 IIR_DEST_A0;
|
||||
u32 IIR_DEST_A1;
|
||||
u32 IIR_DEST_B0;
|
||||
u32 IIR_DEST_B1;
|
||||
u32 IIR_SRC_A0;
|
||||
u32 IIR_SRC_A1;
|
||||
u32 IIR_SRC_B1;
|
||||
u32 IIR_SRC_B0;
|
||||
u32 IIR_DEST_A0;
|
||||
u32 IIR_DEST_A1;
|
||||
u32 IIR_DEST_B0;
|
||||
u32 IIR_DEST_B1;
|
||||
|
||||
s16 IIR_ALPHA;
|
||||
s16 IIR_COEF;
|
||||
s16 IIR_ALPHA;
|
||||
s16 IIR_COEF;
|
||||
|
||||
u32 ACC_SRC_A0;
|
||||
u32 ACC_SRC_A1;
|
||||
u32 ACC_SRC_B0;
|
||||
u32 ACC_SRC_B1;
|
||||
u32 ACC_SRC_C0;
|
||||
u32 ACC_SRC_C1;
|
||||
u32 ACC_SRC_D0;
|
||||
u32 ACC_SRC_D1;
|
||||
u32 ACC_SRC_A0;
|
||||
u32 ACC_SRC_A1;
|
||||
u32 ACC_SRC_B0;
|
||||
u32 ACC_SRC_B1;
|
||||
u32 ACC_SRC_C0;
|
||||
u32 ACC_SRC_C1;
|
||||
u32 ACC_SRC_D0;
|
||||
u32 ACC_SRC_D1;
|
||||
|
||||
s16 ACC_COEF_A;
|
||||
s16 ACC_COEF_B;
|
||||
s16 ACC_COEF_C;
|
||||
s16 ACC_COEF_D;
|
||||
s16 ACC_COEF_A;
|
||||
s16 ACC_COEF_B;
|
||||
s16 ACC_COEF_C;
|
||||
s16 ACC_COEF_D;
|
||||
|
||||
u32 MIX_DEST_A0;
|
||||
u32 MIX_DEST_A1;
|
||||
u32 MIX_DEST_B0;
|
||||
u32 MIX_DEST_B1;
|
||||
u32 MIX_DEST_A0;
|
||||
u32 MIX_DEST_A1;
|
||||
u32 MIX_DEST_B0;
|
||||
u32 MIX_DEST_B1;
|
||||
};
|
||||
|
||||
struct V_ReverbBuffers
|
||||
{
|
||||
s32 FB_SRC_A0;
|
||||
s32 FB_SRC_B0;
|
||||
s32 FB_SRC_A1;
|
||||
s32 FB_SRC_B1;
|
||||
s32 FB_SRC_A0;
|
||||
s32 FB_SRC_B0;
|
||||
s32 FB_SRC_A1;
|
||||
s32 FB_SRC_B1;
|
||||
|
||||
s32 IIR_SRC_A0;
|
||||
s32 IIR_SRC_A1;
|
||||
s32 IIR_SRC_B0;
|
||||
s32 IIR_SRC_B1;
|
||||
s32 IIR_DEST_A0;
|
||||
s32 IIR_DEST_A1;
|
||||
s32 IIR_DEST_B0;
|
||||
s32 IIR_DEST_B1;
|
||||
s32 IIR_SRC_A0;
|
||||
s32 IIR_SRC_A1;
|
||||
s32 IIR_SRC_B0;
|
||||
s32 IIR_SRC_B1;
|
||||
s32 IIR_DEST_A0;
|
||||
s32 IIR_DEST_A1;
|
||||
s32 IIR_DEST_B0;
|
||||
s32 IIR_DEST_B1;
|
||||
|
||||
s32 ACC_SRC_A0;
|
||||
s32 ACC_SRC_A1;
|
||||
s32 ACC_SRC_B0;
|
||||
s32 ACC_SRC_B1;
|
||||
s32 ACC_SRC_C0;
|
||||
s32 ACC_SRC_C1;
|
||||
s32 ACC_SRC_D0;
|
||||
s32 ACC_SRC_D1;
|
||||
s32 ACC_SRC_A0;
|
||||
s32 ACC_SRC_A1;
|
||||
s32 ACC_SRC_B0;
|
||||
s32 ACC_SRC_B1;
|
||||
s32 ACC_SRC_C0;
|
||||
s32 ACC_SRC_C1;
|
||||
s32 ACC_SRC_D0;
|
||||
s32 ACC_SRC_D1;
|
||||
|
||||
s32 MIX_DEST_A0;
|
||||
s32 MIX_DEST_A1;
|
||||
s32 MIX_DEST_B0;
|
||||
s32 MIX_DEST_B1;
|
||||
s32 MIX_DEST_A0;
|
||||
s32 MIX_DEST_A1;
|
||||
s32 MIX_DEST_B0;
|
||||
s32 MIX_DEST_B1;
|
||||
|
||||
bool NeedsUpdated;
|
||||
bool NeedsUpdated;
|
||||
};
|
||||
|
||||
struct V_SPDIF
|
||||
{
|
||||
u16 Out;
|
||||
u16 Info;
|
||||
u16 Unknown1;
|
||||
u16 Mode;
|
||||
u16 Media;
|
||||
u16 Unknown2;
|
||||
u16 Protection;
|
||||
u16 Out;
|
||||
u16 Info;
|
||||
u16 Unknown1;
|
||||
u16 Mode;
|
||||
u16 Media;
|
||||
u16 Unknown2;
|
||||
u16 Protection;
|
||||
};
|
||||
|
||||
struct V_CoreRegs
|
||||
{
|
||||
u32 PMON;
|
||||
u32 NON;
|
||||
u32 VMIXL;
|
||||
u32 VMIXR;
|
||||
u32 VMIXEL;
|
||||
u32 VMIXER;
|
||||
u32 ENDX;
|
||||
u32 PMON;
|
||||
u32 NON;
|
||||
u32 VMIXL;
|
||||
u32 VMIXR;
|
||||
u32 VMIXEL;
|
||||
u32 VMIXER;
|
||||
u32 ENDX;
|
||||
|
||||
u16 MMIX;
|
||||
u16 STATX;
|
||||
u16 ATTR;
|
||||
u16 _1AC;
|
||||
u16 MMIX;
|
||||
u16 STATX;
|
||||
u16 ATTR;
|
||||
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
|
||||
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
|
||||
};
|
||||
|
||||
struct V_CoreGates
|
||||
{
|
||||
union
|
||||
{
|
||||
u128 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)
|
||||
};
|
||||
};
|
||||
union
|
||||
{
|
||||
u128 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 VoiceMixSet
|
||||
{
|
||||
static const VoiceMixSet Empty;
|
||||
StereoOut32 Dry, Wet;
|
||||
static const VoiceMixSet Empty;
|
||||
StereoOut32 Dry, Wet;
|
||||
|
||||
VoiceMixSet() {}
|
||||
VoiceMixSet( const StereoOut32& dry, const StereoOut32& wet ) :
|
||||
Dry( dry ),
|
||||
Wet( wet )
|
||||
{
|
||||
}
|
||||
VoiceMixSet() {}
|
||||
VoiceMixSet(const StereoOut32 &dry, const StereoOut32 &wet)
|
||||
: Dry(dry)
|
||||
, Wet(wet)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct V_Core
|
||||
{
|
||||
static const uint NumVoices = 24;
|
||||
static const uint NumVoices = 24;
|
||||
|
||||
int Index; // Core index identifier.
|
||||
int Index; // Core index identifier.
|
||||
|
||||
// Voice Gates -- These are SSE-related values, and must always be
|
||||
// first to ensure 16 byte alignment
|
||||
// Voice Gates -- These are SSE-related values, and must always be
|
||||
// first to ensure 16 byte alignment
|
||||
|
||||
V_VoiceGates VoiceGates[NumVoices];
|
||||
V_CoreGates DryGate;
|
||||
V_CoreGates WetGate;
|
||||
V_VoiceGates VoiceGates[NumVoices];
|
||||
V_CoreGates DryGate;
|
||||
V_CoreGates WetGate;
|
||||
|
||||
V_VolumeSlideLR MasterVol; // Master Volume
|
||||
V_VolumeLR ExtVol; // Volume for External Data Input
|
||||
V_VolumeLR InpVol; // Volume for Sound Data Input
|
||||
V_VolumeLR FxVol; // Volume for Output from Effects
|
||||
V_VolumeSlideLR MasterVol; // Master Volume
|
||||
V_VolumeLR ExtVol; // Volume for External Data Input
|
||||
V_VolumeLR InpVol; // Volume for Sound Data Input
|
||||
V_VolumeLR FxVol; // Volume for Output from Effects
|
||||
|
||||
V_Voice Voices[NumVoices];
|
||||
V_Voice Voices[NumVoices];
|
||||
|
||||
u32 IRQA; // Interrupt Address
|
||||
u32 TSA; // DMA Transfer Start Address
|
||||
u32 IRQA; // Interrupt Address
|
||||
u32 TSA; // DMA Transfer Start Address
|
||||
|
||||
bool IRQEnable; // Interrupt Enable
|
||||
bool FxEnable; // Effect Enable
|
||||
bool Mute; // Mute
|
||||
bool AdmaInProgress;
|
||||
bool IRQEnable; // Interrupt Enable
|
||||
bool FxEnable; // Effect Enable
|
||||
bool Mute; // Mute
|
||||
bool AdmaInProgress;
|
||||
|
||||
s8 DMABits; // DMA related?
|
||||
s8 NoiseClk; // Noise Clock
|
||||
u16 AutoDMACtrl; // AutoDMA Status
|
||||
s32 DMAICounter; // DMA Interrupt Counter
|
||||
u32 InputDataLeft; // Input Buffer
|
||||
u32 InputPosRead;
|
||||
u32 InputPosWrite;
|
||||
u32 InputDataProgress;
|
||||
s8 DMABits; // DMA related?
|
||||
s8 NoiseClk; // Noise Clock
|
||||
u16 AutoDMACtrl; // AutoDMA Status
|
||||
s32 DMAICounter; // DMA Interrupt Counter
|
||||
u32 InputDataLeft; // Input Buffer
|
||||
u32 InputPosRead;
|
||||
u32 InputPosWrite;
|
||||
u32 InputDataProgress;
|
||||
|
||||
V_Reverb Revb; // Reverb Registers
|
||||
V_ReverbBuffers RevBuffers; // buffer pointers for reverb, pre-calculated and pre-clipped.
|
||||
u32 EffectsStartA;
|
||||
u32 EffectsEndA;
|
||||
u32 ExtEffectsStartA;
|
||||
u32 ExtEffectsEndA;
|
||||
u32 ReverbX;
|
||||
V_Reverb Revb; // Reverb Registers
|
||||
V_ReverbBuffers RevBuffers; // buffer pointers for reverb, pre-calculated and pre-clipped.
|
||||
u32 EffectsStartA;
|
||||
u32 EffectsEndA;
|
||||
u32 ExtEffectsStartA;
|
||||
u32 ExtEffectsEndA;
|
||||
u32 ReverbX;
|
||||
|
||||
// Current size of and position of the effects buffer. Pre-caculated when the effects start
|
||||
// or end position registers are written. CAN BE NEGATIVE OR ZERO, in which
|
||||
// case reverb should be disabled.
|
||||
s32 EffectsBufferSize;
|
||||
u32 EffectsBufferStart;
|
||||
// Current size of and position of the effects buffer. Pre-caculated when the effects start
|
||||
// or end position registers are written. CAN BE NEGATIVE OR ZERO, in which
|
||||
// case reverb should be disabled.
|
||||
s32 EffectsBufferSize;
|
||||
u32 EffectsBufferStart;
|
||||
|
||||
V_CoreRegs Regs; // Registers
|
||||
V_CoreRegs Regs; // Registers
|
||||
|
||||
// Last samples to pass through the effects processor.
|
||||
// Used because the effects processor works at 24khz and just pulls
|
||||
// from this for the odd Ts.
|
||||
StereoOut32 LastEffect;
|
||||
// Last samples to pass through the effects processor.
|
||||
// Used because the effects processor works at 24khz and just pulls
|
||||
// from this for the odd Ts.
|
||||
StereoOut32 LastEffect;
|
||||
|
||||
u8 CoreEnabled;
|
||||
u8 CoreEnabled;
|
||||
|
||||
u8 AttrBit0;
|
||||
u8 DmaMode;
|
||||
u8 AttrBit0;
|
||||
u8 DmaMode;
|
||||
|
||||
// new dma only
|
||||
bool DmaStarted;
|
||||
u32 AutoDmaFree;
|
||||
// new dma only
|
||||
bool DmaStarted;
|
||||
u32 AutoDmaFree;
|
||||
|
||||
// old dma only
|
||||
u16* DMAPtr;
|
||||
u32 MADR;
|
||||
u32 TADR;
|
||||
// old dma only
|
||||
u16 *DMAPtr;
|
||||
u32 MADR;
|
||||
u32 TADR;
|
||||
|
||||
u32 KeyOn; // not the KON register (though maybe it is)
|
||||
u32 KeyOn; // not the KON register (though maybe it is)
|
||||
|
||||
// psxmode caches
|
||||
u16 psxSoundDataTransferControl;
|
||||
u16 psxSPUSTAT;
|
||||
// psxmode caches
|
||||
u16 psxSoundDataTransferControl;
|
||||
u16 psxSPUSTAT;
|
||||
|
||||
StereoOut32 downbuf[8];
|
||||
StereoOut32 upbuf[8];
|
||||
int dbpos, ubpos;
|
||||
StereoOut32 downbuf[8];
|
||||
StereoOut32 upbuf[8];
|
||||
int dbpos, ubpos;
|
||||
|
||||
// HACK -- This is a temp buffer which is (or isn't?) used to circumvent some memory
|
||||
// corruption that originates elsewhere in the plugin. >_< The actual ADMA buffer
|
||||
// is an area mapped to SPU2 main memory.
|
||||
//s16 ADMATempBuffer[0x1000];
|
||||
// HACK -- This is a temp buffer which is (or isn't?) used to circumvent some memory
|
||||
// corruption that originates elsewhere in the plugin. >_< The actual ADMA buffer
|
||||
// is an area mapped to SPU2 main memory.
|
||||
//s16 ADMATempBuffer[0x1000];
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// V_Core Methods
|
||||
// ----------------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------
|
||||
// V_Core Methods
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
// uninitialized constructor
|
||||
V_Core() : Index( -1 ), DMAPtr( NULL ) {}
|
||||
V_Core( int idx ); // our badass constructor
|
||||
~V_Core() throw();
|
||||
// uninitialized constructor
|
||||
V_Core()
|
||||
: Index(-1)
|
||||
, DMAPtr(NULL)
|
||||
{
|
||||
}
|
||||
V_Core(int idx); // our badass constructor
|
||||
~V_Core() throw();
|
||||
|
||||
void Init( int index );
|
||||
void UpdateEffectsBufferSize();
|
||||
void AnalyzeReverbPreset();
|
||||
void Init(int index);
|
||||
void UpdateEffectsBufferSize();
|
||||
void AnalyzeReverbPreset();
|
||||
|
||||
s32 EffectsBufferIndexer( s32 offset ) const;
|
||||
void UpdateFeedbackBuffersA();
|
||||
void UpdateFeedbackBuffersB();
|
||||
s32 EffectsBufferIndexer(s32 offset) const;
|
||||
void UpdateFeedbackBuffersA();
|
||||
void UpdateFeedbackBuffersB();
|
||||
|
||||
void WriteRegPS1( u32 mem, u16 value );
|
||||
u16 ReadRegPS1( u32 mem );
|
||||
void WriteRegPS1(u32 mem, u16 value);
|
||||
u16 ReadRegPS1(u32 mem);
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Mixer Section
|
||||
// --------------------------------------------------------------------------------------
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Mixer Section
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
StereoOut32 Mix( const VoiceMixSet& inVoices, const StereoOut32& Input, const StereoOut32& Ext );
|
||||
void Reverb_AdvanceBuffer();
|
||||
StereoOut32 DoReverb( const StereoOut32& Input );
|
||||
s32 RevbGetIndexer( s32 offset );
|
||||
StereoOut32 Mix(const VoiceMixSet &inVoices, const StereoOut32 &Input, const StereoOut32 &Ext);
|
||||
void Reverb_AdvanceBuffer();
|
||||
StereoOut32 DoReverb(const StereoOut32 &Input);
|
||||
s32 RevbGetIndexer(s32 offset);
|
||||
|
||||
StereoOut32 ReadInput();
|
||||
StereoOut32 ReadInput_HiFi();
|
||||
StereoOut32 ReadInput();
|
||||
StereoOut32 ReadInput_HiFi();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// DMA Section
|
||||
// --------------------------------------------------------------------------
|
||||
// --------------------------------------------------------------------------
|
||||
// DMA Section
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
// Returns the index of the DMA channel (4 for Core 0, or 7 for Core 1)
|
||||
int GetDmaIndex() const
|
||||
{
|
||||
return (Index == 0) ? 4 : 7;
|
||||
}
|
||||
// Returns the index of the DMA channel (4 for Core 0, or 7 for Core 1)
|
||||
int GetDmaIndex() const
|
||||
{
|
||||
return (Index == 0) ? 4 : 7;
|
||||
}
|
||||
|
||||
// returns either '4' or '7'
|
||||
char GetDmaIndexChar() const
|
||||
{
|
||||
return 0x30 + GetDmaIndex();
|
||||
}
|
||||
// returns either '4' or '7'
|
||||
char GetDmaIndexChar() const
|
||||
{
|
||||
return 0x30 + GetDmaIndex();
|
||||
}
|
||||
|
||||
__forceinline u16 DmaRead()
|
||||
{
|
||||
const u16 ret = (u16)spu2M_Read(TSA);
|
||||
++TSA; TSA &= 0xfffff;
|
||||
return ret;
|
||||
}
|
||||
__forceinline u16 DmaRead()
|
||||
{
|
||||
const u16 ret = (u16)spu2M_Read(TSA);
|
||||
++TSA;
|
||||
TSA &= 0xfffff;
|
||||
return ret;
|
||||
}
|
||||
|
||||
__forceinline void DmaWrite(u16 value)
|
||||
{
|
||||
spu2M_Write( TSA, value );
|
||||
++TSA; TSA &= 0xfffff;
|
||||
}
|
||||
__forceinline void DmaWrite(u16 value)
|
||||
{
|
||||
spu2M_Write(TSA, value);
|
||||
++TSA;
|
||||
TSA &= 0xfffff;
|
||||
}
|
||||
|
||||
void LogAutoDMA( FILE* fp );
|
||||
void LogAutoDMA(FILE *fp);
|
||||
|
||||
s32 NewDmaRead(u32* data, u32 bytesLeft, u32* bytesProcessed);
|
||||
s32 NewDmaWrite(u32* data, u32 bytesLeft, u32* bytesProcessed);
|
||||
void NewDmaInterrupt();
|
||||
s32 NewDmaRead(u32 *data, u32 bytesLeft, u32 *bytesProcessed);
|
||||
s32 NewDmaWrite(u32 *data, u32 bytesLeft, u32 *bytesProcessed);
|
||||
void NewDmaInterrupt();
|
||||
|
||||
// old dma only
|
||||
void DoDMAwrite(u16* pMem, u32 size);
|
||||
void DoDMAread(u16* pMem, u32 size);
|
||||
// old dma only
|
||||
void DoDMAwrite(u16 *pMem, u32 size);
|
||||
void DoDMAread(u16 *pMem, u32 size);
|
||||
|
||||
void AutoDMAReadBuffer(int mode);
|
||||
void StartADMAWrite(u16 *pMem, u32 sz);
|
||||
void PlainDMAWrite(u16 *pMem, u32 sz);
|
||||
void AutoDMAReadBuffer(int mode);
|
||||
void StartADMAWrite(u16 *pMem, u32 sz);
|
||||
void PlainDMAWrite(u16 *pMem, u32 sz);
|
||||
};
|
||||
|
||||
extern V_Core Cores[2];
|
||||
extern V_SPDIF Spdif;
|
||||
extern V_Core Cores[2];
|
||||
extern V_SPDIF Spdif;
|
||||
|
||||
// Output Buffer Writing Position (the same for all data);
|
||||
extern s16 OutPos;
|
||||
extern s16 OutPos;
|
||||
// Input Buffer Reading Position (the same for all data);
|
||||
extern s16 InputPos;
|
||||
extern s16 InputPos;
|
||||
// SPU Mixing Cycles ("Ticks mixed" counter)
|
||||
extern u32 Cycles;
|
||||
extern u32 Cycles;
|
||||
|
||||
extern s16* spu2regs;
|
||||
extern s16* _spu2mem;
|
||||
extern int PlayMode;
|
||||
extern s16 *spu2regs;
|
||||
extern s16 *_spu2mem;
|
||||
extern int PlayMode;
|
||||
|
||||
extern void SetIrqCall(int core);
|
||||
extern void StartVoices(int core, u32 value);
|
||||
extern void StopVoices(int core, u32 value);
|
||||
extern void InitADSR();
|
||||
extern void CalculateADSR( V_Voice& vc );
|
||||
extern void CalculateADSR(V_Voice &vc);
|
||||
extern void UpdateSpdifMode();
|
||||
|
||||
namespace Savestate
|
||||
{
|
||||
struct DataBlock;
|
||||
struct DataBlock;
|
||||
|
||||
extern s32 __fastcall FreezeIt( DataBlock& spud );
|
||||
extern s32 __fastcall ThawIt( DataBlock& spud );
|
||||
extern s32 __fastcall SizeIt();
|
||||
extern s32 __fastcall FreezeIt(DataBlock &spud);
|
||||
extern s32 __fastcall ThawIt(DataBlock &spud);
|
||||
extern s32 __fastcall SizeIt();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
@ -580,8 +585,8 @@ static const int pcm_DecodedSamplesPerBlock = 28;
|
|||
|
||||
struct PcmCacheEntry
|
||||
{
|
||||
bool Validated;
|
||||
s16 Sampledata[pcm_DecodedSamplesPerBlock];
|
||||
bool Validated;
|
||||
s16 Sampledata[pcm_DecodedSamplesPerBlock];
|
||||
};
|
||||
|
||||
extern PcmCacheEntry* pcm_cache_data;
|
||||
extern PcmCacheEntry *pcm_cache_data;
|
||||
|
|
|
@ -17,78 +17,78 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#define SPU2_CORE0 0x00000000
|
||||
#define SPU2_CORE1 0x00000400
|
||||
#define SPU2_CORE0 0x00000000
|
||||
#define SPU2_CORE1 0x00000400
|
||||
|
||||
#define SPU2_VP(voice) ((voice) * 16)
|
||||
#define SPU2_VA(voice) ((voice) * 12)
|
||||
#define SPU2_VP(voice) ((voice)*16)
|
||||
#define SPU2_VA(voice) ((voice)*12)
|
||||
|
||||
#define REG_VP_VOLL 0x0000 // Voice Volume Left
|
||||
#define REG_VP_VOLR 0x0002 // Voice Volume Right
|
||||
#define REG_VP_PITCH 0x0004 // Pitch
|
||||
#define REG_VP_ADSR1 0x0006 // Envelope 1 (Attack-Decay-Sustain-Release)
|
||||
#define REG_VP_ADSR2 0x0008 // Envelope 2 (Attack-Decay-Sustain-Release)
|
||||
#define REG_VP_ENVX 0x000A // Current Envelope
|
||||
#define REG_VP_VOLXL 0x000C // Current Voice Volume Left
|
||||
#define REG_VP_VOLXR 0x000E // Current Voice Volume Right
|
||||
#define REG_VP_VOLL 0x0000 // Voice Volume Left
|
||||
#define REG_VP_VOLR 0x0002 // Voice Volume Right
|
||||
#define REG_VP_PITCH 0x0004 // Pitch
|
||||
#define REG_VP_ADSR1 0x0006 // Envelope 1 (Attack-Decay-Sustain-Release)
|
||||
#define REG_VP_ADSR2 0x0008 // Envelope 2 (Attack-Decay-Sustain-Release)
|
||||
#define REG_VP_ENVX 0x000A // Current Envelope
|
||||
#define REG_VP_VOLXL 0x000C // Current Voice Volume Left
|
||||
#define REG_VP_VOLXR 0x000E // Current Voice Volume Right
|
||||
|
||||
// .. repeated for each voice ..
|
||||
|
||||
#define REG_S_PMON 0x0180 // Pitch Modulation Spec.
|
||||
#define REG_S_NON 0x0184 // Alloc Noise Generator
|
||||
#define REG_S_VMIXL 0x0188 // Voice Output Mix Left (Dry)
|
||||
#define REG_S_VMIXEL 0x018C // Voice Output Mix Left (Wet)
|
||||
#define REG_S_VMIXR 0x0190 // Voice Output Mix Right (Dry)
|
||||
#define REG_S_VMIXER 0x0194 // Voice Output Mix Right (Wet)
|
||||
#define REG_S_PMON 0x0180 // Pitch Modulation Spec.
|
||||
#define REG_S_NON 0x0184 // Alloc Noise Generator
|
||||
#define REG_S_VMIXL 0x0188 // Voice Output Mix Left (Dry)
|
||||
#define REG_S_VMIXEL 0x018C // Voice Output Mix Left (Wet)
|
||||
#define REG_S_VMIXR 0x0190 // Voice Output Mix Right (Dry)
|
||||
#define REG_S_VMIXER 0x0194 // Voice Output Mix Right (Wet)
|
||||
|
||||
#define REG_P_MMIX 0x0198 // Output Spec. After Voice Mix
|
||||
#define REG_C_ATTR 0x019A // Core X Attrib
|
||||
#define REG_A_IRQA 0x019C // Interrupt Address Spec.
|
||||
#define REG_P_MMIX 0x0198 // Output Spec. After Voice Mix
|
||||
#define REG_C_ATTR 0x019A // Core X Attrib
|
||||
#define REG_A_IRQA 0x019C // Interrupt Address Spec.
|
||||
|
||||
#define REG_S_KON 0x01A0 // Key On 0/1
|
||||
#define REG_S_KOFF 0x01A4 // Key Off 0/1
|
||||
#define REG_S_KON 0x01A0 // Key On 0/1
|
||||
#define REG_S_KOFF 0x01A4 // Key Off 0/1
|
||||
|
||||
#define REG_A_TSA 0x01A8 // Transfer starting address
|
||||
#define REG__1AC 0x01AC // Transfer data
|
||||
#define REG__1AE 0x01AE
|
||||
#define REG_S_ADMAS 0x01B0 // AutoDMA Status
|
||||
#define REG_A_TSA 0x01A8 // Transfer starting address
|
||||
#define REG__1AC 0x01AC // Transfer data
|
||||
#define REG__1AE 0x01AE
|
||||
#define REG_S_ADMAS 0x01B0 // AutoDMA Status
|
||||
|
||||
// 1b2, 1b4, 1b6, 1b8, 1ba, 1bc, 1be are unknown
|
||||
|
||||
#define REG_VA_SSA 0x01C0 // Waveform data starting address
|
||||
#define REG_VA_LSAX 0x01C4 // Loop point address
|
||||
#define REG_VA_NAX 0x01C8 // Waveform data that should be read next
|
||||
#define REG_VA_SSA 0x01C0 // Waveform data starting address
|
||||
#define REG_VA_LSAX 0x01C4 // Loop point address
|
||||
#define REG_VA_NAX 0x01C8 // Waveform data that should be read next
|
||||
|
||||
// .. repeated for each voice ..
|
||||
|
||||
#define REG_A_ESA 0x02E0 //Address: Top address of working area for effects processing
|
||||
#define R_FB_SRC_A 0x02E4 // Feedback Source A
|
||||
#define R_FB_SRC_B 0x02E8 // Feedback Source B
|
||||
#define R_IIR_DEST_A0 0x02EC
|
||||
#define R_IIR_DEST_A1 0x02F0
|
||||
#define R_ACC_SRC_A0 0x02F4
|
||||
#define R_ACC_SRC_A1 0x02F8
|
||||
#define R_ACC_SRC_B0 0x02FC
|
||||
#define R_ACC_SRC_B1 0x0300
|
||||
#define R_IIR_SRC_A0 0x0304
|
||||
#define R_IIR_SRC_A1 0x0308
|
||||
#define R_IIR_DEST_B0 0x030C
|
||||
#define R_IIR_DEST_B1 0x0310
|
||||
#define R_ACC_SRC_C0 0x0314
|
||||
#define R_ACC_SRC_C1 0x0318
|
||||
#define R_ACC_SRC_D0 0x031C
|
||||
#define R_ACC_SRC_D1 0x0320
|
||||
#define R_IIR_SRC_B0 0x0324 // Some sources have R_IIR_SRC_B0 and R_IIR_SRC_B1 swapped ><
|
||||
#define R_IIR_SRC_B1 0x0328 // Assume a typo in the docs and B0 is actually at 324, B1 at 328 in the HW.
|
||||
#define R_MIX_DEST_A0 0x032C
|
||||
#define R_MIX_DEST_A1 0x0330
|
||||
#define R_MIX_DEST_B0 0x0334
|
||||
#define R_MIX_DEST_B1 0x0338
|
||||
#define REG_A_EEA 0x033C // Address: End address of working area for effects processing (upper part of address only!)
|
||||
#define REG_A_ESA 0x02E0 //Address: Top address of working area for effects processing
|
||||
#define R_FB_SRC_A 0x02E4 // Feedback Source A
|
||||
#define R_FB_SRC_B 0x02E8 // Feedback Source B
|
||||
#define R_IIR_DEST_A0 0x02EC
|
||||
#define R_IIR_DEST_A1 0x02F0
|
||||
#define R_ACC_SRC_A0 0x02F4
|
||||
#define R_ACC_SRC_A1 0x02F8
|
||||
#define R_ACC_SRC_B0 0x02FC
|
||||
#define R_ACC_SRC_B1 0x0300
|
||||
#define R_IIR_SRC_A0 0x0304
|
||||
#define R_IIR_SRC_A1 0x0308
|
||||
#define R_IIR_DEST_B0 0x030C
|
||||
#define R_IIR_DEST_B1 0x0310
|
||||
#define R_ACC_SRC_C0 0x0314
|
||||
#define R_ACC_SRC_C1 0x0318
|
||||
#define R_ACC_SRC_D0 0x031C
|
||||
#define R_ACC_SRC_D1 0x0320
|
||||
#define R_IIR_SRC_B0 0x0324 // Some sources have R_IIR_SRC_B0 and R_IIR_SRC_B1 swapped ><
|
||||
#define R_IIR_SRC_B1 0x0328 // Assume a typo in the docs and B0 is actually at 324, B1 at 328 in the HW.
|
||||
#define R_MIX_DEST_A0 0x032C
|
||||
#define R_MIX_DEST_A1 0x0330
|
||||
#define R_MIX_DEST_B0 0x0334
|
||||
#define R_MIX_DEST_B1 0x0338
|
||||
#define REG_A_EEA 0x033C // Address: End address of working area for effects processing (upper part of address only!)
|
||||
|
||||
#define REG_S_ENDX 0x0340 // End Point passed flag
|
||||
#define REG_S_ENDX 0x0340 // End Point passed flag
|
||||
|
||||
#define REG_P_STATX 0x0344 // Status register?
|
||||
#define REG_P_STATX 0x0344 // Status register?
|
||||
|
||||
// 0x346 .. 0x3fe are unknown (unused?)
|
||||
|
||||
|
@ -99,38 +99,38 @@
|
|||
|
||||
// "Different" register area
|
||||
|
||||
#define REG_P_MVOLL 0x0760 // Master Volume Left
|
||||
#define REG_P_MVOLR 0x0762 // Master Volume Right
|
||||
#define REG_P_EVOLL 0x0764 // Effect Volume Left
|
||||
#define REG_P_EVOLR 0x0766 // Effect Volume Right
|
||||
#define REG_P_AVOLL 0x0768 // Core External Input Volume Left (Only Core 1)
|
||||
#define REG_P_AVOLR 0x076A // Core External Input Volume Right (Only Core 1)
|
||||
#define REG_P_BVOLL 0x076C // Sound Data Volume Left
|
||||
#define REG_P_BVOLR 0x076E // Sound Data Volume Right
|
||||
#define REG_P_MVOLXL 0x0770 // Current Master Volume Left
|
||||
#define REG_P_MVOLXR 0x0772 // Current Master Volume Right
|
||||
#define REG_P_MVOLL 0x0760 // Master Volume Left
|
||||
#define REG_P_MVOLR 0x0762 // Master Volume Right
|
||||
#define REG_P_EVOLL 0x0764 // Effect Volume Left
|
||||
#define REG_P_EVOLR 0x0766 // Effect Volume Right
|
||||
#define REG_P_AVOLL 0x0768 // Core External Input Volume Left (Only Core 1)
|
||||
#define REG_P_AVOLR 0x076A // Core External Input Volume Right (Only Core 1)
|
||||
#define REG_P_BVOLL 0x076C // Sound Data Volume Left
|
||||
#define REG_P_BVOLR 0x076E // Sound Data Volume Right
|
||||
#define REG_P_MVOLXL 0x0770 // Current Master Volume Left
|
||||
#define REG_P_MVOLXR 0x0772 // Current Master Volume Right
|
||||
|
||||
#define R_IIR_ALPHA 0x0774 //IIR alpha (% used)
|
||||
#define R_ACC_COEF_A 0x0776
|
||||
#define R_ACC_COEF_B 0x0778
|
||||
#define R_ACC_COEF_C 0x077A
|
||||
#define R_ACC_COEF_D 0x077C
|
||||
#define R_IIR_COEF 0x077E
|
||||
#define R_FB_ALPHA 0x0780 //feedback alpha (% used)
|
||||
#define R_FB_X 0x0782 //feedback
|
||||
#define R_IN_COEF_L 0x0784
|
||||
#define R_IN_COEF_R 0x0786
|
||||
#define R_IIR_ALPHA 0x0774 //IIR alpha (% used)
|
||||
#define R_ACC_COEF_A 0x0776
|
||||
#define R_ACC_COEF_B 0x0778
|
||||
#define R_ACC_COEF_C 0x077A
|
||||
#define R_ACC_COEF_D 0x077C
|
||||
#define R_IIR_COEF 0x077E
|
||||
#define R_FB_ALPHA 0x0780 //feedback alpha (% used)
|
||||
#define R_FB_X 0x0782 //feedback
|
||||
#define R_IN_COEF_L 0x0784
|
||||
#define R_IN_COEF_R 0x0786
|
||||
|
||||
// values repeat for core1
|
||||
|
||||
// End OF "Different" register area
|
||||
|
||||
// SPDIF interface
|
||||
#define SPDIF_OUT 0x07C0 // SPDIF Out: OFF/'PCM'/Bitstream/Bypass
|
||||
#define SPDIF_IRQINFO 0x07C2
|
||||
#define SPDIF_MODE 0x07C6
|
||||
#define SPDIF_MEDIA 0x07C8 // SPDIF Media: 'CD'/DVD
|
||||
#define SPDIF_PROTECT 0x07CC // SPDIF Copy Protection
|
||||
#define SPDIF_OUT 0x07C0 // SPDIF Out: OFF/'PCM'/Bitstream/Bypass
|
||||
#define SPDIF_IRQINFO 0x07C2
|
||||
#define SPDIF_MODE 0x07C6
|
||||
#define SPDIF_MEDIA 0x07C8 // SPDIF Media: 'CD'/DVD
|
||||
#define SPDIF_PROTECT 0x07CC // SPDIF Copy Protection
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
|
@ -147,38 +147,38 @@ Core attributes (SD_C)
|
|||
|
||||
*********************************************************************/
|
||||
|
||||
#define SPDIF_OUT_OFF 0x0000 // no spdif output
|
||||
#define SPDIF_OUT_PCM 0x0020 // encode spdif from spu2 pcm output
|
||||
#define SPDIF_OUT_BYPASS 0x0100 // bypass spu2 processing
|
||||
#define SPDIF_OUT_OFF 0x0000 // no spdif output
|
||||
#define SPDIF_OUT_PCM 0x0020 // encode spdif from spu2 pcm output
|
||||
#define SPDIF_OUT_BYPASS 0x0100 // bypass spu2 processing
|
||||
|
||||
#define SPDIF_MODE_BYPASS_BITSTREAM 0x0002 // bypass mode for digital bitstream data
|
||||
#define SPDIF_MODE_BYPASS_PCM 0x0000 // bypass mode for pcm data (using analog output)
|
||||
#define SPDIF_MODE_BYPASS_BITSTREAM 0x0002 // bypass mode for digital bitstream data
|
||||
#define SPDIF_MODE_BYPASS_PCM 0x0000 // bypass mode for pcm data (using analog output)
|
||||
|
||||
#define SPDIF_MODE_MEDIA_CD 0x0800 // source media is a CD
|
||||
#define SPDIF_MODE_MEDIA_DVD 0x0000 // source media is a DVD
|
||||
#define SPDIF_MODE_MEDIA_CD 0x0800 // source media is a CD
|
||||
#define SPDIF_MODE_MEDIA_DVD 0x0000 // source media is a DVD
|
||||
|
||||
#define SPDIF_MEDIA_CDVD 0x0200
|
||||
#define SPDIF_MEDIA_400 0x0000
|
||||
#define SPDIF_MEDIA_CDVD 0x0200
|
||||
#define SPDIF_MEDIA_400 0x0000
|
||||
|
||||
#define SPDIF_PROTECT_NORMAL 0x0000 // spdif stream is not protected
|
||||
#define SPDIF_PROTECT_PROHIBIT 0x8000 // spdif stream can't be copied
|
||||
#define SPDIF_PROTECT_NORMAL 0x0000 // spdif stream is not protected
|
||||
#define SPDIF_PROTECT_PROHIBIT 0x8000 // spdif stream can't be copied
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
#define VOICE_PARAM_VOLL 0x0 // Voice Volume Left
|
||||
#define VOICE_PARAM_VOLR 0x2 // Voice Volume Right
|
||||
#define VOICE_PARAM_PITCH 0x4 // Pitch
|
||||
#define VOICE_PARAM_ADSR1 0x6 // Envelope 1 (Attack-Delay-Sustain-Release)
|
||||
#define VOICE_PARAM_ADSR2 0x8 // Envelope 2 (Attack-Delay-Sustain-Release)
|
||||
#define VOICE_PARAM_ENVX 0xA // Current Envelope
|
||||
#define VOICE_PARAM_VOLXL 0xC // Current Voice Volume Left
|
||||
#define VOICE_PARAM_VOLXR 0xE // Current Voice Volume Right
|
||||
#define VOICE_PARAM_VOLL 0x0 // Voice Volume Left
|
||||
#define VOICE_PARAM_VOLR 0x2 // Voice Volume Right
|
||||
#define VOICE_PARAM_PITCH 0x4 // Pitch
|
||||
#define VOICE_PARAM_ADSR1 0x6 // Envelope 1 (Attack-Delay-Sustain-Release)
|
||||
#define VOICE_PARAM_ADSR2 0x8 // Envelope 2 (Attack-Delay-Sustain-Release)
|
||||
#define VOICE_PARAM_ENVX 0xA // Current Envelope
|
||||
#define VOICE_PARAM_VOLXL 0xC // Current Voice Volume Left
|
||||
#define VOICE_PARAM_VOLXR 0xE // Current Voice Volume Right
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
#define VOICE_ADDR_SSA 0x0 // Waveform data starting address
|
||||
#define VOICE_ADDR_LSAX 0x4 // Loop point address
|
||||
#define VOICE_ADDR_NAX 0x8 // Waveform data that should be read next
|
||||
#define VOICE_ADDR_SSA 0x0 // Waveform data starting address
|
||||
#define VOICE_ADDR_LSAX 0x4 // Loop point address
|
||||
#define VOICE_ADDR_NAX 0x8 // Waveform data that should be read next
|
||||
|
||||
|
||||
|
||||
|
@ -186,11 +186,10 @@ Core attributes (SD_C)
|
|||
// SPU2-X Register Table LUT
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
#define U16P(x) ( (u16*)&(x) )
|
||||
#define U16P(x) ((u16 *)&(x))
|
||||
|
||||
// Returns the hiword of a 32 bit integer.
|
||||
#define U16P_HI(x) ( ((u16*)&(x))+1 )
|
||||
|
||||
extern u16* regtable[0x401];
|
||||
extern u16 const* const regtable_original[0x401];
|
||||
#define U16P_HI(x) (((u16 *)&(x)) + 1)
|
||||
|
||||
extern u16 *regtable[0x401];
|
||||
extern u16 const *const regtable_original[0x401];
|
||||
|
|
|
@ -70,13 +70,13 @@ Preamble W: Marks a word containing data for channel B.
|
|||
|
||||
typedef struct _subframe
|
||||
{
|
||||
u32 preamble:4;
|
||||
u32 aux_data:4;
|
||||
u32 snd_data:20;
|
||||
u32 validity:1;
|
||||
u32 subcode:1;
|
||||
u32 chstatus:1;
|
||||
u32 parity:1;
|
||||
u32 preamble : 4;
|
||||
u32 aux_data : 4;
|
||||
u32 snd_data : 20;
|
||||
u32 validity : 1;
|
||||
u32 subcode : 1;
|
||||
u32 chstatus : 1;
|
||||
u32 parity : 1;
|
||||
} subframe;
|
||||
|
||||
/*
|
||||
|
@ -103,9 +103,8 @@ typedef struct _subframe
|
|||
|
||||
typedef struct _chstatus
|
||||
{
|
||||
u8 ctrlbits:4;
|
||||
u8 reservd1:4;
|
||||
u8 category;
|
||||
u8 reservd2[22];
|
||||
u8 ctrlbits : 4;
|
||||
u8 reservd1 : 4;
|
||||
u8 category;
|
||||
u8 reservd2[22];
|
||||
} chstatus:
|
||||
|
||||
|
|
|
@ -16,134 +16,132 @@
|
|||
*/
|
||||
|
||||
#include "Global.h"
|
||||
#include "PS2E-spu2.h" // hopefully temporary, until I resolve lClocks depdendency
|
||||
#include "PS2E-spu2.h" // hopefully temporary, until I resolve lClocks depdendency
|
||||
|
||||
namespace Savestate
|
||||
{
|
||||
// Arbitrary ID to identify SPU2-X saves.
|
||||
static const u32 SAVE_ID = 0x1227521;
|
||||
// Arbitrary ID to identify SPU2-X saves.
|
||||
static const u32 SAVE_ID = 0x1227521;
|
||||
|
||||
// versioning for saves.
|
||||
// Increment this when changes to the savestate system are made.
|
||||
static const u32 SAVE_VERSION = 0x000d;
|
||||
// versioning for saves.
|
||||
// Increment this when changes to the savestate system are made.
|
||||
static const u32 SAVE_VERSION = 0x000d;
|
||||
|
||||
static void wipe_the_cache()
|
||||
{
|
||||
memset( pcm_cache_data, 0, pcm_BlockCount * sizeof(PcmCacheEntry) );
|
||||
}
|
||||
static void wipe_the_cache()
|
||||
{
|
||||
memset(pcm_cache_data, 0, pcm_BlockCount * sizeof(PcmCacheEntry));
|
||||
}
|
||||
}
|
||||
|
||||
struct Savestate::DataBlock
|
||||
{
|
||||
u32 spu2id; // SPU2-X state identifier lets ZeroGS/PeopsSPU2 know this isn't their state)
|
||||
u8 unkregs[0x10000]; // SPU2 raw register memory
|
||||
u8 mem[0x200000]; // SPU2 raw sample memory
|
||||
u32 spu2id; // SPU2-X state identifier lets ZeroGS/PeopsSPU2 know this isn't their state)
|
||||
u8 unkregs[0x10000]; // SPU2 raw register memory
|
||||
u8 mem[0x200000]; // SPU2 raw sample memory
|
||||
|
||||
u32 version; // SPU2-X version identifier
|
||||
V_Core Cores[2];
|
||||
V_SPDIF Spdif;
|
||||
s16 OutPos;
|
||||
s16 InputPos;
|
||||
u32 Cycles;
|
||||
u32 lClocks;
|
||||
int PlayMode;
|
||||
u32 version; // SPU2-X version identifier
|
||||
V_Core Cores[2];
|
||||
V_SPDIF Spdif;
|
||||
s16 OutPos;
|
||||
s16 InputPos;
|
||||
u32 Cycles;
|
||||
u32 lClocks;
|
||||
int PlayMode;
|
||||
};
|
||||
|
||||
s32 __fastcall Savestate::FreezeIt( DataBlock& spud )
|
||||
s32 __fastcall Savestate::FreezeIt(DataBlock &spud)
|
||||
{
|
||||
spud.spu2id = SAVE_ID;
|
||||
spud.version = SAVE_VERSION;
|
||||
spud.spu2id = SAVE_ID;
|
||||
spud.version = SAVE_VERSION;
|
||||
|
||||
pxAssertMsg( spu2regs && _spu2mem, "Looks like PCSX2 is trying to savestate while pluigns are shut down. That's a no-no! It shouldn't crash, but the savestate will probably be corrupted." );
|
||||
pxAssertMsg(spu2regs && _spu2mem, "Looks like PCSX2 is trying to savestate while pluigns are shut down. That's a no-no! It shouldn't crash, but the savestate will probably be corrupted.");
|
||||
|
||||
if( spu2regs != NULL ) memcpy(spud.unkregs, spu2regs, sizeof(spud.unkregs));
|
||||
if( _spu2mem != NULL ) memcpy(spud.mem, _spu2mem, sizeof(spud.mem));
|
||||
if (spu2regs != NULL)
|
||||
memcpy(spud.unkregs, spu2regs, sizeof(spud.unkregs));
|
||||
if (_spu2mem != NULL)
|
||||
memcpy(spud.mem, _spu2mem, sizeof(spud.mem));
|
||||
|
||||
memcpy(spud.Cores, Cores, sizeof(Cores));
|
||||
memcpy(&spud.Spdif, &Spdif, sizeof(Spdif));
|
||||
memcpy(spud.Cores, Cores, sizeof(Cores));
|
||||
memcpy(&spud.Spdif, &Spdif, sizeof(Spdif));
|
||||
|
||||
spud.OutPos = OutPos;
|
||||
spud.InputPos = InputPos;
|
||||
spud.Cycles = Cycles;
|
||||
spud.lClocks = lClocks;
|
||||
spud.PlayMode = PlayMode;
|
||||
spud.OutPos = OutPos;
|
||||
spud.InputPos = InputPos;
|
||||
spud.Cycles = Cycles;
|
||||
spud.lClocks = lClocks;
|
||||
spud.PlayMode = PlayMode;
|
||||
|
||||
// note: Don't save the cache. PCSX2 doesn't offer a safe method of predicting
|
||||
// the required size of the savestate prior to saving, plus this is just too
|
||||
// "implementation specific" for the intended spec of a savestate. Let's just
|
||||
// force the user to rebuild their cache instead.
|
||||
// note: Don't save the cache. PCSX2 doesn't offer a safe method of predicting
|
||||
// the required size of the savestate prior to saving, plus this is just too
|
||||
// "implementation specific" for the intended spec of a savestate. Let's just
|
||||
// force the user to rebuild their cache instead.
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 __fastcall Savestate::ThawIt( DataBlock& spud )
|
||||
s32 __fastcall Savestate::ThawIt(DataBlock &spud)
|
||||
{
|
||||
if( spud.spu2id != SAVE_ID || spud.version < SAVE_VERSION )
|
||||
{
|
||||
fprintf(stderr, "\n*** SPU2-X Warning:\n");
|
||||
if( spud.spu2id == SAVE_ID )
|
||||
fprintf(stderr, "\tSavestate version is from an older version of this plugin.\n");
|
||||
else
|
||||
fprintf(stderr, "\tThe savestate you are trying to load was not made with this plugin.\n");
|
||||
if (spud.spu2id != SAVE_ID || spud.version < SAVE_VERSION) {
|
||||
fprintf(stderr, "\n*** SPU2-X Warning:\n");
|
||||
if (spud.spu2id == SAVE_ID)
|
||||
fprintf(stderr, "\tSavestate version is from an older version of this plugin.\n");
|
||||
else
|
||||
fprintf(stderr, "\tThe savestate you are trying to load was not made with this plugin.\n");
|
||||
|
||||
fprintf(stderr,
|
||||
"\tAudio may not recover correctly. Save your game to memorycard, reset,\n\n"
|
||||
"\tand then continue from there.\n\n"
|
||||
);
|
||||
fprintf(stderr,
|
||||
"\tAudio may not recover correctly. Save your game to memorycard, reset,\n\n"
|
||||
"\tand then continue from there.\n\n");
|
||||
|
||||
// Do *not* reset the cores.
|
||||
// We'll need some "hints" as to how the cores should be initialized, and the
|
||||
// only way to get that is to use the game's existing core settings and hope
|
||||
// they kinda match the settings for the savestate (IRQ enables and such).
|
||||
// Do *not* reset the cores.
|
||||
// We'll need some "hints" as to how the cores should be initialized, and the
|
||||
// only way to get that is to use the game's existing core settings and hope
|
||||
// they kinda match the settings for the savestate (IRQ enables and such).
|
||||
|
||||
// adpcm cache : Clear all the cache flags and buffers.
|
||||
// adpcm cache : Clear all the cache flags and buffers.
|
||||
|
||||
wipe_the_cache();
|
||||
}
|
||||
else
|
||||
{
|
||||
SndBuffer::ClearContents();
|
||||
wipe_the_cache();
|
||||
} else {
|
||||
SndBuffer::ClearContents();
|
||||
|
||||
pxAssertMsg( spu2regs && _spu2mem, "Looks like PCSX2 is trying to loadstate while pluigns are shut down. That's a no-no! It shouldn't crash, but the savestate will probably be corrupted." );
|
||||
pxAssertMsg(spu2regs && _spu2mem, "Looks like PCSX2 is trying to loadstate while pluigns are shut down. That's a no-no! It shouldn't crash, but the savestate will probably be corrupted.");
|
||||
|
||||
// base stuff
|
||||
if( spu2regs ) memcpy(spu2regs, spud.unkregs, sizeof(spud.unkregs));
|
||||
if( _spu2mem ) memcpy(_spu2mem, spud.mem, sizeof(spud.mem));
|
||||
// base stuff
|
||||
if (spu2regs)
|
||||
memcpy(spu2regs, spud.unkregs, sizeof(spud.unkregs));
|
||||
if (_spu2mem)
|
||||
memcpy(_spu2mem, spud.mem, sizeof(spud.mem));
|
||||
|
||||
memcpy(Cores, spud.Cores, sizeof(Cores));
|
||||
memcpy(&Spdif, &spud.Spdif, sizeof(Spdif));
|
||||
memcpy(Cores, spud.Cores, sizeof(Cores));
|
||||
memcpy(&Spdif, &spud.Spdif, sizeof(Spdif));
|
||||
|
||||
OutPos = spud.OutPos;
|
||||
InputPos = spud.InputPos;
|
||||
Cycles = spud.Cycles;
|
||||
lClocks = spud.lClocks;
|
||||
PlayMode = spud.PlayMode;
|
||||
OutPos = spud.OutPos;
|
||||
InputPos = spud.InputPos;
|
||||
Cycles = spud.Cycles;
|
||||
lClocks = spud.lClocks;
|
||||
PlayMode = spud.PlayMode;
|
||||
|
||||
wipe_the_cache();
|
||||
wipe_the_cache();
|
||||
|
||||
// Go through the V_Voice structs and recalculate SBuffer pointer from
|
||||
// the NextA setting.
|
||||
// Go through the V_Voice structs and recalculate SBuffer pointer from
|
||||
// the NextA setting.
|
||||
|
||||
for( int c=0; c<2; c++ )
|
||||
{
|
||||
for( int v=0; v<24; v++ )
|
||||
{
|
||||
const int cacheIdx = Cores[c].Voices[v].NextA / pcm_WordsPerBlock;
|
||||
Cores[c].Voices[v].SBuffer = pcm_cache_data[cacheIdx].Sampledata;
|
||||
}
|
||||
}
|
||||
for (int c = 0; c < 2; c++) {
|
||||
for (int v = 0; v < 24; v++) {
|
||||
const int cacheIdx = Cores[c].Voices[v].NextA / pcm_WordsPerBlock;
|
||||
Cores[c].Voices[v].SBuffer = pcm_cache_data[cacheIdx].Sampledata;
|
||||
}
|
||||
}
|
||||
|
||||
// HACKFIX!! DMAPtr can be invalid after a savestate load, so force it to NULL and
|
||||
// ignore it on any pending ADMA writes. (the DMAPtr concept used to work in old VM
|
||||
// editions of PCSX2 with fixed addressing, but new PCSX2s have dynamic memory
|
||||
// addressing).
|
||||
// HACKFIX!! DMAPtr can be invalid after a savestate load, so force it to NULL and
|
||||
// ignore it on any pending ADMA writes. (the DMAPtr concept used to work in old VM
|
||||
// editions of PCSX2 with fixed addressing, but new PCSX2s have dynamic memory
|
||||
// addressing).
|
||||
|
||||
Cores[0].DMAPtr = Cores[1].DMAPtr = NULL;
|
||||
}
|
||||
return 0;
|
||||
Cores[0].DMAPtr = Cores[1].DMAPtr = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 __fastcall Savestate::SizeIt()
|
||||
{
|
||||
return sizeof(DataBlock);
|
||||
return sizeof(DataBlock);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue