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:
Clang Format 2016-10-10 20:35:26 +02:00 committed by Gregory Hainaut
parent 0f022da98c
commit 039573b133
59 changed files with 10023 additions and 10027 deletions

View File

@ -19,49 +19,46 @@
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
{
for (int i=0; i<(32+128); i++)
{
int shift=(i-32)>>2;
s64 rate=(i&3)+4;
if (shift<0)
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:
const uint newSr = 0x7f - SrAr;
return ((1|(newSr&3)) << (newSr>>2));
return ((1 | (newSr & 3)) << (newSr >> 2));
}
bool V_ADSR::Calculate()
{
pxAssume( Phase != 0 );
pxAssume(Phase != 0);
if(Releasing && (Phase < 5))
if (Releasing && (Phase < 5))
Phase = 5;
switch (Phase)
{
switch (Phase) {
case 1: // attack
if( Value == ADSR_MAX_VOL )
{
if (Value == ADSR_MAX_VOL) {
// Already maxed out. Progress phase and nothing more:
Phase++;
break;
@ -70,13 +67,12 @@ bool V_ADSR::Calculate()
// 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];
if (AttackMode && (Value >= 0x60000000))
Value += PsxRates[(AttackRate ^ 0x7f) - 0x18 + 32];
else
Value += PsxRates[(AttackRate^0x7f)-0x10+32];
Value += PsxRates[(AttackRate ^ 0x7f) - 0x10 + 32];
if( Value < 0 )
{
if (Value < 0) {
// We hit the ceiling.
Phase++;
Value = ADSR_MAX_VOL;
@ -85,88 +81,78 @@ bool V_ADSR::Calculate()
case 2: // decay
{
u32 off = InvExpOffsets[(Value>>28)&7];
Value -= PsxRates[((DecayRate^0x1f)*4)-0x18+off+32];
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.
s32 suslev = ((0x80000000 / 0x10 ) * (SustainLevel+1)) - 1;
s32 suslev = ((0x80000000 / 0x10) * (SustainLevel + 1)) - 1;
if( Value <= suslev )
{
if (Value <= suslev) {
if (Value < 0)
Value = 0;
Phase++;
}
}
break;
} break;
case 3: // sustain
{
// 0x7f disables sustain (infinite sustain)
if( SustainRate == 0x7f ) return true;
if (SustainRate == 0x7f)
return true;
if (SustainMode&2) // decreasing
if (SustainMode & 2) // decreasing
{
if (SustainMode&4) // exponential
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];
u32 off = InvExpOffsets[(Value >> 28) & 7];
Value -= PsxRates[(SustainRate ^ 0x7f) - 0x1b + off + 32];
} else // linear
Value -= PsxRates[(SustainRate ^ 0x7f) - 0xf + 32];
if( Value <= 0 )
{
if (Value <= 0) {
Value = 0;
Phase++;
}
}
else // increasing
{
if( (SustainMode&4) && (Value>=0x60000000) )
Value += PsxRates[(SustainRate^0x7f)-0x18+32];
} 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];
Value += PsxRates[(SustainRate ^ 0x7f) - 0x10 + 32];
if( Value < 0 )
{
if (Value < 0) {
Value = ADSR_MAX_VOL;
Phase++;
}
}
}
break;
} break;
case 4: // sustain end
Value = (SustainMode&2) ? 0 : ADSR_MAX_VOL;
if(Value==0)
Phase=6;
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
{
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 (ReleaseRate != 0x1f)
Value -= (1 << (0x1f - ReleaseRate));
}
if( Value <= 0 )
{
Value=0;
if (Value <= 0) {
Value = 0;
Phase++;
}
break;
case 6: // release end
Value=0;
Value = 0;
break;
jNO_DEFAULT
@ -180,53 +166,49 @@ bool V_ADSR::Calculate()
/////////////////////////////////////////////////////////////////////////////////////////
// //
#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)
if( Increment == 0x7f ) return;
if (Increment == 0x7f)
return;
s32 value = abs(Value);
if (Mode & VOLFLAG_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)
{
if (value < 0) {
value = 0;
Mode = 0; // disable slide
}
}
else
{
} 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];
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];
value += PsxRates[(Increment ^ 0x7f) - 0x10 + 32];
if( value < 0 ) // wrapped around the "top"?
if (value < 0) // wrapped around the "top"?
{
value = 0x7fffffff;
Mode = 0; // disable slide

View File

@ -92,7 +92,7 @@ extern bool dspPluginEnabled;
namespace SoundtouchCfg
{
extern void ApplySettings( soundtouch::SoundTouch& sndtouch );
extern void ApplySettings(soundtouch::SoundTouch &sndtouch);
}
//////

View File

@ -35,17 +35,17 @@ protected:
LPF_data lpf_r;
u8 bufdone;
s32 Gfl,Gfr;
s32 Gfl, Gfr;
s32 spdif_data[6];
s32 LMax,RMax;
s32 LMax, RMax;
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

View File

@ -17,24 +17,27 @@
#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;
if(!AccessLog()) return;
if(!spu2Log) return;
if (!AccessLog())
return;
if (!spu2Log)
return;
va_start(list, fmt);
vsprintf(s,fmt, list);
vsprintf(s, fmt, list);
va_end(list);
fputs(s,spu2Log);
fputs(s, spu2Log);
fflush(spu2Log);
#if 0
@ -51,43 +54,44 @@ 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);
vsprintf(s, fmt, list);
va_end(list);
fputs(s,stderr);
fputs(s, stderr);
fflush(stderr);
if(spu2Log)
{
fputs(s,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"
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()
@ -95,79 +99,73 @@ void DoFullDump()
#ifdef _MSC_VER
#ifdef SPU2_LOG
FILE *dump;
u8 c=0, v=0;
u8 c = 0, v = 0;
if(MemDump())
{
dump = fopen( wxString(MemDumpFileName).ToUTF8(), "wb" );
if (dump)
{
fwrite(_spu2mem,0x200000,1,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);
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"
fprintf(dump, " - ADSR Envelope: %x & %x\n"
" - Ar: %x\n"
" - Am: %x\n"
" - Dr: %x\n"
@ -191,69 +189,67 @@ void DoFullDump()
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, " - 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");
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);
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," - 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, " - 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," - 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, " - 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," - 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, " - 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," - 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, " - 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");
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);
}

View File

@ -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
{
enum CoreSourceType {
// Core's input stream, usually pulled from ADMA streams.
CoreSrc_Input = 0
CoreSrc_Input = 0,
// Output of the actual 24 input voices which have dry output enabled.
, CoreSrc_DryVoiceMix
CoreSrc_DryVoiceMix,
// Output of the actual 24 input voices that have wet output enabled.
, CoreSrc_WetVoiceMix
CoreSrc_WetVoiceMix,
// Wet mix including inputs and externals, prior to the application of reverb.
, CoreSrc_PreReverb
CoreSrc_PreReverb,
// Wet mix after reverb has turned it into a pile of garbly gook.
, CoreSrc_PostReverb
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
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;

View File

@ -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)
{
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;
} 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;
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);
if (ANum >= 128) {
ANum = 0;
LAccum = 1 + ((LAccum * 224 + LMax * 31) >> 8);
RAccum = 1 + ((RAccum * 224 + RMax * 31) >> 8);
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;
Gfl = (Gfl * 200 + Tfl * 56)>>8;
Gfr = (Gfr * 200 + Tfr * 56)>>8;
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;
}
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;
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 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 )

View File

@ -28,41 +28,53 @@ static FILE *ADMA4LogFile = NULL;
static FILE *ADMA7LogFile = NULL;
static FILE *ADMAOutLogFile = NULL;
static FILE *REGWRTLogFile[2] = {0,0};
static FILE *REGWRTLogFile[2] = {0, 0};
void DMALogOpen()
{
if(!DMALog()) return;
DMA4LogFile = OpenBinaryLog( DMA4LogFileName );
DMA7LogFile = OpenBinaryLog( DMA7LogFileName );
ADMA4LogFile = OpenBinaryLog( L"adma4.raw" );
ADMA7LogFile = OpenBinaryLog( L"adma7.raw" );
ADMAOutLogFile = OpenBinaryLog( L"admaOut.raw" );
if (!DMALog())
return;
DMA4LogFile = OpenBinaryLog(DMA4LogFileName);
DMA7LogFile = OpenBinaryLog(DMA7LogFileName);
ADMA4LogFile = OpenBinaryLog(L"adma4.raw");
ADMA7LogFile = OpenBinaryLog(L"adma7.raw");
ADMAOutLogFile = OpenBinaryLog(L"admaOut.raw");
}
void DMA4LogWrite(void *lpData, u32 ulSize) {
if(!DMALog()) return;
if (!DMA4LogFile) return;
fwrite(lpData,ulSize,1,DMA4LogFile);
}
void DMA7LogWrite(void *lpData, u32 ulSize) {
if(!DMALog()) return;
if (!DMA7LogFile) return;
fwrite(lpData,ulSize,1,DMA7LogFile);
}
void ADMAOutLogWrite(void *lpData, u32 ulSize) {
if(!DMALog()) return;
if (!ADMAOutLogFile) return;
fwrite(lpData,ulSize,1,ADMAOutLogFile);
}
void RegWriteLog(u32 core,u16 value)
void DMA4LogWrite(void *lpData, u32 ulSize)
{
if(!DMALog()) return;
if (!REGWRTLogFile[core]) return;
fwrite(&value,2,1,REGWRTLogFile[core]);
if (!DMALog())
return;
if (!DMA4LogFile)
return;
fwrite(lpData, ulSize, 1, DMA4LogFile);
}
void DMA7LogWrite(void *lpData, u32 ulSize)
{
if (!DMALog())
return;
if (!DMA7LogFile)
return;
fwrite(lpData, ulSize, 1, DMA7LogFile);
}
void ADMAOutLogWrite(void *lpData, u32 ulSize)
{
if (!DMALog())
return;
if (!ADMAOutLogFile)
return;
fwrite(lpData, ulSize, 1, ADMAOutLogFile);
}
void RegWriteLog(u32 core, u16 value)
{
if (!DMALog())
return;
if (!REGWRTLogFile[core])
return;
fwrite(&value, 2, 1, REGWRTLogFile[core]);
}
void DMALogClose()
@ -76,100 +88,90 @@ void DMALogClose()
safe_fclose(ADMAOutLogFile);
}
void V_Core::LogAutoDMA( FILE* fp )
void V_Core::LogAutoDMA(FILE *fp)
{
if( !DMALog() || !fp || !DMAPtr ) return;
fwrite( DMAPtr+InputDataProgress, 0x400, 1, fp );
if (!DMALog() || !fp || !DMAPtr)
return;
fwrite(DMAPtr + InputDataProgress, 0x400, 1, fp);
}
void V_Core::AutoDMAReadBuffer(int mode) //mode: 0= split stereo; 1 = do not split stereo
{
#ifndef ENABLE_NEW_IOPDMA_SPU2
int spos = ((InputPosRead+0xff)&0x100); //starting position of the free buffer
int spos = ((InputPosRead + 0xff) & 0x100); //starting position of the free buffer
LogAutoDMA( Index ? ADMA7LogFile : ADMA4LogFile );
LogAutoDMA(Index ? ADMA7LogFile : ADMA4LogFile);
// HACKFIX!! DMAPtr can be invalid after a savestate load, so the savestate just forces it
// to NULL and we ignore it here. (used to work in old VM editions of PCSX2 with fixed
// addressing, but new PCSX2s have dynamic memory addressing).
if(mode)
{
if( DMAPtr != NULL )
if (mode) {
if (DMAPtr != NULL)
//memcpy((ADMATempBuffer+(spos<<1)),DMAPtr+InputDataProgress,0x400);
memcpy(GetMemPtr(0x2000+(Index<<10)+spos),DMAPtr+InputDataProgress,0x400);
MADR+=0x400;
InputDataLeft-=0x200;
InputDataProgress+=0x200;
}
else
{
if( DMAPtr != NULL )
memcpy(GetMemPtr(0x2000 + (Index << 10) + spos), DMAPtr + InputDataProgress, 0x400);
MADR += 0x400;
InputDataLeft -= 0x200;
InputDataProgress += 0x200;
} else {
if (DMAPtr != NULL)
//memcpy((ADMATempBuffer+spos),DMAPtr+InputDataProgress,0x200);
memcpy(GetMemPtr(0x2000+(Index<<10)+spos),DMAPtr+InputDataProgress,0x200);
MADR+=0x200;
InputDataLeft-=0x100;
InputDataProgress+=0x100;
memcpy(GetMemPtr(0x2000 + (Index << 10) + spos), DMAPtr + InputDataProgress, 0x200);
MADR += 0x200;
InputDataLeft -= 0x100;
InputDataProgress += 0x100;
if( DMAPtr != NULL )
if (DMAPtr != NULL)
//memcpy((ADMATempBuffer+spos+0x200),DMAPtr+InputDataProgress,0x200);
memcpy(GetMemPtr(0x2200+(Index<<10)+spos),DMAPtr+InputDataProgress,0x200);
MADR+=0x200;
InputDataLeft-=0x100;
InputDataProgress+=0x100;
memcpy(GetMemPtr(0x2200 + (Index << 10) + spos), DMAPtr + InputDataProgress, 0x200);
MADR += 0x200;
InputDataLeft -= 0x100;
InputDataProgress += 0x100;
}
// See ReadInput at mixer.cpp for explanation on the commented out lines
//
// See ReadInput at mixer.cpp for explanation on the commented out lines
//
#endif
}
void V_Core::StartADMAWrite(u16 *pMem, u32 sz)
{
#ifndef ENABLE_NEW_IOPDMA_SPU2
int size = (sz)&(~511);
int size = (sz) & (~511);
if(MsgAutoDMA()) ConLog("* SPU2-X: DMA%c AutoDMA Transfer of %d bytes to %x (%02x %x %04x).\n",
GetDmaIndexChar(), size<<1, TSA, DMABits, AutoDMACtrl, (~Regs.ATTR)&0x7fff);
if (MsgAutoDMA())
ConLog("* SPU2-X: DMA%c AutoDMA Transfer of %d bytes to %x (%02x %x %04x).\n",
GetDmaIndexChar(), size << 1, TSA, DMABits, AutoDMACtrl, (~Regs.ATTR) & 0x7fff);
InputDataProgress = 0;
if((AutoDMACtrl&(Index+1))==0)
{
TSA = 0x2000 + (Index<<10);
if ((AutoDMACtrl & (Index + 1)) == 0) {
TSA = 0x2000 + (Index << 10);
DMAICounter = size;
}
else if(size>=512)
{
} else if (size >= 512) {
InputDataLeft = size;
if(AdmaInProgress==0)
{
if (AdmaInProgress == 0) {
#ifdef PCM24_S1_INTERLEAVE
if((Index==1)&&((PlayMode&8)==8))
{
AutoDMAReadBuffer(Index,1);
}
else
{
AutoDMAReadBuffer(Index,0);
if ((Index == 1) && ((PlayMode & 8) == 8)) {
AutoDMAReadBuffer(Index, 1);
} else {
AutoDMAReadBuffer(Index, 0);
}
#else
if( ((PlayMode&4)==4) && (Index==0) )
Cores[0].InputPosRead=0;
if (((PlayMode & 4) == 4) && (Index == 0))
Cores[0].InputPosRead = 0;
AutoDMAReadBuffer(0);
#endif
// Klonoa 2
if(size==512)
if (size == 512)
DMAICounter = size;
}
AdmaInProgress = 1;
}
else
{
} else {
InputDataLeft = 0;
DMAICounter = 1;
}
TADR = MADR + (size<<1);
TADR = MADR + (size << 1);
#endif
}
@ -196,44 +198,41 @@ void V_Core::PlainDMAWrite(u16 *pMem, u32 size)
// Not really important. Everything should work regardless,
// but it could be indicative of an emulation foopah elsewhere.
if(MsgToConsole()) {
if (MsgToConsole()) {
// Don't need this anymore. Target may still be good to know though.
/*if((uptr)pMem & 15)
{
ConLog("* SPU2 DMA Write > Misaligned source. Core: %d IOP: %p TSA: 0x%x Size: 0x%x\n", Index, (void*)pMem, TSA, size);
}*/
if(TSA & 7)
{
ConLog("* SPU2 DMA Write > Misaligned target. Core: %d IOP: %p TSA: 0x%x Size: 0x%x\n", Index, (void*)pMem, TSA, size );
if (TSA & 7) {
ConLog("* SPU2 DMA Write > Misaligned target. Core: %d IOP: %p TSA: 0x%x Size: 0x%x\n", Index, (void *)pMem, TSA, size);
}
}
if(Index==0)
DMA4LogWrite(pMem,size<<1);
if (Index == 0)
DMA4LogWrite(pMem, size << 1);
else
DMA7LogWrite(pMem,size<<1);
DMA7LogWrite(pMem, size << 1);
TSA &= 0xfffff;
u32 buff1end = TSA + size;
u32 buff2end=0;
if( buff1end > 0x100000 )
{
u32 buff2end = 0;
if (buff1end > 0x100000) {
buff2end = buff1end - 0x100000;
buff1end = 0x100000;
}
const int cacheIdxStart = TSA / pcm_WordsPerBlock;
const int cacheIdxEnd = (buff1end+pcm_WordsPerBlock-1) / pcm_WordsPerBlock;
PcmCacheEntry* cacheLine = &pcm_cache_data[cacheIdxStart];
PcmCacheEntry& cacheEnd = pcm_cache_data[cacheIdxEnd];
const int cacheIdxEnd = (buff1end + pcm_WordsPerBlock - 1) / pcm_WordsPerBlock;
PcmCacheEntry *cacheLine = &pcm_cache_data[cacheIdxStart];
PcmCacheEntry &cacheEnd = pcm_cache_data[cacheIdxEnd];
do
{
do {
cacheLine->Validated = false;
cacheLine++;
} while ( cacheLine != &cacheEnd );
} while (cacheLine != &cacheEnd);
//ConLog( "* SPU2-X: Cache Clear Range! TSA=0x%x, TDA=0x%x (low8=0x%x, high8=0x%x, len=0x%x)\n",
// TSA, buff1end, flagTSA, flagTDA, clearLen );
@ -242,13 +241,12 @@ void V_Core::PlainDMAWrite(u16 *pMem, u32 size)
// First Branch needs cleared:
// It starts at TSA and goes to buff1end.
const u32 buff1size = (buff1end-TSA);
memcpy( GetMemPtr( TSA ), pMem, buff1size*2 );
const u32 buff1size = (buff1end - TSA);
memcpy(GetMemPtr(TSA), pMem, buff1size * 2);
u32 TDA;
if( buff2end > 0 )
{
if (buff2end > 0) {
// second branch needs copied:
// It starts at the beginning of memory and moves forward to buff2end
@ -260,16 +258,15 @@ void V_Core::PlainDMAWrite(u16 *pMem, u32 size)
// Emulation Grayarea: Should addresses wrap around to zero, or wrap around to
// 0x2800? Hard to know for sure (almost no games depend on this)
memcpy( GetMemPtr( 0 ), &pMem[buff1size], buff2end*2 );
TDA = (buff2end+1) & 0xfffff;
memcpy(GetMemPtr(0), &pMem[buff1size], buff2end * 2);
TDA = (buff2end + 1) & 0xfffff;
// Flag interrupt? If IRQA occurs between start and dest, flag it.
// Important: Test both core IRQ settings for either DMA!
// Note: Because this buffer wraps, we use || instead of &&
// Flag interrupt? If IRQA occurs between start and dest, flag it.
// Important: Test both core IRQ settings for either DMA!
// Note: Because this buffer wraps, we use || instead of &&
#if NO_BIOS_HACKFIX
for( int i=0; i<2; i++ )
{
for (int i = 0; i < 2; i++) {
// Start is exclusive and end is inclusive... maybe? The end is documented to be inclusive,
// which suggests that memory access doesn't trigger interrupts, incrementing registers does
// (which would mean that if TSA=IRQA an interrupt doesn't fire... I guess?)
@ -279,8 +276,7 @@ void V_Core::PlainDMAWrite(u16 *pMem, u32 size)
// understanding would trigger the interrupt early causing it to switch buffers again immediately
// and an interrupt never fires again, leaving the voices looping the same samples forever.
if (Cores[i].IRQEnable && (Cores[i].IRQA > TSA || Cores[i].IRQA <= TDA))
{
if (Cores[i].IRQEnable && (Cores[i].IRQA > TSA || Cores[i].IRQA <= TDA)) {
//ConLog("DMAwrite Core %d: IRQ Called (IRQ passed). IRQA = %x Cycles = %d\n", i, Cores[i].IRQA, Cycles );
SetIrqCall(i);
}
@ -291,29 +287,24 @@ void V_Core::PlainDMAWrite(u16 *pMem, u32 size)
SetIrqCall(Index);
}
#endif
}
else
{
} else {
// Buffer doesn't wrap/overflow!
// Just set the TDA and check for an IRQ...
TDA = (buff1end + 1) & 0xfffff;
// Flag interrupt? If IRQA occurs between start and dest, flag it.
// Important: Test both core IRQ settings for either DMA!
// Flag interrupt? If IRQA occurs between start and dest, flag it.
// Important: Test both core IRQ settings for either DMA!
#if NO_BIOS_HACKFIX
for( int i=0; i<2; i++ )
{
if (Cores[i].IRQEnable && (Cores[i].IRQA > TSA && Cores[i].IRQA <= TDA))
{
for (int i = 0; i < 2; i++) {
if (Cores[i].IRQEnable && (Cores[i].IRQA > TSA && Cores[i].IRQA <= TDA)) {
//ConLog("DMAwrite Core %d: IRQ Called (IRQ passed). IRQA = %x Cycles = %d\n", i, Cores[i].IRQA, Cycles );
SetIrqCall(i);
}
}
#else
if( IRQEnable && (IRQA > TSA) && (IRQA <= TDA) )
{
if (IRQEnable && (IRQA > TSA) && (IRQA <= TDA)) {
SetIrqCall(Index);
}
#endif
@ -321,24 +312,23 @@ void V_Core::PlainDMAWrite(u16 *pMem, u32 size)
TSA = TDA;
DMAICounter = size;
TADR = MADR + (size<<1);
TADR = MADR + (size << 1);
}
void V_Core::DoDMAread(u16* pMem, u32 size)
void V_Core::DoDMAread(u16 *pMem, u32 size)
{
#ifndef ENABLE_NEW_IOPDMA_SPU2
TSA &= 0xfffff;
u32 buff1end = TSA + size;
u32 buff2end = 0;
if( buff1end > 0x100000 )
{
if (buff1end > 0x100000) {
buff2end = buff1end - 0x100000;
buff1end = 0x100000;
}
const u32 buff1size = (buff1end-TSA);
memcpy( pMem, GetMemPtr( TSA ), buff1size*2 );
const u32 buff1size = (buff1end - TSA);
memcpy(pMem, GetMemPtr(TSA), buff1size * 2);
// Note on TSA's position after our copy finishes:
// IRQA should be measured by the end of the writepos+0x20. But the TDA
@ -346,29 +336,24 @@ void V_Core::DoDMAread(u16* pMem, u32 size)
u32 TDA;
if( buff2end > 0 )
{
if (buff2end > 0) {
// second branch needs cleared:
// It starts at the beginning of memory and moves forward to buff2end
memcpy( &pMem[buff1size], GetMemPtr( 0 ), buff2end*2 );
memcpy(&pMem[buff1size], GetMemPtr(0), buff2end * 2);
TDA = (buff2end+0x20) & 0xfffff;
TDA = (buff2end + 0x20) & 0xfffff;
// Flag interrupt? If IRQA occurs between start and dest, flag it.
// Important: Test both core IRQ settings for either DMA!
// Note: Because this buffer wraps, we use || instead of &&
for( int i=0; i<2; i++ )
{
if (Cores[i].IRQEnable && (Cores[i].IRQA > TSA || Cores[i].IRQA <= TDA))
{
for (int i = 0; i < 2; i++) {
if (Cores[i].IRQEnable && (Cores[i].IRQA > TSA || Cores[i].IRQA <= TDA)) {
SetIrqCall(i);
}
}
}
else
{
} else {
// Buffer doesn't wrap/overflow!
// Just set the TDA and check for an IRQ...
@ -377,10 +362,8 @@ void V_Core::DoDMAread(u16* pMem, u32 size)
// Flag interrupt? If IRQA occurs between start and dest, flag it.
// Important: Test both core IRQ settings for either DMA!
for( int i=0; i<2; i++ )
{
if (Cores[i].IRQEnable && (Cores[i].IRQA > TSA && Cores[i].IRQA <= TDA))
{
for (int i = 0; i < 2; i++) {
if (Cores[i].IRQEnable && (Cores[i].IRQA > TSA && Cores[i].IRQA <= TDA)) {
SetIrqCall(i);
}
}
@ -391,60 +374,56 @@ void V_Core::DoDMAread(u16* pMem, u32 size)
DMAICounter = size;
Regs.STATX &= ~0x80;
//Regs.ATTR |= 0x30;
TADR = MADR + (size<<1);
TADR = MADR + (size << 1);
#endif
}
void V_Core::DoDMAwrite(u16* pMem, u32 size)
void V_Core::DoDMAwrite(u16 *pMem, u32 size)
{
#ifndef ENABLE_NEW_IOPDMA_SPU2
DMAPtr = pMem;
if(size<2) {
if (size < 2) {
//if(dma7callback) dma7callback();
Regs.STATX &= ~0x80;
//Regs.ATTR |= 0x30;
DMAICounter=1;
DMAICounter = 1;
return;
}
if( IsDevBuild )
{
if (IsDevBuild) {
DebugCores[Index].lastsize = size;
DebugCores[Index].dmaFlag = 2;
}
if(MsgToConsole())
{
if (TSA > 0xfffff){
if (MsgToConsole()) {
if (TSA > 0xfffff) {
ConLog("* SPU2-X: Transfer Start Address out of bounds. TSA is %x\n", TSA);
}
}
TSA &= 0xfffff;
bool adma_enable = ((AutoDMACtrl&(Index+1))==(Index+1));
bool adma_enable = ((AutoDMACtrl & (Index + 1)) == (Index + 1));
if(adma_enable)
{
TSA&=0x1fff;
StartADMAWrite(pMem,size);
}
else
{
if(MsgDMA()) ConLog("* SPU2-X: DMA%c Transfer of %d bytes to %x (%02x %x %04x). IRQE = %d IRQA = %x \n",
GetDmaIndexChar(),size<<1,TSA,DMABits,AutoDMACtrl,(~Regs.ATTR)&0x7fff,
if (adma_enable) {
TSA &= 0x1fff;
StartADMAWrite(pMem, size);
} else {
if (MsgDMA())
ConLog("* SPU2-X: DMA%c Transfer of %d bytes to %x (%02x %x %04x). IRQE = %d IRQA = %x \n",
GetDmaIndexChar(), size << 1, TSA, DMABits, AutoDMACtrl, (~Regs.ATTR) & 0x7fff,
Cores[0].IRQEnable, Cores[0].IRQA);
PlainDMAWrite(pMem,size);
PlainDMAWrite(pMem, size);
}
Regs.STATX &= ~0x80;
//Regs.ATTR |= 0x30;
//Regs.ATTR |= 0x30;
#endif
}
s32 V_Core::NewDmaRead(u32* data, u32 bytesLeft, u32* bytesProcessed)
s32 V_Core::NewDmaRead(u32 *data, u32 bytesLeft, u32 *bytesProcessed)
{
#ifdef ENABLE_NEW_IOPDMA_SPU2
bool DmaStarting = !DmaStarted;
@ -452,18 +431,17 @@ s32 V_Core::NewDmaRead(u32* data, u32 bytesLeft, u32* bytesProcessed)
TSA &= 0xfffff;
u16* pMem = (u16*)data;
u16 *pMem = (u16 *)data;
u32 buff1end = TSA + bytesLeft;
u32 buff2end = 0;
if( buff1end > 0x100000 )
{
if (buff1end > 0x100000) {
buff2end = buff1end - 0x100000;
buff1end = 0x100000;
}
const u32 buff1size = (buff1end-TSA);
memcpy( pMem, GetMemPtr( TSA ), buff1size*2 );
const u32 buff1size = (buff1end - TSA);
memcpy(pMem, GetMemPtr(TSA), buff1size * 2);
// Note on TSA's position after our copy finishes:
// IRQA should be measured by the end of the writepos+0x20. But the TDA
@ -471,29 +449,24 @@ s32 V_Core::NewDmaRead(u32* data, u32 bytesLeft, u32* bytesProcessed)
u32 TDA;
if( buff2end > 0 )
{
if (buff2end > 0) {
// second branch needs cleared:
// It starts at the beginning of memory and moves forward to buff2end
memcpy( &pMem[buff1size], GetMemPtr( 0 ), buff2end*2 );
memcpy(&pMem[buff1size], GetMemPtr(0), buff2end * 2);
TDA = (buff2end+0x20) & 0xfffff;
TDA = (buff2end + 0x20) & 0xfffff;
// Flag interrupt? If IRQA occurs between start and dest, flag it.
// Important: Test both core IRQ settings for either DMA!
// Note: Because this buffer wraps, we use || instead of &&
for( int i=0; i<2; i++ )
{
if( Cores[i].IRQEnable && (Cores[i].IRQA > TSA || Cores[i].IRQA <= TDA) )
{
for (int i = 0; i < 2; i++) {
if (Cores[i].IRQEnable && (Cores[i].IRQA > TSA || Cores[i].IRQA <= TDA)) {
SetIrqCall(i);
}
}
}
else
{
} else {
// Buffer doesn't wrap/overflow!
// Just set the TDA and check for an IRQ...
@ -502,10 +475,8 @@ s32 V_Core::NewDmaRead(u32* data, u32 bytesLeft, u32* bytesProcessed)
// Flag interrupt? If IRQA occurs between start and dest, flag it.
// Important: Test both core IRQ settings for either DMA!
for( int i=0; i<2; i++ )
{
if( Cores[i].IRQEnable && (Cores[i].IRQA > TSA) && (Cores[i].IRQA <= TDA) )
{
for (int i = 0; i < 2; i++) {
if (Cores[i].IRQEnable && (Cores[i].IRQA > TSA) && (Cores[i].IRQA <= TDA)) {
SetIrqCall(i);
}
}
@ -521,14 +492,13 @@ s32 V_Core::NewDmaRead(u32* data, u32 bytesLeft, u32* bytesProcessed)
return 0;
}
s32 V_Core::NewDmaWrite(u32* data, u32 bytesLeft, u32* bytesProcessed)
s32 V_Core::NewDmaWrite(u32 *data, u32 bytesLeft, u32 *bytesProcessed)
{
#ifdef ENABLE_NEW_IOPDMA_SPU2
bool DmaStarting = !DmaStarted;
DmaStarted = true;
if(bytesLeft<2)
{
if (bytesLeft < 2) {
// execute interrupt code early
NewDmaInterrupt();
@ -536,94 +506,83 @@ s32 V_Core::NewDmaWrite(u32* data, u32 bytesLeft, u32* bytesProcessed)
return 0;
}
if( IsDevBuild )
{
if (IsDevBuild) {
DebugCores[Index].lastsize = bytesLeft;
DebugCores[Index].dmaFlag = 1;
}
TSA &= 0xfffff;
bool adma_enable = ((AutoDMACtrl&(Index+1))==(Index+1));
bool adma_enable = ((AutoDMACtrl & (Index + 1)) == (Index + 1));
if(adma_enable)
{
TSA&=0x1fff;
if (adma_enable) {
TSA &= 0x1fff;
if(MsgAutoDMA() && DmaStarting) ConLog("* SPU2-X: DMA%c AutoDMA Transfer of %d bytes to %x (%02x %x %04x).\n",
GetDmaIndexChar(), bytesLeft<<1, TSA, DMABits, AutoDMACtrl, (~Regs.ATTR)&0x7fff);
if (MsgAutoDMA() && DmaStarting)
ConLog("* SPU2-X: DMA%c AutoDMA Transfer of %d bytes to %x (%02x %x %04x).\n",
GetDmaIndexChar(), bytesLeft << 1, TSA, DMABits, AutoDMACtrl, (~Regs.ATTR) & 0x7fff);
u32 processed = 0;
while((AutoDmaFree>0)&&(bytesLeft>=0x400))
{
while ((AutoDmaFree > 0) && (bytesLeft >= 0x400)) {
// copy block
LogAutoDMA( Index ? ADMA7LogFile : ADMA4LogFile );
LogAutoDMA(Index ? ADMA7LogFile : ADMA4LogFile);
// HACKFIX!! DMAPtr can be invalid after a savestate load, so the savestate just forces it
// to NULL and we ignore it here. (used to work in old VM editions of PCSX2 with fixed
// addressing, but new PCSX2s have dynamic memory addressing).
s16* mptr = (s16*)data;
s16 *mptr = (s16 *)data;
if(false)//(mode)
if (false) //(mode)
{
//memcpy((ADMATempBuffer+(InputPosWrite<<1)),mptr,0x400);
memcpy(GetMemPtr(0x2000+(Index<<10)+InputPosWrite),mptr,0x400);
mptr+=0x200;
memcpy(GetMemPtr(0x2000 + (Index << 10) + InputPosWrite), mptr, 0x400);
mptr += 0x200;
// Flag interrupt? If IRQA occurs between start and dest, flag it.
// Important: Test both core IRQ settings for either DMA!
u32 dummyTSA = 0x2000+(Index<<10)+InputPosWrite;
u32 dummyTDA = 0x2000+(Index<<10)+InputPosWrite+0x200;
u32 dummyTSA = 0x2000 + (Index << 10) + InputPosWrite;
u32 dummyTDA = 0x2000 + (Index << 10) + InputPosWrite + 0x200;
for( int i=0; i<2; i++ )
{
if( Cores[i].IRQEnable && (Cores[i].IRQA > dummyTSA) && (Cores[i].IRQA <= dummyTDA) )
{
for (int i = 0; i < 2; i++) {
if (Cores[i].IRQEnable && (Cores[i].IRQA > dummyTSA) && (Cores[i].IRQA <= dummyTDA)) {
SetIrqCall(i);
}
}
}
else
{
} else {
//memcpy((ADMATempBuffer+InputPosWrite),mptr,0x200);
memcpy(GetMemPtr(0x2000+(Index<<10)+InputPosWrite),mptr,0x200);
mptr+=0x100;
memcpy(GetMemPtr(0x2000 + (Index << 10) + InputPosWrite), mptr, 0x200);
mptr += 0x100;
// Flag interrupt? If IRQA occurs between start and dest, flag it.
// Important: Test both core IRQ settings for either DMA!
u32 dummyTSA = 0x2000+(Index<<10)+InputPosWrite;
u32 dummyTDA = 0x2000+(Index<<10)+InputPosWrite+0x100;
u32 dummyTSA = 0x2000 + (Index << 10) + InputPosWrite;
u32 dummyTDA = 0x2000 + (Index << 10) + InputPosWrite + 0x100;
for( int i=0; i<2; i++ )
{
if( Cores[i].IRQEnable && (Cores[i].IRQA > dummyTSA) && (Cores[i].IRQA <= dummyTDA) )
{
for (int i = 0; i < 2; i++) {
if (Cores[i].IRQEnable && (Cores[i].IRQA > dummyTSA) && (Cores[i].IRQA <= dummyTDA)) {
SetIrqCall(i);
}
}
//memcpy((ADMATempBuffer+InputPosWrite+0x200),mptr,0x200);
memcpy(GetMemPtr(0x2200+(Index<<10)+InputPosWrite),mptr,0x200);
mptr+=0x100;
memcpy(GetMemPtr(0x2200 + (Index << 10) + InputPosWrite), mptr, 0x200);
mptr += 0x100;
// Flag interrupt? If IRQA occurs between start and dest, flag it.
// Important: Test both core IRQ settings for either DMA!
dummyTSA = 0x2200+(Index<<10)+InputPosWrite;
dummyTDA = 0x2200+(Index<<10)+InputPosWrite+0x100;
dummyTSA = 0x2200 + (Index << 10) + InputPosWrite;
dummyTDA = 0x2200 + (Index << 10) + InputPosWrite + 0x100;
for( int i=0; i<2; i++ )
{
if( Cores[i].IRQEnable && (Cores[i].IRQA > dummyTSA) && (Cores[i].IRQA <= dummyTDA) )
{
for (int i = 0; i < 2; i++) {
if (Cores[i].IRQEnable && (Cores[i].IRQA > dummyTSA) && (Cores[i].IRQA <= dummyTDA)) {
SetIrqCall(i);
}
}
}
// See ReadInput at mixer.cpp for explanation on the commented out lines
//
@ -634,27 +593,23 @@ s32 V_Core::NewDmaWrite(u32* data, u32 bytesLeft, u32* bytesProcessed)
bytesLeft -= 0x400;
}
if(processed==0)
{
if (processed == 0) {
*bytesProcessed = 0;
return 768*15; // pause a bit
}
else
{
return 768 * 15; // pause a bit
} else {
*bytesProcessed = processed;
return 0; // auto pause
}
}
else
{
if(MsgDMA() && DmaStarting) ConLog("* SPU2-X: DMA%c Transfer of %d bytes to %x (%02x %x %04x).\n",
GetDmaIndexChar(),bytesLeft,TSA,DMABits,AutoDMACtrl,(~Regs.ATTR)&0x7fff);
} else {
if (MsgDMA() && DmaStarting)
ConLog("* SPU2-X: DMA%c Transfer of %d bytes to %x (%02x %x %04x).\n",
GetDmaIndexChar(), bytesLeft, TSA, DMABits, AutoDMACtrl, (~Regs.ATTR) & 0x7fff);
if(bytesLeft> 2048)
if (bytesLeft > 2048)
bytesLeft = 2048;
// TODO: Sliced transfers?
PlainDMAWrite((u16*)data,bytesLeft/2);
PlainDMAWrite((u16 *)data, bytesLeft / 2);
}
Regs.STATX &= ~0x80;
Regs.STATX |= 0x400;
@ -667,7 +622,7 @@ s32 V_Core::NewDmaWrite(u32* data, u32 bytesLeft, u32* bytesProcessed)
void V_Core::NewDmaInterrupt()
{
#ifdef ENABLE_NEW_IOPDMA_SPU2
FileLog("[%10d] SPU2 interruptDMA4\n",Cycles);
FileLog("[%10d] SPU2 interruptDMA4\n", Cycles);
Regs.STATX |= 0x80;
Regs.STATX &= ~0x400;
//Regs.ATTR &= ~0x30;

View File

@ -21,29 +21,29 @@
#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
@ -55,27 +55,27 @@ 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
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 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
@ -85,29 +85,29 @@ void ProcessDplIISample32( const StereoOut32& src, Stereo51Out32DplII * s)
float PL = std::abs(L);
float PR = std::abs(R);
AccL += (PL-AccL)*0.1f;
AccR += (PR-AccR)*0.1f;
AccL += (PL - AccL) * 0.1f;
AccR += (PR - AccR) * 0.1f;
// Calculate power balance
float Balance = (AccR-AccL); // -1 .. 1
float Balance = (AccR - AccL); // -1 .. 1
// 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 Rearness = 1 - Frontness; // And the other way around
// Equalize the power levels for L/R
float B = std::min(0.9f,std::max(-0.9f,Balance));
float B = std::min(0.9f, std::max(-0.9f, Balance));
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 VL = L / (1 - B); // if B>0, it means R>L, so increase L, else decrease L
float VR = R / (1 + B); // vice-versa
// 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 SL = (VR*1.73f - VL*1.22f) * RearScale * Rearness;
float SR = (VR*1.22f - VL*1.73f) * RearScale * Rearness;
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
// Adjust the volume of the front speakers based on what we calculated above
@ -116,15 +116,15 @@ void ProcessDplIISample32( const StereoOut32& src, Stereo51Out32DplII * s)
s32 CX = (s32)(C * AddCLR);
s->Left = (s32)(L * GainL ) + CX;
s->Right = (s32)(R * GainR ) + CX;
s->Center = (s32)(C * GainC );
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 );
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);
@ -137,30 +137,30 @@ void ProcessDplIISample16( const StereoOut32& src, Stereo51Out16DplII * s)
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
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->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 );
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);

View File

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

View File

@ -15,7 +15,7 @@
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Dialogs.h"
#include "Dialogs.h"
void AboutBox()
{

View File

@ -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__
@ -26,7 +26,7 @@
#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
@ -46,36 +46,34 @@ protected:
void _InternalCallback()
{
snd_pcm_sframes_t avail;
fprintf(stderr,"* SPU2-X:Iz in your internal callback.\n");
fprintf(stderr, "* SPU2-X:Iz in your internal callback.\n");
avail = snd_pcm_avail_update( handle );
while (avail >= (int)period_time )
{
avail = snd_pcm_avail_update(handle);
while (avail >= (int)period_time) {
StereoOut16 buff[PacketsPerBuffer * SndOutPacketSize];
StereoOut16* p1 = buff;
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 );
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)
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 );
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 != 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");
if (data->handle != snd_async_handler_get_pcm(pcm_call)) {
fprintf(stderr, "* SPU2-X: Failed to handle sound.\n");
return;
}
@ -83,7 +81,6 @@ protected:
}
public:
s32 Init()
{
//fprintf(stderr,"* SPU2-X: Initing Alsa\n");
@ -99,22 +96,20 @@ public:
// 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);
period_time = (SndOutPacketSize * 1000) / (SampleRate / 1000);
buffer_time = period_time * NumBuffers;
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));
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));
if (err < 0) {
fprintf(stderr, "Can't set blocking mode: %s\n", snd_strerror(err));
return -1;
}
@ -122,78 +117,70 @@ public:
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));
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));
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));
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));
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));
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));
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));
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));
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));
if (err < 0) {
fprintf(stderr, "Unable to get status: %s\n", snd_strerror(err));
return -1;
}
// 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));
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:
@ -206,7 +193,8 @@ public:
void Close()
{
//fprintf(stderr,"* SPU2-X: Closing Alsa\n");
if(handle == NULL) return;
if (handle == NULL)
return;
snd_pcm_drop(handle);
snd_pcm_close(handle);
@ -226,24 +214,24 @@ public:
int GetEmptySampleCount()
{
if(handle == NULL)
{
fprintf(stderr,"Handle is NULL!\n");
if (handle == NULL) {
fprintf(stderr, "Handle is NULL!\n");
return 0;
}
// Returns the amount of free buffer space, in samples.
int l = snd_pcm_avail_update(handle);
if( l < 0 ) return 0;
if (l < 0)
return 0;
return (l / 1000) * (SampleRate / 1000);
}
const wchar_t* GetIdent() const
const wchar_t *GetIdent() const
{
return L"Alsa";
}
const wchar_t* GetLongName() const
const wchar_t *GetLongName() const
{
return L"Alsa";
}

View File

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

View File

@ -15,56 +15,57 @@
* 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)
{
void setIni(const wchar_t *Section)
{
initIni();
spuConfig->SetPath(wxsFormat(L"/%s", Section));
}
}
void CfgSetSettingsDir(const char* dir)
void CfgSetSettingsDir(const char *dir)
{
FileLog("CfgSetSettingsDir(%s)\n", dir);
path = wxString::FromAscii(dir) + L"/spu2-x.ini";
pathSet = true;
}
void CfgWriteBool(const wchar_t* Section, const wchar_t* Name, bool Value)
void CfgWriteBool(const wchar_t *Section, const wchar_t *Name, bool Value)
{
setIni(Section);
spuConfig->Write(Name, Value);
}
void CfgWriteInt(const wchar_t* Section, const wchar_t* Name, int Value)
void CfgWriteInt(const wchar_t *Section, const wchar_t *Name, int Value)
{
setIni(Section);
spuConfig->Write(Name, Value);
}
void CfgWriteFloat(const wchar_t* Section, const wchar_t* Name, float Value)
void CfgWriteFloat(const wchar_t *Section, const wchar_t *Name, float Value)
{
setIni(Section);
spuConfig->Write(Name, (double)Value);
}
void CfgWriteStr(const wchar_t* Section, const wchar_t* Name, const wxString& Data)
void CfgWriteStr(const wchar_t *Section, const wchar_t *Name, const wxString &Data)
{
setIni(Section);
spuConfig->Write(Name, Data);
}
bool CfgReadBool(const wchar_t *Section,const wchar_t* Name, bool Default)
bool CfgReadBool(const wchar_t *Section, const wchar_t *Name, bool Default)
{
bool ret;
@ -74,7 +75,7 @@ bool CfgReadBool(const wchar_t *Section,const wchar_t* Name, bool Default)
return ret;
}
int CfgReadInt(const wchar_t* Section, const wchar_t* Name,int Default)
int CfgReadInt(const wchar_t *Section, const wchar_t *Name, int Default)
{
int ret;
@ -84,7 +85,7 @@ int CfgReadInt(const wchar_t* Section, const wchar_t* Name,int Default)
return ret;
}
float CfgReadFloat(const wchar_t* Section, const wchar_t* Name, float Default)
float CfgReadFloat(const wchar_t *Section, const wchar_t *Name, float Default)
{
double ret;
@ -94,13 +95,13 @@ float CfgReadFloat(const wchar_t* Section, const wchar_t* Name, float Default)
return (float)ret;
}
void CfgReadStr(const wchar_t* Section, const wchar_t* Name, wchar_t* Data, int DataSize, 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);
wcscpy(Data, spuConfig->Read(Name, Default).wc_str());
}
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, wxString &Data, const wchar_t *Default)
{
setIni(Section);
Data = spuConfig->Read(Name, Default);

View File

@ -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.
@ -86,17 +86,17 @@ 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)
{
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;
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);
@ -119,25 +119,29 @@ void ReadSettings()
wxString temp;
CfgReadStr( L"OUTPUT", L"Output_Module", temp, PortaudioOut->GetIdent() );
OutputModule = FindOutputModuleById( temp.c_str() );// find the driver index of this module
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" );
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;
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" );
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" );
CfgReadStr(L"SDL", L"HostApi", temp, L"pulseaudio");
SdlOutputAPI = -1;
#if SDL_MAJOR_VERSION >= 2
// YES It sucks ...
@ -148,8 +152,8 @@ void ReadSettings()
#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();
#ifdef __linux__
@ -161,7 +165,7 @@ void ReadSettings()
// Sanity Checks
// -------------
Clampify( SndOutLatencyMS, LATENCY_MIN, LATENCY_MAX );
Clampify(SndOutLatencyMS, LATENCY_MIN, LATENCY_MAX);
WriteSettings();
spuConfig->Flush();
@ -171,16 +175,15 @@ void ReadSettings()
void WriteSettings()
{
if (!pathSet)
{
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);
@ -192,9 +195,9 @@ void WriteSettings()
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);
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();
@ -241,7 +244,7 @@ void DisplayDialog()
GtkWidget *advanced_button;
/* Create the widgets */
dialog = gtk_dialog_new_with_buttons (
dialog = gtk_dialog_new_with_buttons(
"SPU2-X Config",
NULL, /* parent window*/
(GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
@ -249,8 +252,8 @@ void DisplayDialog()
"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)");
@ -264,8 +267,8 @@ void DisplayDialog()
debug_check = gtk_check_button_new_with_label("Enable Debug Options");
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,8 +277,8 @@ 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
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(api_box), "0 - ALSA (recommended)");
@ -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,8 +307,8 @@ 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.)");
@ -314,16 +317,16 @@ void DisplayDialog()
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);
@ -354,16 +357,15 @@ void DisplayDialog()
//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)
{
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)
@ -378,16 +380,26 @@ void DisplayDialog()
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
}
@ -406,12 +418,11 @@ void DisplayDialog()
SynchMode = gtk_combo_box_get_active(GTK_COMBO_BOX(sync_box));
}
gtk_widget_destroy (dialog);
gtk_widget_destroy(dialog);
}
#else
void DisplayDialog()
{
}
#endif

View File

@ -89,9 +89,9 @@ extern int SynchMode;
namespace SoundtouchCfg
{
void ReadSettings();
void WriteSettings();
void DisplayDialog();
void ReadSettings();
void WriteSettings();
void DisplayDialog();
};
void ReadSettings();

View File

@ -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,30 +53,31 @@ 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()
{
@ -92,66 +93,65 @@ static void set_default_filenames()
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();
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);
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__
@ -172,7 +172,7 @@ void DisplayDialog()
ReadSettings();
// Create the widgets
dialog = gtk_dialog_new_with_buttons (
dialog = gtk_dialog_new_with_buttons(
"Spu2-X Config",
NULL, // parent window
(GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
@ -181,8 +181,8 @@ void DisplayDialog()
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
@ -212,8 +212,8 @@ 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);
@ -230,8 +230,8 @@ void DisplayDialog()
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);
@ -248,23 +248,22 @@ void DisplayDialog()
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)
{
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));
@ -282,14 +281,13 @@ void DisplayDialog()
_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
}

View File

@ -26,66 +26,66 @@
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();
}
}
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()
{
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()
{
void DisplayDialog()
{
int return_value;
GtkWidget *dialog, *main_label, *main_frame, *main_box;
GtkWidget *default_button;
@ -93,7 +93,7 @@ namespace SoundtouchCfg
ReadSettings();
/* Create the widgets */
dialog = gtk_dialog_new_with_buttons (
dialog = gtk_dialog_new_with_buttons(
"Advanced Settings",
NULL, /* parent window*/
(GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
@ -101,8 +101,8 @@ namespace SoundtouchCfg
"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");
@ -131,45 +131,42 @@ namespace SoundtouchCfg
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_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_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_frame);
gtk_widget_show_all(dialog);
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));;
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);
gtk_widget_destroy(dialog);
WriteSettings();
}
}
#else
void DisplayDialog()
{
void DisplayDialog()
{
}
}
void restore_defaults()
{
}
void restore_defaults()
{
}
#endif
}

View File

@ -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,
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);
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
}
void SysMessage(const wchar_t *fmt, ...)
{
va_list list;
va_start(list,fmt);
va_start(list, fmt);
wxString msg;
msg.PrintfV( fmt, list );
msg.PrintfV(fmt, list);
va_end(list);
GtkWidget *dialog;
dialog = gtk_message_dialog_new (NULL,
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);
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;
}

View File

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

View File

@ -20,8 +20,8 @@
#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;
@ -30,65 +30,65 @@ LowPassFilter<FloatType>::LowPassFilter( FloatType freq, FloatType srate )
// 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;
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;
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[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[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;
}
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);
}

View File

@ -17,28 +17,28 @@
#pragma once
template< typename FloatType >
template <typename FloatType>
struct LowPassFilter
{
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;
LowPassFilter32( float freq, float srate );
float sample( float inval );
LowPassFilter32(float freq, float srate);
float sample(float inval);
};
struct LowPassFilter64
{
LowPassFilter<double> impl_lpf;
LowPassFilter64( double freq, double srate );
double sample( double inval );
LowPassFilter64(double freq, double srate);
double sample(double inval);
};

View File

@ -25,13 +25,12 @@
void ADMAOutLogWrite(void *lpData, u32 ulSize);
static const s32 tbl_XA_Factor[16][2] =
{
{ 0, 0 },
{ 60, 0 },
{ 115, -52 },
{ 98, -55 },
{ 122, -60 }
};
{
{0, 0},
{60, 0},
{115, -52},
{98, -55},
{122, -60}};
// Performs a 64-bit multiplication between two values and returns the
@ -47,14 +46,14 @@ static const s32 tbl_XA_Factor[16][2] =
// caller to extend the inputs so that they make use of all 32 bits of
// precision.
//
static __forceinline s32 MulShr32( s32 srcval, s32 mulval )
static __forceinline s32 MulShr32(s32 srcval, s32 mulval)
{
return (s64)srcval * mulval >> 32;
}
__forceinline s32 clamp_mix( s32 x, u8 bitshift )
__forceinline s32 clamp_mix(s32 x, u8 bitshift)
{
return GetClamped( x, -0x8000<<bitshift, 0x7fff<<bitshift );
return GetClamped(x, -0x8000 << bitshift, 0x7fff << bitshift);
}
#if _MSC_VER
@ -66,42 +65,41 @@ __forceinline
// inline. Gcc 4.5 has the experimental options -flto, -fwhopr and -fwhole-program to
// do it but it still experimental...
#endif
StereoOut32 clamp_mix( const StereoOut32& sample, u8 bitshift )
StereoOut32
clamp_mix(const StereoOut32 &sample, u8 bitshift)
{
// We should clampify between -0x8000 and 0x7fff, however some audio output
// modules or sound drivers could (will :p) overshoot with that. So giving it a small safety.
return StereoOut32(
GetClamped( sample.Left, -0x7f00<<bitshift, 0x7f00<<bitshift ),
GetClamped( sample.Right, -0x7f00<<bitshift, 0x7f00<<bitshift )
);
GetClamped(sample.Left, -0x7f00 << bitshift, 0x7f00 << bitshift),
GetClamped(sample.Right, -0x7f00 << bitshift, 0x7f00 << bitshift));
}
static void __forceinline XA_decode_block(s16* buffer, const s16* block, s32& prev1, s32& prev2)
static void __forceinline XA_decode_block(s16 *buffer, const s16 *block, s32 &prev1, s32 &prev2)
{
const s32 header = *block;
const s32 shift = (header&0xF)+16;
const s32 shift = (header & 0xF) + 16;
const int id = header >> 4 & 0xF;
if (id > 4 && MsgToConsole())
ConLog("* SPU2-X: Unknown ADPCM coefficients table id %d\n", id);
const s32 pred1 = tbl_XA_Factor[id][0];
const s32 pred2 = tbl_XA_Factor[id][1];
const s8* blockbytes = (s8*)&block[1];
const s8* blockend = &blockbytes[13];
const s8 *blockbytes = (s8 *)&block[1];
const s8 *blockend = &blockbytes[13];
for(; blockbytes<=blockend; ++blockbytes)
{
s32 data = ((*blockbytes)<<28) & 0xF0000000;
s32 pcm = (data >> shift) + (((pred1*prev1)+(pred2*prev2)+32) >> 6);
for (; blockbytes <= blockend; ++blockbytes) {
s32 data = ((*blockbytes) << 28) & 0xF0000000;
s32 pcm = (data >> shift) + (((pred1 * prev1) + (pred2 * prev2) + 32) >> 6);
Clampify( pcm, -0x8000, 0x7fff );
Clampify(pcm, -0x8000, 0x7fff);
*(buffer++) = pcm;
data = ((*blockbytes)<<24) & 0xF0000000;
s32 pcm2 = (data >> shift) + (((pred1*pcm)+(pred2*prev1)+32) >> 6);
data = ((*blockbytes) << 24) & 0xF0000000;
s32 pcm2 = (data >> shift) + (((pred1 * pcm) + (pred2 * prev1) + 32) >> 6);
Clampify( pcm2, -0x8000, 0x7fff );
Clampify(pcm2, -0x8000, 0x7fff);
*(buffer++) = pcm2;
prev2 = pcm;
@ -109,17 +107,15 @@ static void __forceinline XA_decode_block(s16* buffer, const s16* block, s32& pr
}
}
static void __forceinline IncrementNextA(V_Core& thiscore, uint voiceidx)
static void __forceinline IncrementNextA(V_Core &thiscore, uint voiceidx)
{
V_Voice &vc(thiscore.Voices[voiceidx]);
// Important! Both cores signal IRQ when an address is read, regardless of
// which core actually reads the address.
for( int i=0; i<2; i++ )
{
if( Cores[i].IRQEnable && (vc.NextA==Cores[i].IRQA ) )
{
for (int i = 0; i < 2; i++) {
if (Cores[i].IRQEnable && (vc.NextA == Cores[i].IRQA)) {
//if( IsDevBuild )
// ConLog(" * SPU2 Core %d: IRQ Requested (IRQA (%05X) passed; voice %d).\n", i, Cores[i].IRQA, thiscore.Index * 24 + voiceidx);
@ -128,7 +124,7 @@ static void __forceinline IncrementNextA(V_Core& thiscore, uint voiceidx)
}
vc.NextA++;
vc.NextA&=0xFFFFF;
vc.NextA &= 0xFFFFF;
}
// decoded pcm data, used to cache the decoded data so that it needn't be decoded
@ -145,61 +141,55 @@ int g_counter_cache_ignores = 0;
// (the documented requirement that every block in a loop has the LOOP bit set is nonsense according to tests)
// LOOP/START sets LSA to NAX unless LSA was written manually since sound generation started
// (see LoopMode, the method by which this is achieved on the real SPU2 is unknown)
#define XAFLAG_LOOP_END (1ul<<0)
#define XAFLAG_LOOP (1ul<<1)
#define XAFLAG_LOOP_START (1ul<<2)
#define XAFLAG_LOOP_END (1ul << 0)
#define XAFLAG_LOOP (1ul << 1)
#define XAFLAG_LOOP_START (1ul << 2)
static __forceinline s32 GetNextDataBuffered( V_Core& thiscore, uint voiceidx )
static __forceinline s32 GetNextDataBuffered(V_Core &thiscore, uint voiceidx)
{
V_Voice& vc( thiscore.Voices[voiceidx] );
V_Voice &vc(thiscore.Voices[voiceidx]);
if( (vc.SCurrent&3) == 0 )
{
IncrementNextA( thiscore, voiceidx );
if ((vc.SCurrent & 3) == 0) {
IncrementNextA(thiscore, voiceidx);
if ((vc.NextA & 7) == 0) // vc.SCurrent == 24 equivalent
{
if(vc.LoopFlags & XAFLAG_LOOP_END)
{
if (vc.LoopFlags & XAFLAG_LOOP_END) {
thiscore.Regs.ENDX |= (1 << voiceidx);
vc.NextA = vc.LoopStartA | 1;
if (!(vc.LoopFlags & XAFLAG_LOOP))
{
if (!(vc.LoopFlags & XAFLAG_LOOP)) {
vc.Stop();
if( IsDevBuild )
{
if(MsgVoiceOff()) ConLog("* SPU2-X: Voice Off by EndPoint: %d \n", voiceidx);
if (IsDevBuild) {
if (MsgVoiceOff())
ConLog("* SPU2-X: Voice Off by EndPoint: %d \n", voiceidx);
}
}
}
else
} else
vc.NextA++; // no, don't IncrementNextA here. We haven't read the header yet.
}
}
if( vc.SCurrent == 28 )
{
if (vc.SCurrent == 28) {
vc.SCurrent = 0;
// We'll need the loop flags and buffer pointers regardless of cache status:
for (int i=0; i<2; i++)
for (int i = 0; i < 2; i++)
if (Cores[i].IRQEnable && Cores[i].IRQA == (vc.NextA & 0xFFFF8))
SetIrqCall(i);
s16* memptr = GetMemPtr(vc.NextA & 0xFFFF8);
s16 *memptr = GetMemPtr(vc.NextA & 0xFFFF8);
vc.LoopFlags = *memptr >> 8; // grab loop flags from the upper byte.
if( (vc.LoopFlags & XAFLAG_LOOP_START) && !vc.LoopMode )
if ((vc.LoopFlags & XAFLAG_LOOP_START) && !vc.LoopMode)
vc.LoopStartA = vc.NextA & 0xFFFF8;
const int cacheIdx = vc.NextA / pcm_WordsPerBlock;
PcmCacheEntry& cacheLine = pcm_cache_data[cacheIdx];
PcmCacheEntry &cacheLine = pcm_cache_data[cacheIdx];
vc.SBuffer = cacheLine.Sampledata;
if( cacheLine.Validated )
{
if (cacheLine.Validated) {
// Cached block! Read from the cache directly.
// Make sure to propagate the prev1/prev2 ADPCM:
@ -208,54 +198,48 @@ static __forceinline s32 GetNextDataBuffered( V_Core& thiscore, uint voiceidx )
//ConLog( "* SPU2-X: Cache Hit! NextA=0x%x, cacheIdx=0x%x\n", vc.NextA, cacheIdx );
if( IsDevBuild )
if (IsDevBuild)
g_counter_cache_hits++;
}
else
{
} else {
// Only flag the cache if it's a non-dynamic memory range.
if( vc.NextA >= SPU2_DYN_MEMLINE )
if (vc.NextA >= SPU2_DYN_MEMLINE)
cacheLine.Validated = true;
if( IsDevBuild )
{
if( vc.NextA < SPU2_DYN_MEMLINE )
if (IsDevBuild) {
if (vc.NextA < SPU2_DYN_MEMLINE)
g_counter_cache_ignores++;
else
g_counter_cache_misses++;
}
XA_decode_block( vc.SBuffer, memptr, vc.Prev1, vc.Prev2 );
XA_decode_block(vc.SBuffer, memptr, vc.Prev1, vc.Prev2);
}
}
return vc.SBuffer[vc.SCurrent++];
}
static __forceinline void GetNextDataDummy(V_Core& thiscore, uint voiceidx)
static __forceinline void GetNextDataDummy(V_Core &thiscore, uint voiceidx)
{
V_Voice& vc( thiscore.Voices[voiceidx] );
V_Voice &vc(thiscore.Voices[voiceidx]);
IncrementNextA( thiscore, voiceidx );
IncrementNextA(thiscore, voiceidx);
if ((vc.NextA & 7) == 0) // vc.SCurrent == 24 equivalent
{
if(vc.LoopFlags & XAFLAG_LOOP_END)
{
if (vc.LoopFlags & XAFLAG_LOOP_END) {
thiscore.Regs.ENDX |= (1 << voiceidx);
vc.NextA = vc.LoopStartA | 1;
}
else
} else
vc.NextA++; // no, don't IncrementNextA here. We haven't read the header yet.
}
if (vc.SCurrent == 28)
{
for (int i=0; i<2; i++)
if (vc.SCurrent == 28) {
for (int i = 0; i < 2; i++)
if (Cores[i].IRQEnable && Cores[i].IRQA == (vc.NextA & 0xFFFF8))
SetIrqCall(i);
vc.LoopFlags = *GetMemPtr(vc.NextA&0xFFFF8) >> 8; // grab loop flags from the upper byte.
vc.LoopFlags = *GetMemPtr(vc.NextA & 0xFFFF8) >> 8; // grab loop flags from the upper byte.
if ((vc.LoopFlags & XAFLAG_LOOP_START) && !vc.LoopMode)
vc.LoopStartA = vc.NextA & 0xFFFF8;
@ -275,9 +259,9 @@ static s32 __forceinline GetNoiseValues()
static s32 Seed = 0x41595321;
s32 retval = 0x8000;
if( Seed&0x100 )
retval = (Seed&0xff) << 8;
else if( Seed&0xffff )
if (Seed & 0x100)
retval = (Seed & 0xff) << 8;
else if (Seed & 0xffff)
retval = 0x7fff;
s32 x = _rotr(Seed, 0x5);
@ -299,71 +283,66 @@ static s32 __forceinline GetNoiseValues()
static __forceinline s32 ApplyVolume(s32 data, s32 volume)
{
//return (volume * data) >> 15;
return MulShr32( data<<1, volume );
return MulShr32(data << 1, volume);
}
static __forceinline StereoOut32 ApplyVolume( const StereoOut32& data, const V_VolumeLR& volume )
static __forceinline StereoOut32 ApplyVolume(const StereoOut32 &data, const V_VolumeLR &volume)
{
return StereoOut32(
ApplyVolume( data.Left, volume.Left ),
ApplyVolume( data.Right, volume.Right )
);
ApplyVolume(data.Left, volume.Left),
ApplyVolume(data.Right, volume.Right));
}
static __forceinline StereoOut32 ApplyVolume( const StereoOut32& data, const V_VolumeSlideLR& volume )
static __forceinline StereoOut32 ApplyVolume(const StereoOut32 &data, const V_VolumeSlideLR &volume)
{
return StereoOut32(
ApplyVolume( data.Left, volume.Left.Value ),
ApplyVolume( data.Right, volume.Right.Value )
);
ApplyVolume(data.Left, volume.Left.Value),
ApplyVolume(data.Right, volume.Right.Value));
}
static void __forceinline UpdatePitch( uint coreidx, uint voiceidx )
static void __forceinline UpdatePitch(uint coreidx, uint voiceidx)
{
V_Voice& vc( Cores[coreidx].Voices[voiceidx] );
V_Voice &vc(Cores[coreidx].Voices[voiceidx]);
s32 pitch;
// [Air] : re-ordered comparisons: Modulated is much more likely to be zero than voice,
// and so the way it was before it's have to check both voice and modulated values
// most of the time. Now it'll just check Modulated and short-circuit past the voice
// check (not that it amounts to much, but eh every little bit helps).
if( (vc.Modulated==0) || (voiceidx==0) )
if ((vc.Modulated == 0) || (voiceidx == 0))
pitch = vc.Pitch;
else
pitch = GetClamped((vc.Pitch*(32768 + Cores[coreidx].Voices[voiceidx-1].OutX))>>15, 0, 0x3fff);
pitch = GetClamped((vc.Pitch * (32768 + Cores[coreidx].Voices[voiceidx - 1].OutX)) >> 15, 0, 0x3fff);
vc.SP+=pitch;
vc.SP += pitch;
}
static __forceinline void CalculateADSR( V_Core& thiscore, uint voiceidx )
static __forceinline void CalculateADSR(V_Core &thiscore, uint voiceidx)
{
V_Voice& vc( thiscore.Voices[voiceidx] );
V_Voice &vc(thiscore.Voices[voiceidx]);
if( vc.ADSR.Phase==0 )
{
if (vc.ADSR.Phase == 0) {
vc.ADSR.Value = 0;
return;
}
if( !vc.ADSR.Calculate() )
{
if( IsDevBuild )
{
if(MsgVoiceOff()) ConLog("* SPU2-X: Voice Off by ADSR: %d \n", voiceidx);
if (!vc.ADSR.Calculate()) {
if (IsDevBuild) {
if (MsgVoiceOff())
ConLog("* SPU2-X: Voice Off by ADSR: %d \n", voiceidx);
}
vc.Stop();
}
pxAssume( vc.ADSR.Value >= 0 ); // ADSR should never be negative...
pxAssume(vc.ADSR.Value >= 0); // ADSR should never be negative...
}
/*
Tension: 65535 is high, 32768 is normal, 0 is low
*/
template<s32 i_tension>
__forceinline
static s32 HermiteInterpolate(
template <s32 i_tension>
__forceinline static s32 HermiteInterpolate(
s32 y0, // 16.0
s32 y1, // 16.0
s32 y2, // 16.0
@ -371,23 +350,22 @@ static s32 HermiteInterpolate(
s32 mu // 0.12
)
{
s32 m00 = ((y1-y0)*i_tension) >> 16; // 16.0
s32 m01 = ((y2-y1)*i_tension) >> 16; // 16.0
s32 m00 = ((y1 - y0) * i_tension) >> 16; // 16.0
s32 m01 = ((y2 - y1) * i_tension) >> 16; // 16.0
s32 m0 = m00 + m01;
s32 m10 = ((y2-y1)*i_tension) >> 16; // 16.0
s32 m11 = ((y3-y2)*i_tension) >> 16; // 16.0
s32 m10 = ((y2 - y1) * i_tension) >> 16; // 16.0
s32 m11 = ((y3 - y2) * i_tension) >> 16; // 16.0
s32 m1 = m10 + m11;
s32 val = (( 2*y1 + m0 + m1 - 2*y2) * mu) >> 12; // 16.0
val = ((val - 3*y1 - 2*m0 - m1 + 3*y2) * mu) >> 12; // 16.0
val = ((val + m0 ) * mu) >> 11; // 16.0
s32 val = ((2 * y1 + m0 + m1 - 2 * y2) * mu) >> 12; // 16.0
val = ((val - 3 * y1 - 2 * m0 - m1 + 3 * y2) * mu) >> 12; // 16.0
val = ((val + m0) * mu) >> 11; // 16.0
return(val + (y1<<1));
return (val + (y1 << 1));
}
__forceinline
static s32 CatmullRomInterpolate(
__forceinline static s32 CatmullRomInterpolate(
s32 y0, // 16.0
s32 y1, // 16.0
s32 y2, // 16.0
@ -400,20 +378,19 @@ static s32 CatmullRomInterpolate(
// (2*P0 - 5*P1 + 4*P2 - P3) * t2 +
// (-P0 + 3*P1- 3*P2 + P3) * t3)
s32 a3 = (- y0 + 3*y1 - 3*y2 + y3);
s32 a2 = ( 2*y0 - 5*y1 + 4*y2 - y3);
s32 a1 = (- y0 + y2 );
s32 a0 = ( 2*y1 );
s32 a3 = (-y0 + 3 * y1 - 3 * y2 + y3);
s32 a2 = (2 * y0 - 5 * y1 + 4 * y2 - y3);
s32 a1 = (-y0 + y2);
s32 a0 = (2 * y1);
s32 val = ((a3 ) * mu) >> 12;
s32 val = ((a3)*mu) >> 12;
val = ((a2 + val) * mu) >> 12;
val = ((a1 + val) * mu) >> 12;
return (a0 + val);
}
__forceinline
static s32 CubicInterpolate(
__forceinline static s32 CubicInterpolate(
s32 y0, // 16.0
s32 y1, // 16.0
s32 y2, // 16.0
@ -425,43 +402,45 @@ static s32 CubicInterpolate(
const s32 a1 = y0 - y1 - a0;
const s32 a2 = y2 - y0;
s32 val = (( a0) * mu) >> 12;
s32 val = ((a0)*mu) >> 12;
val = ((val + a1) * mu) >> 12;
val = ((val + a2) * mu) >> 11;
return(val + (y1<<1));
return (val + (y1 << 1));
}
// Returns a 16 bit result in Value.
// Uses standard template-style optimization techniques to statically generate five different
// versions of this function (one for each type of interpolation).
template< int InterpType >
static __forceinline s32 GetVoiceValues( V_Core& thiscore, uint voiceidx )
template <int InterpType>
static __forceinline s32 GetVoiceValues(V_Core &thiscore, uint voiceidx)
{
V_Voice& vc( thiscore.Voices[voiceidx] );
V_Voice &vc(thiscore.Voices[voiceidx]);
while( vc.SP > 0 )
{
if( InterpType >= 2 )
{
while (vc.SP > 0) {
if (InterpType >= 2) {
vc.PV4 = vc.PV3;
vc.PV3 = vc.PV2;
}
vc.PV2 = vc.PV1;
vc.PV1 = GetNextDataBuffered( thiscore, voiceidx );
vc.PV1 = GetNextDataBuffered(thiscore, voiceidx);
vc.SP -= 4096;
}
const s32 mu = vc.SP + 4096;
switch( InterpType )
{
case 0: return vc.PV1<<1;
case 1: return (vc.PV1<<1) - (( (vc.PV2 - vc.PV1) * vc.SP)>>11);
switch (InterpType) {
case 0:
return vc.PV1 << 1;
case 1:
return (vc.PV1 << 1) - (((vc.PV2 - vc.PV1) * vc.SP) >> 11);
case 2: return CubicInterpolate (vc.PV4, vc.PV3, vc.PV2, vc.PV1, mu);
case 3: return HermiteInterpolate<16384> (vc.PV4, vc.PV3, vc.PV2, vc.PV1, mu);
case 4: return CatmullRomInterpolate (vc.PV4, vc.PV3, vc.PV2, vc.PV1, mu);
case 2:
return CubicInterpolate(vc.PV4, vc.PV3, vc.PV2, vc.PV1, mu);
case 3:
return HermiteInterpolate<16384>(vc.PV4, vc.PV3, vc.PV2, vc.PV1, mu);
case 4:
return CatmullRomInterpolate(vc.PV4, vc.PV3, vc.PV2, vc.PV1, mu);
jNO_DEFAULT;
}
@ -472,9 +451,9 @@ static __forceinline s32 GetVoiceValues( V_Core& thiscore, uint voiceidx )
// Noise values need to be mixed without going through interpolation, since it
// can wreak havoc on the noise (causing muffling or popping). Not that this noise
// generator is accurate in its own right.. but eh, ah well :)
static __forceinline s32 GetNoiseValues( V_Core& thiscore, uint voiceidx )
static __forceinline s32 GetNoiseValues(V_Core &thiscore, uint voiceidx)
{
V_Voice& vc( thiscore.Voices[voiceidx] );
V_Voice &vc(thiscore.Voices[voiceidx]);
s32 retval = GetNoiseValues();
@ -486,7 +465,7 @@ static __forceinline s32 GetNoiseValues( V_Core& thiscore, uint voiceidx )
// GetNoiseValues can't set the phase zero on us unexpectedly
// like GetVoiceValues can. Better assert just in case though..
pxAssume( vc.ADSR.Phase != 0 );
pxAssume(vc.ADSR.Phase != 0);
return retval;
}
@ -498,33 +477,31 @@ static __forceinline s32 GetNoiseValues( V_Core& thiscore, uint voiceidx )
// writes a signed value to the SPU2 ram
// Performs no cache invalidation -- use only for dynamic memory ranges
// of the SPU2 (between 0x0000 and SPU2_DYN_MEMLINE)
static __forceinline void spu2M_WriteFast( u32 addr, s16 value )
static __forceinline void spu2M_WriteFast(u32 addr, s16 value)
{
// Fixes some of the oldest hangs in pcsx2's history! :p
for( int i=0; i<2; i++ )
{
if( Cores[i].IRQEnable && Cores[i].IRQA == addr )
{
for (int i = 0; i < 2; i++) {
if (Cores[i].IRQEnable && Cores[i].IRQA == addr) {
//printf("Core %d special write IRQ Called (IRQ passed). IRQA = %x\n",i,addr);
SetIrqCall(i);
}
}
// throw an assertion if the memory range is invalid:
// throw an assertion if the memory range is invalid:
#ifndef DEBUG_FAST
pxAssume( addr < SPU2_DYN_MEMLINE );
pxAssume(addr < SPU2_DYN_MEMLINE);
#endif
*GetMemPtr( addr ) = value;
*GetMemPtr(addr) = value;
}
static __forceinline StereoOut32 MixVoice( uint coreidx, uint voiceidx )
static __forceinline StereoOut32 MixVoice(uint coreidx, uint voiceidx)
{
V_Core& thiscore( Cores[coreidx] );
V_Voice& vc( thiscore.Voices[voiceidx] );
V_Core &thiscore(Cores[coreidx]);
V_Voice &vc(thiscore.Voices[voiceidx]);
// If this assertion fails, it mans SCurrent is being corrupted somewhere, or is not initialized
// properly. Invalid values in SCurrent will cause errant IRQs and corrupted audio.
pxAssertMsg( (vc.SCurrent <= 28) && (vc.SCurrent != 0), "Current sample should always range from 1->28" );
pxAssertMsg((vc.SCurrent <= 28) && (vc.SCurrent != 0), "Current sample should always range from 1->28");
// Most games don't use much volume slide effects. So only call the UpdateVolume
// methods when needed by checking the flag outside the method here...
@ -536,26 +513,33 @@ static __forceinline StereoOut32 MixVoice( uint coreidx, uint voiceidx )
// have to run through all the motions of updating the voice regardless of it's
// audible status. Otherwise IRQs might not trigger and emulation might fail.
if( vc.ADSR.Phase > 0 )
{
UpdatePitch( coreidx, voiceidx );
if (vc.ADSR.Phase > 0) {
UpdatePitch(coreidx, voiceidx);
s32 Value = 0;
if( vc.Noise )
Value = GetNoiseValues( thiscore, voiceidx );
else
{
if (vc.Noise)
Value = GetNoiseValues(thiscore, voiceidx);
else {
// Optimization : Forceinline'd Templated Dispatch Table. Any halfwit compiler will
// turn this into a clever jump dispatch table (no call/rets, no compares, uber-efficient!)
switch( Interpolation )
{
case 0: Value = GetVoiceValues<0>( thiscore, voiceidx ); break;
case 1: Value = GetVoiceValues<1>( thiscore, voiceidx ); break;
case 2: Value = GetVoiceValues<2>( thiscore, voiceidx ); break;
case 3: Value = GetVoiceValues<3>( thiscore, voiceidx ); break;
case 4: Value = GetVoiceValues<4>( thiscore, voiceidx ); break;
switch (Interpolation) {
case 0:
Value = GetVoiceValues<0>(thiscore, voiceidx);
break;
case 1:
Value = GetVoiceValues<1>(thiscore, voiceidx);
break;
case 2:
Value = GetVoiceValues<2>(thiscore, voiceidx);
break;
case 3:
Value = GetVoiceValues<3>(thiscore, voiceidx);
break;
case 4:
Value = GetVoiceValues<4>(thiscore, voiceidx);
break;
jNO_DEFAULT;
}
@ -568,39 +552,35 @@ static __forceinline StereoOut32 MixVoice( uint coreidx, uint voiceidx )
// one or two bits. Best result comes from no truncation at all, which is why we
// use a full 64-bit multiply/result here.
CalculateADSR( thiscore, voiceidx );
Value = MulShr32( Value, vc.ADSR.Value );
CalculateADSR(thiscore, voiceidx);
Value = MulShr32(Value, vc.ADSR.Value);
// Store Value for eventual modulation later
// Pseudonym's Crest calculation idea. Actually calculates a crest, unlike the old code which was just peak.
if(vc.PV1 < vc.NextCrest)
{
if (vc.PV1 < vc.NextCrest) {
vc.OutX = MulShr32(vc.NextCrest, vc.ADSR.Value);
vc.NextCrest = -0x8000;
}
if(vc.PV1 > vc.PV2)
{
if (vc.PV1 > vc.PV2) {
vc.NextCrest = vc.PV1;
}
if( IsDevBuild )
DebugCores[coreidx].Voices[voiceidx].displayPeak = std::max(DebugCores[coreidx].Voices[voiceidx].displayPeak,(s32)vc.OutX);
if (IsDevBuild)
DebugCores[coreidx].Voices[voiceidx].displayPeak = std::max(DebugCores[coreidx].Voices[voiceidx].displayPeak, (s32)vc.OutX);
// Write-back of raw voice data (post ADSR applied)
if (voiceidx==1) spu2M_WriteFast( ( (0==coreidx) ? 0x400 : 0xc00 ) + OutPos, vc.OutX );
else if (voiceidx==3) spu2M_WriteFast( ( (0==coreidx) ? 0x600 : 0xe00 ) + OutPos, vc.OutX );
if (voiceidx == 1)
spu2M_WriteFast(((0 == coreidx) ? 0x400 : 0xc00) + OutPos, vc.OutX);
else if (voiceidx == 3)
spu2M_WriteFast(((0 == coreidx) ? 0x600 : 0xe00) + OutPos, vc.OutX);
return ApplyVolume( StereoOut32( Value, Value ), vc.Volume );
}
else
{
return ApplyVolume(StereoOut32(Value, Value), vc.Volume);
} else {
// Continue processing voice, even if it's "off". Or else we miss interrupts! (Fatal Frame engine died because of this.)
if (NEVER_SKIP_VOICES
|| (*GetMemPtr(vc.NextA & 0xFFFF8) >> 8 & 3) != 3 || vc.LoopStartA != (vc.NextA & ~7) // not in a tight loop
if (NEVER_SKIP_VOICES || (*GetMemPtr(vc.NextA & 0xFFFF8) >> 8 & 3) != 3 || vc.LoopStartA != (vc.NextA & ~7) // not in a tight loop
|| (Cores[0].IRQEnable && (Cores[0].IRQA & ~7) == vc.LoopStartA) // or should be interrupting regularly
|| (Cores[1].IRQEnable && (Cores[1].IRQA & ~7) == vc.LoopStartA)
|| !(thiscore.Regs.ENDX & 1 << voiceidx)) // or isn't currently flagged as having passed the endpoint
|| (Cores[1].IRQEnable && (Cores[1].IRQA & ~7) == vc.LoopStartA) || !(thiscore.Regs.ENDX & 1 << voiceidx)) // or isn't currently flagged as having passed the endpoint
{
UpdatePitch(coreidx, voiceidx);
@ -609,22 +589,23 @@ static __forceinline StereoOut32 MixVoice( uint coreidx, uint voiceidx )
}
// Write-back of raw voice data (some zeros since the voice is "dead")
if (voiceidx==1) spu2M_WriteFast( ( (0==coreidx) ? 0x400 : 0xc00 ) + OutPos, 0 );
else if (voiceidx==3) spu2M_WriteFast( ( (0==coreidx) ? 0x600 : 0xe00 ) + OutPos, 0 );
if (voiceidx == 1)
spu2M_WriteFast(((0 == coreidx) ? 0x400 : 0xc00) + OutPos, 0);
else if (voiceidx == 3)
spu2M_WriteFast(((0 == coreidx) ? 0x600 : 0xe00) + OutPos, 0);
return StereoOut32( 0, 0 );
return StereoOut32(0, 0);
}
}
const VoiceMixSet VoiceMixSet::Empty( (StereoOut32()), (StereoOut32()) ); // Don't use SteroOut32::Empty because C++ doesn't make any dep/order checks on global initializers.
const VoiceMixSet VoiceMixSet::Empty((StereoOut32()), (StereoOut32())); // Don't use SteroOut32::Empty because C++ doesn't make any dep/order checks on global initializers.
static __forceinline void MixCoreVoices( VoiceMixSet& dest, const uint coreidx )
static __forceinline void MixCoreVoices(VoiceMixSet &dest, const uint coreidx)
{
V_Core& thiscore( Cores[coreidx] );
V_Core &thiscore(Cores[coreidx]);
for( uint voiceidx=0; voiceidx<V_Core::NumVoices; ++voiceidx )
{
StereoOut32 VVal( MixVoice( coreidx, voiceidx ) );
for (uint voiceidx = 0; voiceidx < V_Core::NumVoices; ++voiceidx) {
StereoOut32 VVal(MixVoice(coreidx, voiceidx));
// Note: Results from MixVoice are ranged at 16 bits.
@ -635,30 +616,29 @@ static __forceinline void MixCoreVoices( VoiceMixSet& dest, const uint coreidx )
}
}
StereoOut32 V_Core::Mix( const VoiceMixSet& inVoices, const StereoOut32& Input, const StereoOut32& Ext )
StereoOut32 V_Core::Mix(const VoiceMixSet &inVoices, const StereoOut32 &Input, const StereoOut32 &Ext)
{
MasterVol.Update();
// Saturate final result to standard 16 bit range.
const VoiceMixSet Voices( clamp_mix( inVoices.Dry ), clamp_mix( inVoices.Wet ) );
const VoiceMixSet Voices(clamp_mix(inVoices.Dry), clamp_mix(inVoices.Wet));
// Write Mixed results To Output Area
spu2M_WriteFast( ( (0==Index) ? 0x1000 : 0x1800 ) + OutPos, Voices.Dry.Left );
spu2M_WriteFast( ( (0==Index) ? 0x1200 : 0x1A00 ) + OutPos, Voices.Dry.Right );
spu2M_WriteFast( ( (0==Index) ? 0x1400 : 0x1C00 ) + OutPos, Voices.Wet.Left );
spu2M_WriteFast( ( (0==Index) ? 0x1600 : 0x1E00 ) + OutPos, Voices.Wet.Right );
spu2M_WriteFast(((0 == Index) ? 0x1000 : 0x1800) + OutPos, Voices.Dry.Left);
spu2M_WriteFast(((0 == Index) ? 0x1200 : 0x1A00) + OutPos, Voices.Dry.Right);
spu2M_WriteFast(((0 == Index) ? 0x1400 : 0x1C00) + OutPos, Voices.Wet.Left);
spu2M_WriteFast(((0 == Index) ? 0x1600 : 0x1E00) + OutPos, Voices.Wet.Right);
// Write mixed results to logfile (if enabled)
WaveDump::WriteCore( Index, CoreSrc_DryVoiceMix, Voices.Dry );
WaveDump::WriteCore( Index, CoreSrc_WetVoiceMix, Voices.Wet );
WaveDump::WriteCore(Index, CoreSrc_DryVoiceMix, Voices.Dry);
WaveDump::WriteCore(Index, CoreSrc_WetVoiceMix, Voices.Wet);
// Mix in the Input data
StereoOut32 TD(
Input.Left & DryGate.InpL,
Input.Right & DryGate.InpR
);
Input.Right & DryGate.InpR);
// Mix in the Voice data
TD.Left += Voices.Dry.Left & DryGate.SndL;
@ -670,7 +650,8 @@ StereoOut32 V_Core::Mix( const VoiceMixSet& inVoices, const StereoOut32& Input,
// User-level Effects disabling. Nice speedup but breaks games that depend on
// reverb IRQs (very few -- if you find one name it here!).
if( EffectsDisabled ) return TD;
if (EffectsDisabled)
return TD;
// ----------------------------------------------------------------------------
// Reverberation Effects Processing
@ -694,7 +675,8 @@ StereoOut32 V_Core::Mix( const VoiceMixSet& inVoices, const StereoOut32& Input,
// ToDo:
// Bad EndA causes memory corruption. Bad for us, unknown on PS2!
if (!FxEnable || EffectsEndA >= 0x100000) return TD;
if (!FxEnable || EffectsEndA >= 0x100000)
return TD;
StereoOut32 TW;
@ -708,15 +690,15 @@ StereoOut32 V_Core::Mix( const VoiceMixSet& inVoices, const StereoOut32& Input,
TW.Left += Ext.Left & WetGate.ExtL;
TW.Right += Ext.Right & WetGate.ExtR;
WaveDump::WriteCore( Index, CoreSrc_PreReverb, TW );
WaveDump::WriteCore(Index, CoreSrc_PreReverb, TW);
StereoOut32 RV = DoReverb( TW );
StereoOut32 RV = DoReverb(TW);
WaveDump::WriteCore( Index, CoreSrc_PostReverb, RV );
WaveDump::WriteCore(Index, CoreSrc_PostReverb, RV);
// Mix Dry + Wet
// (master volume is applied later to the result of both outputs added together).
return TD + ApplyVolume( RV, FxVol );
return TD + ApplyVolume(RV, FxVol);
}
// Filters that work on the final output to de-alias and equlize it.
@ -753,14 +735,18 @@ StereoOut32 Apply_Frequency_Response_Filter(StereoOut32 &SoundStream)
in = l;
out = FRF.ha0 * in + FRF.ha1 * FRF.History_One_In.Left + FRF.ha2 * FRF.History_Two_In.Left - FRF.hb1 * FRF.History_One_Out.Left - FRF.hb2 * FRF.History_Two_Out.Left;
FRF.History_Two_In.Left = FRF.History_One_In.Left; FRF.History_One_In.Left = in;
FRF.History_Two_Out.Left = FRF.History_One_Out.Left; FRF.History_One_Out.Left = out;
FRF.History_Two_In.Left = FRF.History_One_In.Left;
FRF.History_One_In.Left = in;
FRF.History_Two_Out.Left = FRF.History_One_Out.Left;
FRF.History_One_Out.Left = out;
l = out;
in = r;
out = FRF.ha0 * in + FRF.ha1 * FRF.History_One_In.Right + FRF.ha2 * FRF.History_Two_In.Right - FRF.hb1 * FRF.History_One_Out.Right - FRF.hb2 * FRF.History_Two_Out.Right;
FRF.History_Two_In.Right = FRF.History_One_In.Right; FRF.History_One_In.Right = in;
FRF.History_Two_Out.Right = FRF.History_One_Out.Right; FRF.History_One_Out.Right = out;
FRF.History_Two_In.Right = FRF.History_One_In.Right;
FRF.History_One_In.Right = in;
FRF.History_Two_Out.Right = FRF.History_One_Out.Right;
FRF.History_One_Out.Right = out;
r = out;
//clamp_mix(l);
@ -794,14 +780,15 @@ StereoOut32 Apply_Dealias_Filter(StereoOut32 &SoundStream)
}
// used to throttle the output rate of cache stat reports
static int p_cachestat_counter=0;
static int p_cachestat_counter = 0;
// Gcc does not want to inline it when lto is enabled because some functions growth too much.
// The function is big enought to see any speed impact. -- Gregory
#ifndef __POSIX__
__forceinline
#endif
void Mix()
void
Mix()
{
// Note: Playmode 4 is SPDIF, which overrides other inputs.
StereoOut32 InputData[2] =
@ -810,61 +797,55 @@ void Mix()
// Fixme:
// 1. We do not have an AC3 decoder for the bitstream.
// 2. Games usually provide a normal ADMA stream as well and want to see it getting read!
/*(PlayMode&4) ? StereoOut32::Empty : */ApplyVolume( Cores[0].ReadInput(), Cores[0].InpVol ),
/*(PlayMode&4) ? StereoOut32::Empty : */ ApplyVolume(Cores[0].ReadInput(), Cores[0].InpVol),
// CDDA is on Core 1:
(PlayMode&8) ? StereoOut32::Empty : ApplyVolume( Cores[1].ReadInput(), Cores[1].InpVol )
};
(PlayMode & 8) ? StereoOut32::Empty : ApplyVolume(Cores[1].ReadInput(), Cores[1].InpVol)};
WaveDump::WriteCore( 0, CoreSrc_Input, InputData[0] );
WaveDump::WriteCore( 1, CoreSrc_Input, InputData[1] );
WaveDump::WriteCore(0, CoreSrc_Input, InputData[0]);
WaveDump::WriteCore(1, CoreSrc_Input, InputData[1]);
// Todo: Replace me with memzero initializer!
VoiceMixSet VoiceData[2] = { VoiceMixSet::Empty, VoiceMixSet::Empty }; // mixed voice data for each core.
MixCoreVoices( VoiceData[0], 0 );
MixCoreVoices( VoiceData[1], 1 );
VoiceMixSet VoiceData[2] = {VoiceMixSet::Empty, VoiceMixSet::Empty}; // mixed voice data for each core.
MixCoreVoices(VoiceData[0], 0);
MixCoreVoices(VoiceData[1], 1);
StereoOut32 Ext( Cores[0].Mix( VoiceData[0], InputData[0], StereoOut32::Empty ) );
StereoOut32 Ext(Cores[0].Mix(VoiceData[0], InputData[0], StereoOut32::Empty));
if( (PlayMode & 4) || (Cores[0].Mute!=0) )
if ((PlayMode & 4) || (Cores[0].Mute != 0))
Ext = StereoOut32::Empty;
else
{
Ext = clamp_mix( ApplyVolume( Ext, Cores[0].MasterVol ) );
else {
Ext = clamp_mix(ApplyVolume(Ext, Cores[0].MasterVol));
}
// Commit Core 0 output to ram before mixing Core 1:
spu2M_WriteFast(0x800 + OutPos, Ext.Left);
spu2M_WriteFast(0xA00 + OutPos, Ext.Right);
WaveDump::WriteCore( 0, CoreSrc_External, Ext );
WaveDump::WriteCore(0, CoreSrc_External, Ext);
Ext = ApplyVolume( Ext, Cores[1].ExtVol );
StereoOut32 Out( Cores[1].Mix( VoiceData[1], InputData[1], Ext ) );
Ext = ApplyVolume(Ext, Cores[1].ExtVol);
StereoOut32 Out(Cores[1].Mix(VoiceData[1], InputData[1], Ext));
if( PlayMode & 8 )
{
if (PlayMode & 8) {
// Experimental CDDA support
// The CDDA overrides all other mixer output. It's a direct feed!
Out = Cores[1].ReadInput_HiFi();
//WaveLog::WriteCore( 1, "CDDA-32", OutL, OutR );
}
else
{
Out.Left = MulShr32( Out.Left<<(SndOutVolumeShift+1), Cores[1].MasterVol.Left.Value );
Out.Right = MulShr32( Out.Right<<(SndOutVolumeShift+1), Cores[1].MasterVol.Right.Value );
} else {
Out.Left = MulShr32(Out.Left << (SndOutVolumeShift + 1), Cores[1].MasterVol.Left.Value);
Out.Right = MulShr32(Out.Right << (SndOutVolumeShift + 1), Cores[1].MasterVol.Right.Value);
#ifdef DEBUG_KEYS
if(postprocess_filter_enabled)
#endif
{
if(postprocess_filter_dealias)
#ifdef DEBUG_KEYS
if (postprocess_filter_enabled)
#endif
{
if (postprocess_filter_dealias) {
// Dealias filter emphasizes the highs too much.
Out = Apply_Dealias_Filter ( Out );
Out = Apply_Dealias_Filter(Out);
}
Out = Apply_Frequency_Response_Filter ( Out );
Out = Apply_Frequency_Response_Filter(Out);
}
// Final Clamp!
@ -875,29 +856,29 @@ void Mix()
// Edit: I'm sorry Jake, but I know of no good audio system that arbitrary distorts and clips
// output by design.
// Good thing though that this code gets the volume exactly right, as per tests :)
Out = clamp_mix( Out, SndOutVolumeShift );
Out = clamp_mix(Out, SndOutVolumeShift);
}
// Configurable output volume
Out.Left *= FinalVolume;
Out.Right *= FinalVolume;
SndBuffer::Write( Out );
SndBuffer::Write(Out);
// Update AutoDMA output positioning
OutPos++;
if (OutPos>=0x200) OutPos=0;
if (OutPos >= 0x200)
OutPos = 0;
if( IsDevBuild )
{
if (IsDevBuild) {
p_cachestat_counter++;
if(p_cachestat_counter > (48000*10) )
{
if (p_cachestat_counter > (48000 * 10)) {
p_cachestat_counter = 0;
if( MsgCache() ) ConLog( " * SPU2 > CacheStats > Hits: %d Misses: %d Ignores: %d\n",
if (MsgCache())
ConLog(" * SPU2 > CacheStats > Hits: %d Misses: %d Ignores: %d\n",
g_counter_cache_hits,
g_counter_cache_misses,
g_counter_cache_ignores );
g_counter_cache_ignores);
g_counter_cache_hits =
g_counter_cache_misses =

View File

@ -29,63 +29,61 @@ struct StereoOut32
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;
StereoOut32 operator*( const int& factor ) const
StereoOut32 operator*(const int &factor) const
{
return StereoOut32(
Left * factor,
Right * factor
);
Right * factor);
}
StereoOut32& operator*=( const int& factor )
StereoOut32 &operator*=(const int &factor)
{
Left *= factor;
Right *= factor;
return *this;
}
StereoOut32 operator+( const StereoOut32& right ) const
StereoOut32 operator+(const StereoOut32 &right) const
{
return StereoOut32(
Left + right.Left,
Right + right.Right
);
Right + right.Right);
}
StereoOut32 operator/( int src ) const
StereoOut32 operator/(int src) const
{
return StereoOut32( Left / src, Right / src );
return StereoOut32(Left / src, Right / src);
}
void ResampleFrom( const StereoOut32& src )
void ResampleFrom(const StereoOut32 &src)
{
this->Left = src.Left << 2;
this->Right = src.Right << 2;
}
void AdjustFrom(const StereoOut32& src)
void AdjustFrom(const StereoOut32 &src)
{
ResampleFrom(src);
Left = (s32) (Left * VolumeAdjustFL);
Right = (s32) (Right * VolumeAdjustFR);
Left = (s32)(Left * VolumeAdjustFL);
Right = (s32)(Right * VolumeAdjustFR);
}
};
@ -106,33 +104,32 @@ struct FrequencyResponseFilter
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 ),
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 ),
, 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 )
, 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 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);

View File

@ -38,19 +38,16 @@ static bool IsInitialized = false;
static u32 pClocks = 0;
u32* cyclePtr = NULL;
u32 *cyclePtr = NULL;
u32 lClocks = 0;
#ifdef _MSC_VER
HINSTANCE hInstance;
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
{
if( dwReason == DLL_PROCESS_ATTACH )
{
if (dwReason == DLL_PROCESS_ATTACH) {
hInstance = hinstDLL;
}
else if( dwReason == DLL_PROCESS_DETACH )
{
} else if (dwReason == DLL_PROCESS_DETACH) {
// TODO : perform shutdown procedure, just in case PCSX2 itself failed
// to for some reason..
}
@ -65,47 +62,46 @@ static void InitLibraryName()
// Public Release!
// Output a simplified string that's just our name:
strcpy( libraryName, "SPU2-X" );
strcpy(libraryName, "SPU2-X");
#else
#ifdef SVN_REV_UNKNOWN
#ifdef SVN_REV_UNKNOWN
// Unknown revision.
// Output a name that includes devbuild status but not
// subversion revision tags:
strcpy( libraryName, "SPU2-X"
#ifdef DEBUG_FAST
strcpy(libraryName, "SPU2-X"
#ifdef DEBUG_FAST
"-Debug"
#elif defined( PCSX2_DEBUG )
#elif defined(PCSX2_DEBUG)
"-Debug/Strict" // strict debugging is slow!
#elif defined( PCSX2_DEVBUILD )
#elif defined(PCSX2_DEVBUILD)
"-Dev"
#else
#else
""
#endif
#endif
);
#else
#else
// Use TortoiseSVN's SubWCRev utility's output
// to label the specific revision:
snprintf( libraryName, 255, "SPU2-X %lld%s"
#ifdef DEBUG_FAST
snprintf(libraryName, 255, "SPU2-X %lld%s"
#ifdef DEBUG_FAST
"-Debug"
#elif defined( PCSX2_DEBUG )
#elif defined(PCSX2_DEBUG)
"-Debug/Strict" // strict debugging is slow!
#elif defined( PCSX2_DEVBUILD )
#elif defined(PCSX2_DEVBUILD)
"-Dev"
#else
#else
""
#endif
,SVN_REV, SVN_MODS ? "m" : ""
);
#endif
#endif
,
SVN_REV, SVN_MODS ? "m" : "");
#endif
#endif
}
//static bool cpu_detected = false;
@ -114,7 +110,7 @@ static bool CheckSSE()
{
return true;
#if 0
#if 0
if( !cpu_detected )
{
cpudetectInit();
@ -126,47 +122,52 @@ static bool CheckSSE()
return false;
}
return true;
#endif
#endif
}
EXPORT_C_(u32) PS2EgetLibType()
EXPORT_C_(u32)
PS2EgetLibType()
{
return PS2E_LT_SPU2;
}
EXPORT_C_(char*) PS2EgetLibName()
EXPORT_C_(char *)
PS2EgetLibName()
{
InitLibraryName();
return libraryName;
}
EXPORT_C_(u32) PS2EgetLibVersion2(u32 type)
EXPORT_C_(u32)
PS2EgetLibVersion2(u32 type)
{
return (PS2E_SPU2_VERSION<<16) | (VersionInfo::Release<<8) | VersionInfo::Revision;
return (PS2E_SPU2_VERSION << 16) | (VersionInfo::Release << 8) | VersionInfo::Revision;
}
EXPORT_C_(void) SPU2configure()
EXPORT_C_(void)
SPU2configure()
{
if( !CheckSSE() ) return;
if (!CheckSSE())
return;
configure();
}
EXPORT_C_(void) SPU2about()
EXPORT_C_(void)
SPU2about()
{
AboutBox();
}
EXPORT_C_(s32) SPU2test()
EXPORT_C_(s32)
SPU2test()
{
if( !CheckSSE() ) return -1;
if (!CheckSSE())
return -1;
#ifdef _WIN32
if (IsWindows8OrGreater())
{
for (int n = 0; mods[n] != nullptr; ++n)
{
if (mods[n] == XAudio2_27_Out)
{
if (IsWindows8OrGreater()) {
for (int n = 0; mods[n] != nullptr; ++n) {
if (mods[n] == XAudio2_27_Out) {
mods[n] = XAudio2Out;
break;
}
@ -175,11 +176,10 @@ EXPORT_C_(s32) SPU2test()
#endif
ReadSettings();
if( SndBuffer::Test() != 0 )
{
if (SndBuffer::Test() != 0) {
// TODO : Implement a proper dialog that allows the user to test different audio out drivers.
const wchar_t* wtf = mods[OutputModule]->GetIdent();
SysMessage( L"The '%s' driver test failed. Please configure\na different SoundOut module and try again.", wtf );
const wchar_t *wtf = mods[OutputModule]->GetIdent();
SysMessage(L"The '%s' driver test failed. Please configure\na different SoundOut module and try again.", wtf);
return -1;
}
@ -190,66 +190,76 @@ EXPORT_C_(s32) SPU2test()
// DMA 4/7 Callbacks from Core Emulator
// --------------------------------------------------------------------------------------
u16* DMABaseAddr;
void (* _irqcallback)();
void (* dma4callback)();
void (* dma7callback)();
u16 *DMABaseAddr;
void (*_irqcallback)();
void (*dma4callback)();
void (*dma7callback)();
EXPORT_C_(u32) CALLBACK SPU2ReadMemAddr(int core)
EXPORT_C_(u32)
CALLBACK SPU2ReadMemAddr(int core)
{
return Cores[core].MADR;
}
EXPORT_C_(void) CALLBACK SPU2WriteMemAddr(int core,u32 value)
EXPORT_C_(void)
CALLBACK SPU2WriteMemAddr(int core, u32 value)
{
Cores[core].MADR = value;
}
EXPORT_C_(void) CALLBACK SPU2setDMABaseAddr(uptr baseaddr)
EXPORT_C_(void)
CALLBACK SPU2setDMABaseAddr(uptr baseaddr)
{
DMABaseAddr = (u16*)baseaddr;
DMABaseAddr = (u16 *)baseaddr;
}
EXPORT_C_(void) CALLBACK SPU2setSettingsDir(const char* dir)
EXPORT_C_(void)
CALLBACK SPU2setSettingsDir(const char *dir)
{
CfgSetSettingsDir( dir );
CfgSetSettingsDir(dir);
}
EXPORT_C_(void) CALLBACK SPU2setLogDir(const char* dir)
EXPORT_C_(void)
CALLBACK SPU2setLogDir(const char *dir)
{
CfgSetLogDir( dir );
CfgSetLogDir(dir);
}
EXPORT_C_(s32) SPU2dmaRead(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed)
EXPORT_C_(s32)
SPU2dmaRead(s32 channel, u32 *data, u32 bytesLeft, u32 *bytesProcessed)
{
if(channel==4)
return Cores[0].NewDmaRead(data,bytesLeft, bytesProcessed);
if (channel == 4)
return Cores[0].NewDmaRead(data, bytesLeft, bytesProcessed);
else
return Cores[1].NewDmaRead(data,bytesLeft, bytesProcessed);
return Cores[1].NewDmaRead(data, bytesLeft, bytesProcessed);
}
EXPORT_C_(s32) SPU2dmaWrite(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed)
EXPORT_C_(s32)
SPU2dmaWrite(s32 channel, u32 *data, u32 bytesLeft, u32 *bytesProcessed)
{
if(channel==4)
return Cores[0].NewDmaWrite(data,bytesLeft, bytesProcessed);
if (channel == 4)
return Cores[0].NewDmaWrite(data, bytesLeft, bytesProcessed);
else
return Cores[1].NewDmaWrite(data,bytesLeft, bytesProcessed);
return Cores[1].NewDmaWrite(data, bytesLeft, bytesProcessed);
}
EXPORT_C_(void) SPU2dmaInterrupt(s32 channel)
EXPORT_C_(void)
SPU2dmaInterrupt(s32 channel)
{
if(channel==4)
if (channel == 4)
return Cores[0].NewDmaInterrupt();
else
return Cores[1].NewDmaInterrupt();
}
#ifdef ENABLE_NEW_IOPDMA_SPU2
EXPORT_C_(void) SPU2irqCallback(void (*SPU2callback)())
EXPORT_C_(void)
SPU2irqCallback(void (*SPU2callback)())
{
_irqcallback = SPU2callback;
}
#else
EXPORT_C_(void) SPU2irqCallback(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)())
EXPORT_C_(void)
SPU2irqCallback(void (*SPU2callback)(), void (*DMA4callback)(), void (*DMA7callback)())
{
_irqcallback = SPU2callback;
dma4callback = DMA4callback;
@ -257,61 +267,72 @@ EXPORT_C_(void) SPU2irqCallback(void (*SPU2callback)(),void (*DMA4callback)(),vo
}
#endif
EXPORT_C_(void) CALLBACK SPU2readDMA4Mem(u16 *pMem, u32 size) // size now in 16bit units
EXPORT_C_(void)
CALLBACK SPU2readDMA4Mem(u16 *pMem, u32 size) // size now in 16bit units
{
if( cyclePtr != NULL ) TimeUpdate( *cyclePtr );
if (cyclePtr != NULL)
TimeUpdate(*cyclePtr);
FileLog("[%10d] SPU2 readDMA4Mem size %x\n",Cycles, size<<1);
FileLog("[%10d] SPU2 readDMA4Mem size %x\n", Cycles, size << 1);
Cores[0].DoDMAread(pMem, size);
}
EXPORT_C_(void) CALLBACK SPU2writeDMA4Mem(u16* pMem, u32 size) // size now in 16bit units
EXPORT_C_(void)
CALLBACK SPU2writeDMA4Mem(u16 *pMem, u32 size) // size now in 16bit units
{
if( cyclePtr != NULL ) TimeUpdate( *cyclePtr );
if (cyclePtr != NULL)
TimeUpdate(*cyclePtr);
FileLog("[%10d] SPU2 writeDMA4Mem size %x at address %x\n",Cycles, size<<1, Cores[0].TSA);
FileLog("[%10d] SPU2 writeDMA4Mem size %x at address %x\n", Cycles, size << 1, Cores[0].TSA);
#ifdef S2R_ENABLE
if(!replay_mode)
s2r_writedma4(Cycles,pMem,size);
if (!replay_mode)
s2r_writedma4(Cycles, pMem, size);
#endif
Cores[0].DoDMAwrite(pMem,size);
Cores[0].DoDMAwrite(pMem, size);
}
EXPORT_C_(void) CALLBACK SPU2interruptDMA4()
EXPORT_C_(void)
CALLBACK SPU2interruptDMA4()
{
FileLog("[%10d] SPU2 interruptDMA4\n",Cycles);
FileLog("[%10d] SPU2 interruptDMA4\n", Cycles);
Cores[0].Regs.STATX |= 0x80;
//Cores[0].Regs.ATTR &= ~0x30;
}
EXPORT_C_(void) CALLBACK SPU2interruptDMA7()
EXPORT_C_(void)
CALLBACK SPU2interruptDMA7()
{
FileLog("[%10d] SPU2 interruptDMA7\n",Cycles);
FileLog("[%10d] SPU2 interruptDMA7\n", Cycles);
Cores[1].Regs.STATX |= 0x80;
//Cores[1].Regs.ATTR &= ~0x30;
}
EXPORT_C_(void) CALLBACK SPU2readDMA7Mem(u16* pMem, u32 size)
EXPORT_C_(void)
CALLBACK SPU2readDMA7Mem(u16 *pMem, u32 size)
{
if( cyclePtr != NULL ) TimeUpdate( *cyclePtr );
if (cyclePtr != NULL)
TimeUpdate(*cyclePtr);
FileLog("[%10d] SPU2 readDMA7Mem size %x\n",Cycles, size<<1);
Cores[1].DoDMAread(pMem,size);
FileLog("[%10d] SPU2 readDMA7Mem size %x\n", Cycles, size << 1);
Cores[1].DoDMAread(pMem, size);
}
EXPORT_C_(void) CALLBACK SPU2writeDMA7Mem(u16* pMem, u32 size)
EXPORT_C_(void)
CALLBACK SPU2writeDMA7Mem(u16 *pMem, u32 size)
{
if( cyclePtr != NULL ) TimeUpdate( *cyclePtr );
if (cyclePtr != NULL)
TimeUpdate(*cyclePtr);
FileLog("[%10d] SPU2 writeDMA7Mem size %x at address %x\n",Cycles, size<<1, Cores[1].TSA);
FileLog("[%10d] SPU2 writeDMA7Mem size %x at address %x\n", Cycles, size << 1, Cores[1].TSA);
#ifdef S2R_ENABLE
if(!replay_mode)
s2r_writedma7(Cycles,pMem,size);
if (!replay_mode)
s2r_writedma7(Cycles, pMem, size);
#endif
Cores[1].DoDMAwrite(pMem,size);
Cores[1].DoDMAwrite(pMem, size);
}
EXPORT_C_(void) SPU2reset()
EXPORT_C_(void)
SPU2reset()
{
memset(spu2regs, 0, 0x010000);
memset(_spu2mem, 0, 0x200000);
@ -320,13 +341,13 @@ EXPORT_C_(void) SPU2reset()
Cores[1].Init(1);
}
EXPORT_C_(s32) SPU2init()
EXPORT_C_(s32)
SPU2init()
{
assert( regtable[0x400] == NULL );
assert(regtable[0x400] == NULL);
if (IsInitialized)
{
printf( " * SPU2-X: Already initialized - Ignoring SPU2init signal." );
if (IsInitialized) {
printf(" * SPU2-X: Already initialized - Ignoring SPU2init signal.");
return 0;
}
@ -335,17 +356,16 @@ EXPORT_C_(s32) SPU2init()
ReadSettings();
#ifdef SPU2_LOG
if(AccessLog())
{
spu2Log = OpenLog( AccessLogFileName );
if (AccessLog()) {
spu2Log = OpenLog(AccessLogFileName);
setvbuf(spu2Log, NULL, _IONBF, 0);
FileLog("SPU2init\n");
}
#endif
srand((unsigned)time(NULL));
spu2regs = (s16*)malloc(0x010000);
_spu2mem = (s16*)malloc(0x200000);
spu2regs = (s16 *)malloc(0x010000);
_spu2mem = (s16 *)malloc(0x200000);
// adpcm decoder cache:
// the cache data size is determined by taking the number of adpcm blocks
@ -354,22 +374,21 @@ EXPORT_C_(s32) SPU2init()
// Expanded: 16 bytes expands to 56 bytes [3.5:1 ratio]
// Resulting in 2MB * 3.5.
pcm_cache_data = (PcmCacheEntry*)calloc( pcm_BlockCount, sizeof(PcmCacheEntry) );
pcm_cache_data = (PcmCacheEntry *)calloc(pcm_BlockCount, sizeof(PcmCacheEntry));
if( (spu2regs == NULL) || (_spu2mem == NULL) || (pcm_cache_data == NULL) )
{
SysMessage("SPU2-X: Error allocating Memory\n"); return -1;
if ((spu2regs == NULL) || (_spu2mem == NULL) || (pcm_cache_data == NULL)) {
SysMessage("SPU2-X: Error allocating Memory\n");
return -1;
}
// Patch up a copy of regtable that directly maps "NULLs" to SPU2 memory.
memcpy(regtable, regtable_original, sizeof(regtable));
for(uint mem=0;mem<0x800;mem++)
{
u16 *ptr = regtable[mem>>1];
if(!ptr) {
regtable[mem>>1] = &(spu2Ru16(mem));
for (uint mem = 0; mem < 0x800; mem++) {
u16 *ptr = regtable[mem >> 1];
if (!ptr) {
regtable[mem >> 1] = &(spu2Ru16(mem));
}
}
@ -379,8 +398,8 @@ EXPORT_C_(s32) SPU2init()
InitADSR();
#ifdef S2R_ENABLE
if(!replay_mode)
s2r_open(Cycles,"replay_dump.s2r");
if (!replay_mode)
s2r_open(Cycles, "replay_dump.s2r");
#endif
return 0;
}
@ -390,29 +409,25 @@ EXPORT_C_(s32) SPU2init()
extern bool debugDialogOpen;
extern HWND hDebugDialog;
static INT_PTR CALLBACK DebugProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
static INT_PTR CALLBACK DebugProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
int wmId;
switch(uMsg)
{
switch (uMsg) {
case WM_PAINT:
return FALSE;
case WM_INITDIALOG:
{
debugDialogOpen=true;
}
break;
case WM_INITDIALOG: {
debugDialogOpen = true;
} break;
case WM_COMMAND:
wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
switch (wmId) {
case IDOK:
case IDCANCEL:
debugDialogOpen=false;
EndDialog(hWnd,0);
debugDialogOpen = false;
EndDialog(hWnd, 0);
break;
default:
return FALSE;
@ -427,63 +442,60 @@ static INT_PTR CALLBACK DebugProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lPara
#endif
uptr gsWindowHandle = 0;
EXPORT_C_(s32) SPU2open(void *pDsp)
EXPORT_C_(s32)
SPU2open(void *pDsp)
{
if( IsOpened ) return 0;
if (IsOpened)
return 0;
FileLog("[%10d] SPU2 Open\n",Cycles);
FileLog("[%10d] SPU2 Open\n", Cycles);
if( pDsp != NULL )
gsWindowHandle = *(uptr*)pDsp;
if (pDsp != NULL)
gsWindowHandle = *(uptr *)pDsp;
else
gsWindowHandle = 0;
#ifdef _MSC_VER
#ifdef PCSX2_DEVBUILD // Define may not be needed but not tested yet. Better make sure.
if( IsDevBuild && VisualDebug() )
{
if(debugDialogOpen==0)
{
hDebugDialog = CreateDialogParam(hInstance,MAKEINTRESOURCE(IDD_DEBUG),0,DebugProc,0);
ShowWindow(hDebugDialog,SW_SHOWNORMAL);
debugDialogOpen=1;
if (IsDevBuild && VisualDebug()) {
if (debugDialogOpen == 0) {
hDebugDialog = CreateDialogParam(hInstance, MAKEINTRESOURCE(IDD_DEBUG), 0, DebugProc, 0);
ShowWindow(hDebugDialog, SW_SHOWNORMAL);
debugDialogOpen = 1;
}
}
else if(debugDialogOpen)
{
} else if (debugDialogOpen) {
DestroyWindow(hDebugDialog);
debugDialogOpen=0;
debugDialogOpen = 0;
}
#endif
#endif
IsOpened = true;
lClocks = (cyclePtr!=NULL) ? *cyclePtr : 0;
lClocks = (cyclePtr != NULL) ? *cyclePtr : 0;
try
{
try {
SndBuffer::Init();
#ifndef __POSIX__
DspLoadLibrary(dspPlugin,dspPluginModule);
DspLoadLibrary(dspPlugin, dspPluginModule);
#endif
WaveDump::Open();
}
catch( std::exception& ex )
{
fprintf( stderr, "SPU2-X Error: Could not initialize device, or something.\nReason: %s", ex.what() );
} catch (std::exception &ex) {
fprintf(stderr, "SPU2-X Error: Could not initialize device, or something.\nReason: %s", ex.what());
SPU2close();
return -1;
}
return 0;
}
EXPORT_C_(void) SPU2close()
EXPORT_C_(void)
SPU2close()
{
if( !IsOpened ) return;
if (!IsOpened)
return;
IsOpened = false;
FileLog("[%10d] SPU2 Close\n",Cycles);
FileLog("[%10d] SPU2 Close\n", Cycles);
#ifndef __POSIX__
DspCloseLibrary();
@ -492,17 +504,19 @@ EXPORT_C_(void) SPU2close()
SndBuffer::Cleanup();
}
EXPORT_C_(void) SPU2shutdown()
EXPORT_C_(void)
SPU2shutdown()
{
if(!IsInitialized) return;
if (!IsInitialized)
return;
IsInitialized = false;
ConLog( "* SPU2-X: Shutting down.\n" );
ConLog("* SPU2-X: Shutting down.\n");
SPU2close();
#ifdef S2R_ENABLE
if(!replay_mode)
if (!replay_mode)
s2r_close();
#endif
@ -521,17 +535,20 @@ EXPORT_C_(void) SPU2shutdown()
safe_free(spu2regs);
safe_free(_spu2mem);
safe_free( pcm_cache_data );
safe_free(pcm_cache_data);
#ifdef SPU2_LOG
if(!AccessLog()) return;
FileLog("[%10d] SPU2shutdown\n",Cycles);
if(spu2Log) fclose(spu2Log);
if (!AccessLog())
return;
FileLog("[%10d] SPU2shutdown\n", Cycles);
if (spu2Log)
fclose(spu2Log);
#endif
}
EXPORT_C_(void) SPU2setClockPtr(u32 *ptr)
EXPORT_C_(void)
SPU2setClockPtr(u32 *ptr)
{
cyclePtr = ptr;
}
@ -541,53 +558,58 @@ static u32 lastTicks;
static bool lState[6];
#endif
EXPORT_C_(void) SPU2async(u32 cycles)
EXPORT_C_(void)
SPU2async(u32 cycles)
{
DspUpdate();
if(cyclePtr != NULL)
{
TimeUpdate( *cyclePtr );
}
else
{
if (cyclePtr != NULL) {
TimeUpdate(*cyclePtr);
} else {
pClocks += cycles;
TimeUpdate( pClocks );
TimeUpdate(pClocks);
}
#ifdef DEBUG_KEYS
u32 curTicks = GetTickCount();
if((curTicks - lastTicks) >= 50)
{
if ((curTicks - lastTicks) >= 50) {
int oldI = Interpolation;
bool cState[6];
for(int i=0;i<6;i++)
{
cState[i] = !!(GetAsyncKeyState(VK_NUMPAD0+i)&0x8000);
for (int i = 0; i < 6; i++) {
cState[i] = !!(GetAsyncKeyState(VK_NUMPAD0 + i) & 0x8000);
if((cState[i] && !lState[i]) && i != 5)
if ((cState[i] && !lState[i]) && i != 5)
Interpolation = i;
if((cState[i] && !lState[i]) && i == 5)
{
if ((cState[i] && !lState[i]) && i == 5) {
postprocess_filter_enabled = !postprocess_filter_enabled;
printf("Post process filters %s \n", postprocess_filter_enabled? "enabled" : "disabled");
printf("Post process filters %s \n", postprocess_filter_enabled ? "enabled" : "disabled");
}
lState[i] = cState[i];
}
if(Interpolation != oldI)
{
if (Interpolation != oldI) {
printf("Interpolation set to %d", Interpolation);
switch(Interpolation)
{
case 0: printf(" - Nearest.\n"); break;
case 1: printf(" - Linear.\n"); break;
case 2: printf(" - Cubic.\n"); break;
case 3: printf(" - Hermite.\n"); break;
case 4: printf(" - Catmull-Rom.\n"); break;
default: printf(" (unknown).\n"); break;
switch (Interpolation) {
case 0:
printf(" - Nearest.\n");
break;
case 1:
printf(" - Linear.\n");
break;
case 2:
printf(" - Cubic.\n");
break;
case 3:
printf(" - Hermite.\n");
break;
case 4:
printf(" - Catmull-Rom.\n");
break;
default:
printf(" (unknown).\n");
break;
}
}
@ -596,108 +618,105 @@ EXPORT_C_(void) SPU2async(u32 cycles)
#endif
}
EXPORT_C_(u16) SPU2read(u32 rmem)
EXPORT_C_(u16)
SPU2read(u32 rmem)
{
// if(!replay_mode)
// s2r_readreg(Cycles,rmem);
u16 ret=0xDEAD; u32 core=0, mem=rmem&0xFFFF, omem=mem;
if (mem & 0x400) { omem^=0x400; core=1; }
u16 ret = 0xDEAD;
u32 core = 0, mem = rmem & 0xFFFF, omem = mem;
if (mem & 0x400) {
omem ^= 0x400;
core = 1;
}
if(omem == 0x1f9001AC)
{
if (omem == 0x1f9001AC) {
ret = Cores[core].DmaRead();
}
else
{
if( cyclePtr != NULL )
TimeUpdate( *cyclePtr );
} else {
if (cyclePtr != NULL)
TimeUpdate(*cyclePtr);
if (rmem>>16 == 0x1f80)
{
if (rmem >> 16 == 0x1f80) {
ret = Cores[0].ReadRegPS1(rmem);
}
else if (mem >= 0x800)
{
} else if (mem >= 0x800) {
ret = spu2Ru16(mem);
ConLog("* SPU2-X: Read from reg>=0x800: %x value %x\n",mem,ret);
}
else
{
ret = *(regtable[(mem>>1)]);
ConLog("* SPU2-X: Read from reg>=0x800: %x value %x\n", mem, ret);
} else {
ret = *(regtable[(mem >> 1)]);
//FileLog("[%10d] SPU2 read mem %x (core %d, register %x): %x\n",Cycles, mem, core, (omem & 0x7ff), ret);
SPU2writeLog( "read", rmem, ret );
SPU2writeLog("read", rmem, ret);
}
}
return ret;
}
EXPORT_C_(void) SPU2write(u32 rmem, u16 value)
EXPORT_C_(void)
SPU2write(u32 rmem, u16 value)
{
#ifdef S2R_ENABLE
if(!replay_mode)
s2r_writereg(Cycles,rmem,value);
if (!replay_mode)
s2r_writereg(Cycles, rmem, value);
#endif
// Note: Reverb/Effects are very sensitive to having precise update timings.
// If the SPU2 isn't in in sync with the IOP, samples can end up playing at rather
// incorrect pitches and loop lengths.
if( cyclePtr != NULL )
TimeUpdate( *cyclePtr );
if (cyclePtr != NULL)
TimeUpdate(*cyclePtr);
if (rmem>>16 == 0x1f80)
Cores[0].WriteRegPS1(rmem,value);
else
{
SPU2writeLog( "write", rmem, value );
SPU2_FastWrite( rmem, value );
if (rmem >> 16 == 0x1f80)
Cores[0].WriteRegPS1(rmem, value);
else {
SPU2writeLog("write", rmem, value);
SPU2_FastWrite(rmem, value);
}
}
// if start is 1, starts recording spu2 data, else stops
// returns a non zero value if successful
// for now, pData is not used
EXPORT_C_(int) SPU2setupRecording(int start, void* pData)
EXPORT_C_(int)
SPU2setupRecording(int start, void *pData)
{
if(start==0)
if (start == 0)
RecordStop();
else if(start==1)
else if (start == 1)
RecordStart();
return 0;
}
EXPORT_C_(s32) SPU2freeze(int mode, freezeData *data)
EXPORT_C_(s32)
SPU2freeze(int mode, freezeData *data)
{
pxAssume( data != NULL );
if ( !data )
{
pxAssume(data != NULL);
if (!data) {
printf("SPU2-X savestate null pointer!\n");
return -1;
}
if( mode == FREEZE_SIZE )
{
if (mode == FREEZE_SIZE) {
data->size = Savestate::SizeIt();
return 0;
}
pxAssume( mode == FREEZE_LOAD || mode == FREEZE_SAVE );
pxAssume(mode == FREEZE_LOAD || mode == FREEZE_SAVE);
if( data->data == NULL )
{
if (data->data == NULL) {
printf("SPU2-X savestate null pointer!\n");
return -1;
}
Savestate::DataBlock& spud = (Savestate::DataBlock&)*(data->data);
Savestate::DataBlock &spud = (Savestate::DataBlock &)*(data->data);
switch( mode )
{
case FREEZE_LOAD: return Savestate::ThawIt( spud );
case FREEZE_SAVE: return Savestate::FreezeIt( spud );
switch (mode) {
case FREEZE_LOAD:
return Savestate::ThawIt(spud);
case FREEZE_SAVE:
return Savestate::FreezeIt(spud);
jNO_DEFAULT;
}

View File

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

View File

@ -31,28 +31,27 @@
//
StereoOut32 V_Core::ReadInput_HiFi()
{
if (psxmode)ConLog("ReadInput_HiFi!!!!!\n");
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
//
//#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))
);
(s32 &)(*GetMemPtr(0x2000 + (Index << 10) + InputPosRead)),
(s32 &)(*GetMemPtr(0x2200 + (Index << 10) + InputPosRead)));
if( Index == 1 )
{
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
@ -66,15 +65,13 @@ StereoOut32 V_Core::ReadInput_HiFi()
// 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;
#else
AdmaInProgress = 0;
if(InputDataLeft >= 0x200)
{
if (InputDataLeft >= 0x200) {
#ifdef PCM24_S1_INTERLEAVE
AutoDMAReadBuffer(1);
#else
@ -82,24 +79,27 @@ StereoOut32 V_Core::ReadInput_HiFi()
#endif
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");
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 (Index == 0) {
if (dma4callback)
dma4callback();
} else {
if (dma7callback)
dma7callback();
}
}
}
#endif
@ -112,9 +112,8 @@ StereoOut32 V_Core::ReadInput()
{
StereoOut32 retval;
if( (Index!=1) || ((PlayMode&2)==0) )
{
for (int i=0; i<2; 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);
@ -123,52 +122,52 @@ StereoOut32 V_Core::ReadInput()
// (s32)ADMATempBuffer[InputPosRead+0x200]
//);
retval = StereoOut32(
(s32)(*GetMemPtr(0x2000 + (Index<<10) + InputPosRead)),
(s32)(*GetMemPtr(0x2200 + (Index<<10) + InputPosRead))
);
(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++;
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;
#else
AdmaInProgress = 0;
if(InputDataLeft >= 0x200)
{
if (InputDataLeft >= 0x200) {
//u8 k=InputDataLeft>=InputDataProgress;
AutoDMAReadBuffer(0);
AdmaInProgress = 1;
TSA = (Index<<10) + InputPosRead;
TSA = (Index << 10) + InputPosRead;
if (InputDataLeft < 0x200)
{
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(); }
if (Index == 0) {
if (dma4callback)
dma4callback();
} else {
if (dma7callback)
dma7callback();
}
}
}
#endif

View File

@ -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 )
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 core = 0, omem, mem;
omem = mem = rmem & 0x7FF; //FFFF;
if (mem & 0x400) {
omem ^= 0x400;
core = 1;
}
if( omem < 0x0180 ) // Voice Params (VP)
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)
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;
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 );
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;
}
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;
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);
}
else if ((mem>=0x07C0) && (mem<0x07CE))
{
switch(mem)
{
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);
RegLog(2, "SPDIF_OUT", rmem, -1, value);
break;
case SPDIF_IRQINFO:
RegLog(2,"SPDIF_IRQINFO",rmem,-1,value);
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);
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);
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);
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);
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);
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)
{
} else {
switch (omem) {
case REG_C_ATTR:
RegLog(4,"ATTR",rmem,core,value);
RegLog(4, "ATTR", rmem, core, value);
break;
case REG_S_PMON:
RegLog(1,"PMON0",rmem,core,value);
RegLog(1, "PMON0", rmem, core, value);
break;
case (REG_S_PMON + 2):
RegLog(1,"PMON1",rmem,core,value);
RegLog(1, "PMON1", rmem, core, value);
break;
case REG_S_NON:
RegLog(1,"NON0",rmem,core,value);
RegLog(1, "NON0", rmem, core, value);
break;
case (REG_S_NON + 2):
RegLog(1,"NON1",rmem,core,value);
RegLog(1, "NON1", rmem, core, value);
break;
case REG_S_VMIXL:
RegLog(1,"VMIXL0",rmem,core,value);
RegLog(1, "VMIXL0", rmem, core, value);
case (REG_S_VMIXL + 2):
RegLog(1,"VMIXL1",rmem,core,value);
RegLog(1, "VMIXL1", rmem, core, value);
break;
case REG_S_VMIXEL:
RegLog(1,"VMIXEL0",rmem,core,value);
RegLog(1, "VMIXEL0", rmem, core, value);
break;
case (REG_S_VMIXEL + 2):
RegLog(1,"VMIXEL1",rmem,core,value);
RegLog(1, "VMIXEL1", rmem, core, value);
break;
case REG_S_VMIXR:
RegLog(1,"VMIXR0",rmem,core,value);
RegLog(1, "VMIXR0", rmem, core, value);
break;
case (REG_S_VMIXR + 2):
RegLog(1,"VMIXR1",rmem,core,value);
RegLog(1, "VMIXR1", rmem, core, value);
break;
case REG_S_VMIXER:
RegLog(1,"VMIXER0",rmem,core,value);
RegLog(1, "VMIXER0", rmem, core, value);
break;
case (REG_S_VMIXER + 2):
RegLog(1,"VMIXER1",rmem,core,value);
RegLog(1, "VMIXER1", rmem, core, value);
break;
case REG_P_MMIX:
RegLog(1,"MMIX",rmem,core,value);
RegLog(1, "MMIX", rmem, core, value);
break;
case REG_A_IRQA:
RegLog(2,"IRQAH",rmem,core,value);
RegLog(2, "IRQAH", rmem, core, value);
break;
case (REG_A_IRQA + 2):
RegLog(2,"IRQAL",rmem,core,value);
RegLog(2, "IRQAL", rmem, core, value);
break;
case (REG_S_KON + 2):
RegLog(1,"KON1",rmem,core,value);
RegLog(1, "KON1", rmem, core, value);
break;
case REG_S_KON:
RegLog(1,"KON0",rmem,core,value);
RegLog(1, "KON0", rmem, core, value);
break;
case (REG_S_KOFF + 2):
RegLog(1,"KOFF1",rmem,core,value);
RegLog(1, "KOFF1", rmem, core, value);
break;
case REG_S_KOFF:
RegLog(1,"KOFF0",rmem,core,value);
RegLog(1, "KOFF0", rmem, core, value);
break;
case REG_A_TSA:
RegLog(2,"TSAH",rmem,core,value);
RegLog(2, "TSAH", rmem, core, value);
break;
case (REG_A_TSA + 2):
RegLog(2,"TSAL",rmem,core,value);
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);
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);
RegLog(2, "ENDX1", rmem, core, value);
break;
case REG_P_MVOLL:
RegLog(1,"MVOLL",rmem,core,value);
RegLog(1, "MVOLL", rmem, core, value);
break;
case REG_P_MVOLR:
RegLog(1,"MVOLR",rmem,core,value);
RegLog(1, "MVOLR", rmem, core, value);
break;
case REG_S_ADMAS:
RegLog(3,"ADMAS",rmem,core,value);
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);
RegLog(3, "STATX", rmem, core, value);
break;
case REG_A_ESA:
RegLog(2,"ESAH",rmem,core,value);
RegLog(2, "ESAH", rmem, core, value);
break;
case (REG_A_ESA + 2):
RegLog(2,"ESAL",rmem,core,value);
RegLog(2, "ESAL", rmem, core, value);
break;
case REG_A_EEA:
RegLog(2,"EEAH",rmem,core,value);
RegLog(2, "EEAH", rmem, core, value);
break;
#define LOG_REVB_REG(n,t) \
#define LOG_REVB_REG(n, t) \
case R_##n: \
RegLog(2,t "H",mem,core,value); \
RegLog(2, t "H", mem, core, value); \
break; \
case (R_##n + 2): \
RegLog(2,t "L",mem,core,value); \
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;
RegLog(2, "UNKNOWN", rmem, core, value);
spu2Ru16(mem) = value;
}
}
}

View File

@ -17,270 +17,271 @@
#include "Global.h"
#define PCORE(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] =
{
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),
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,
PCORE(0,TSA)+1,
PCORE(0,TSA),
PCORE(0, TSA) + 1,
PCORE(0, TSA),
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
// 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),
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),
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),
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,
PCORE(1,TSA)+1,
PCORE(1,TSA),
PCORE(1, TSA) + 1,
PCORE(1, TSA),
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
// 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),
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(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),
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),
@ -292,12 +293,11 @@ u16 const* const regtable_original[0x401] =
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(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};

View File

@ -24,16 +24,15 @@
//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;
// Fast and simple single step wrapping, made possible by the preparation of the
// effects buffer addresses.
if( pos > EffectsEndA )
{
pos -= EffectsEndA+1;
if (pos > EffectsEndA) {
pos -= EffectsEndA + 1;
pos += EffectsStartA;
}
@ -43,19 +42,19 @@ __forceinline s32 V_Core::RevbGetIndexer( s32 offset )
void V_Core::Reverb_AdvanceBuffer()
{
if( RevBuffers.NeedsUpdated )
if (RevBuffers.NeedsUpdated)
UpdateEffectsBufferSize();
if( (Cycles & 1) && (EffectsBufferSize > 0) )
{
if ((Cycles & 1) && (EffectsBufferSize > 0)) {
ReverbX += 1;
if( ReverbX >= (u32)EffectsBufferSize ) ReverbX = 0;
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] =
@ -68,68 +67,63 @@ StereoOut32 V_Core::DoReverb( const StereoOut32& Input )
static const s32 downcoeffs[8] =
{
855, 3562, 7263, 10163,
10163, 7263, 3562, 855
};
10163, 7263, 3562, 855};
#endif
downbuf[dbpos] = Input;
dbpos = (dbpos+1) & 7;
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.
if( (Cycles&1) == 0 )
{
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;
} 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.
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 !
@ -140,11 +134,9 @@ StereoOut32 V_Core::DoReverb( const StereoOut32& Input )
// 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) ||
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) ||
@ -162,8 +154,7 @@ StereoOut32 V_Core::DoReverb( const StereoOut32& Input )
(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) )
{
(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);
}
@ -176,10 +167,9 @@ StereoOut32 V_Core::DoReverb( const StereoOut32& Input )
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;
@ -188,10 +178,10 @@ StereoOut32 V_Core::DoReverb( const StereoOut32& Input )
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];
@ -200,28 +190,26 @@ StereoOut32 V_Core::DoReverb( const StereoOut32& Input )
// 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 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)
);
((_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)
);
((_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)
@ -241,10 +229,10 @@ StereoOut32 V_Core::DoReverb( const StereoOut32& Input )
_spu2mem[mix_dest_b0] = mix_b0;
_spu2mem[mix_dest_b1] = mix_b1;
upbuf[ubpos] = clamp_mix( StereoOut32(
upbuf[ubpos] = clamp_mix(StereoOut32(
mix_a0 + mix_b0, // left
mix_a1 + mix_b1 // right
) );
));
}
StereoOut32 retval;
@ -255,15 +243,12 @@ StereoOut32 V_Core::DoReverb( const StereoOut32& Input )
// 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:
@ -279,7 +264,7 @@ StereoOut32 V_Core::DoReverb( const StereoOut32& Input )
//retval.Left >>= (16-1 + 1);
//retval.Right >>= (16-1 + 1);
ubpos = (ubpos+1) & 7;
ubpos = (ubpos + 1) & 7;
return retval;
}

View File

@ -18,17 +18,17 @@
#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))
{
}
@ -36,35 +36,32 @@ StereoOut16 StereoOut32::DownSample() const
{
return StereoOut16(
Left >> SndOutVolumeShift,
Right >> SndOutVolumeShift
);
Right >> SndOutVolumeShift);
}
StereoOut32 StereoOut16::UpSample() const
{
return StereoOut32(
Left << SndOutVolumeShift,
Right << SndOutVolumeShift
);
Right << SndOutVolumeShift);
}
class NullOutModule: public SndOutModule
class NullOutModule : public SndOutModule
{
public:
s32 Init() { return 0; }
void Close() { }
void Close() {}
s32 Test() const { return 0; }
void Configure(uptr parent) { }
void Configure(uptr parent) {}
int GetEmptySampleCount() { return 0; }
const wchar_t* GetIdent() const
const wchar_t *GetIdent() const
{
return L"nullout";
}
const wchar_t* GetLongName() const
const wchar_t *GetLongName() const
{
return L"No Sound (Emulate SPU2 only)";
}
@ -83,8 +80,8 @@ public:
} NullOut;
SndOutModule* mods[]=
{
SndOutModule *mods[] =
{
&NullOut,
#ifdef _MSC_VER
XAudio2_27_Out,
@ -101,12 +98,11 @@ SndOutModule* mods[]=
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 )
while (mods[modcnt] != NULL) {
if (wcscmp(mods[modcnt]->GetIdent(), omodid) == 0)
break;
++modcnt;
}
@ -119,47 +115,43 @@ __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;
int data = _GetApproximateDataInBuffer();
if( m_underrun_freeze )
{
int toFill = m_size / ( (SynchMode == 2) ? 32 : 400); // TimeStretch and Async off?
toFill = GetAlignedBufferSize( toFill );
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
if( data < toFill )
{
if (data < toFill) {
quietSampleCount = nSamples;
return false;
}
m_underrun_freeze = false;
if( MsgOverruns() )
ConLog(" * SPU2 > Underrun compensation (%d packets buffered)\n", toFill / SndOutPacketSize );
if (MsgOverruns())
ConLog(" * SPU2 > Underrun compensation (%d packets buffered)\n", toFill / SndOutPacketSize);
lastPct = 0.0; // normalize timestretcher
}
else if( data < nSamples )
{
} else if (data < nSamples) {
nSamples = data;
quietSampleCount = SndOutPacketSize - data;
m_underrun_freeze = true;
if( SynchMode == 0 ) // TimeStrech on
if (SynchMode == 0) // TimeStrech on
timeStretchUnderrun();
return nSamples != 0;
@ -172,7 +164,7 @@ 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() );
OutputModule = FindOutputModuleById(NullOut.GetIdent());
mods[OutputModule]->Init();
}
@ -207,33 +199,27 @@ void SndBuffer::_ReadSamples_Internal(StereoOut32 *bData, int 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)
{
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 + 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)
{
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 + b1, b2);
} else {
_ReadSamples_Internal(bData, nSamples);
}
}
@ -242,7 +228,8 @@ void SndBuffer::_ReadSamples_Safe(StereoOut32* bData, int nSamples)
// 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;
@ -260,18 +247,16 @@ template<typename T> void SndBuffer::ReadSamples(T* bData)
// set buffer length in duration.
int quietSamples;
if( CheckUnderrunStatus( nSamples, quietSamples ) )
{
pxAssume( nSamples <= SndOutPacketSize );
if (CheckUnderrunStatus(nSamples, quietSamples)) {
pxAssume(nSamples <= SndOutPacketSize);
// WARNING: This code assumes there's only ONE reading process.
int b1 = m_size - m_rpos;
if(b1 > nSamples)
if (b1 > nSamples)
b1 = nSamples;
if (AdvancedVolumeControl)
{
if (AdvancedVolumeControl) {
// First part
for (int i = 0; i < b1; i++)
bData[i].AdjustFrom(m_buffer[i + m_rpos]);
@ -280,9 +265,7 @@ template<typename T> void SndBuffer::ReadSamples(T* bData)
int b2 = nSamples - b1;
for (int i = 0; i < b2; i++)
bData[i + b1].AdjustFrom(m_buffer[i]);
}
else
{
} else {
// First part
for (int i = 0; i < b1; i++)
bData[i].ResampleFrom(m_buffer[i + m_rpos]);
@ -299,29 +282,29 @@ template<typename T> void SndBuffer::ReadSamples(T* bData)
// 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) );
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)
{
@ -339,9 +322,8 @@ void SndBuffer::_WriteSamples(StereoOut32 *bData, int nSamples)
// 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
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,7 +348,7 @@ 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() )
if (MsgOverruns())
ConLog(" * SPU2 > Overrun! 1 packet tossed)\n");
lastPct = 0.0; // normalize the timestretcher
return;
@ -378,8 +360,7 @@ void SndBuffer::_WriteSamples(StereoOut32 *bData, int nSamples)
void SndBuffer::Init()
{
if( mods[OutputModule] == NULL )
{
if (mods[OutputModule] == NULL) {
_InitFail();
return;
}
@ -391,36 +372,34 @@ void SndBuffer::Init()
m_rpos = 0;
m_wpos = 0;
try
{
try {
const float latencyMS = SndOutLatencyMS * 16;
m_size = GetAlignedBufferSize( (int)(latencyMS * SampleRate / 1000.0f ) );
m_size = GetAlignedBufferSize((int)(latencyMS * SampleRate / 1000.0f));
m_buffer = new StereoOut32[m_size];
m_underrun_freeze = false;
sndTempBuffer = new StereoOut32[SndOutPacketSize];
sndTempBuffer16 = new StereoOut16[SndOutPacketSize * 2]; // in case of leftovers.
}
catch( std::bad_alloc& )
{
} catch (std::bad_alloc &) {
// out of memory exception (most likely)
SysMessage( "Out of memory error occurred while initializing SPU2." );
SysMessage("Out of memory error occurred while initializing SPU2.");
_InitFail();
return;
}
// clear buffers!
// Fixes loopy sounds on emu resets.
memset( sndTempBuffer, 0, sizeof(StereoOut32) * SndOutPacketSize );
memset( sndTempBuffer16, 0, sizeof(StereoOut16) * SndOutPacketSize );
memset(sndTempBuffer, 0, sizeof(StereoOut32) * SndOutPacketSize);
memset(sndTempBuffer16, 0, sizeof(StereoOut16) * SndOutPacketSize);
sndTempProgress = 0;
soundtouchInit(); // initializes the timestretching
// initialize module
if( mods[OutputModule]->Init() == -1 ) _InitFail();
if (mods[OutputModule]->Init() == -1)
_InitFail();
}
void SndBuffer::Cleanup()
@ -429,9 +408,9 @@ void SndBuffer::Cleanup()
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;
@ -445,44 +424,47 @@ void SndBuffer::ClearContents()
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() );
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
if (mods[OutputModule] == &NullOut) // null output doesn't need buffering or stretching! :p
return;
sndTempBuffer[sndTempProgress++] = Sample;
// If we haven't accumulated a full packet yet, do nothing more:
if(sndTempProgress < SndOutPacketSize) return;
if (sndTempProgress < SndOutPacketSize)
return;
sndTempProgress = 0;
//Don't play anything directly after loading a savestate, avoids static killing your speakers.
if ( ssFreeze > 0 )
{
if (ssFreeze > 0) {
ssFreeze--;
memset( sndTempBuffer, 0, sizeof(StereoOut32) * SndOutPacketSize ); // Play silence
memset(sndTempBuffer, 0, sizeof(StereoOut32) * SndOutPacketSize); // Play silence
}
#ifndef __POSIX__
if( dspPluginEnabled )
{
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(); }
while (m_dsp_progress >= SndOutPacketSize) {
for (int i = 0; i < SndOutPacketSize; ++i, ++ei) {
sndTempBuffer[i] = sndTempBuffer16[ei].UpSample();
}
if( SynchMode == 0 ) // TimeStrech on
if (SynchMode == 0) // TimeStrech on
timeStretchWrite();
else
_WriteSamples(sndTempBuffer, SndOutPacketSize);
@ -491,17 +473,14 @@ void SndBuffer::Write( const StereoOut32& Sample )
}
// 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
);
if (m_dsp_progress > 0) {
memcpy(sndTempBuffer16, &sndTempBuffer16[ei],
sizeof(sndTempBuffer16[0]) * m_dsp_progress);
}
}
#endif
else
{
if( SynchMode == 0 ) // TimeStrech on
else {
if (SynchMode == 0) // TimeStrech on
timeStretchWrite();
else
_WriteSamples(sndTempBuffer, SndOutPacketSize);
@ -510,7 +489,7 @@ void SndBuffer::Write( const StereoOut32& Sample )
s32 SndBuffer::Test()
{
if( mods[OutputModule] == NULL )
if (mods[OutputModule] == NULL)
return -1;
return mods[OutputModule]->Test();

View File

@ -27,14 +27,14 @@ static const int SndOutPacketSize = 64;
// downsamples 32 bit samples to 16 bit sound driver output (this way timestretching and
// DSP effects get better precision results)
static const int SndOutVolumeShift = 12;
static const int SndOutVolumeShift32 = 16-SndOutVolumeShift; // shift up, not down
static const int SndOutVolumeShift32 = 16 - SndOutVolumeShift; // shift up, not down
// Samplerate of the SPU2. For accurate playback we need to match this
// exactly. Trying to scale samplerates and maintain SPU2's Ts timing accuracy
// is too problematic. :)
static const int SampleRate = 48000;
extern int FindOutputModuleById( const wchar_t* omodid );
extern int FindOutputModuleById(const wchar_t *omodid);
// Implemented in Config.cpp
extern float VolumeAdjustFL;
@ -54,48 +54,48 @@ struct Stereo51Out16Dpl; // similar to DplII but without rear balancing
struct Stereo51Out32Dpl;
extern void ResetDplIIDecoder();
extern void ProcessDplIISample16( const StereoOut32& src, Stereo51Out16DplII * s);
extern void ProcessDplIISample32( const StereoOut32& src, Stereo51Out32DplII * s);
extern void ProcessDplSample16( const StereoOut32& src, Stereo51Out16Dpl * s);
extern void ProcessDplSample32( const StereoOut32& src, Stereo51Out32Dpl * s);
extern void ProcessDplIISample16(const StereoOut32 &src, Stereo51Out16DplII *s);
extern void ProcessDplIISample32(const StereoOut32 &src, Stereo51Out32DplII *s);
extern void ProcessDplSample16(const StereoOut32 &src, Stereo51Out16Dpl *s);
extern void ProcessDplSample32(const StereoOut32 &src, Stereo51Out32Dpl *s);
struct StereoOut16
{
s16 Left;
s16 Right;
StereoOut16() :
Left( 0 ),
Right( 0 )
StereoOut16()
: Left(0)
, Right(0)
{
}
StereoOut16( const StereoOut32& src ) :
Left( (s16)src.Left ),
Right( (s16)src.Right )
StereoOut16(const StereoOut32 &src)
: Left((s16)src.Left)
, Right((s16)src.Right)
{
}
StereoOut16( s16 left, s16 right ) :
Left( left ),
Right( right )
StereoOut16(s16 left, s16 right)
: Left(left)
, Right(right)
{
}
StereoOut32 UpSample() const;
void ResampleFrom( const StereoOut32& src )
void ResampleFrom(const StereoOut32 &src)
{
// Use StereoOut32's built in conversion
*this = src.DownSample();
}
void AdjustFrom(const StereoOut32& src)
void AdjustFrom(const StereoOut32 &src)
{
ResampleFrom(src);
Left = (s16) (Left * VolumeAdjustFL);
Right = (s16) (Right * VolumeAdjustFR);
Left = (s16)(Left * VolumeAdjustFL);
Right = (s16)(Right * VolumeAdjustFR);
}
};
@ -104,27 +104,27 @@ struct StereoOutFloat
float Left;
float Right;
StereoOutFloat() :
Left( 0 ),
Right( 0 )
StereoOutFloat()
: Left(0)
, Right(0)
{
}
explicit StereoOutFloat( const StereoOut32& src ) :
Left( src.Left / 2147483647.0f ),
Right( src.Right / 2147483647.0f )
explicit StereoOutFloat(const StereoOut32 &src)
: Left(src.Left / 2147483647.0f)
, Right(src.Right / 2147483647.0f)
{
}
explicit StereoOutFloat( s32 left, s32 right ) :
Left( left / 2147483647.0f ),
Right( right / 2147483647.0f )
explicit StereoOutFloat(s32 left, s32 right)
: Left(left / 2147483647.0f)
, Right(right / 2147483647.0f)
{
}
StereoOutFloat( float left, float right ) :
Left( left ),
Right( right )
StereoOutFloat(float left, float right)
: Left(left)
, Right(right)
{
}
};
@ -135,20 +135,20 @@ struct Stereo21Out16
s16 Right;
s16 LFE;
void ResampleFrom( const StereoOut32& src )
void ResampleFrom(const StereoOut32 &src)
{
Left = src.Left >> SndOutVolumeShift;
Right = src.Right >> SndOutVolumeShift;
LFE = (src.Left + src.Right) >> (SndOutVolumeShift + 1);
}
void AdjustFrom(const StereoOut32& src)
void AdjustFrom(const StereoOut32 &src)
{
ResampleFrom(src);
Left = (s16) (Left * VolumeAdjustFL);
Right = (s16) (Right * VolumeAdjustFR);
LFE = (s16) (LFE * VolumeAdjustLFE);
Left = (s16)(Left * VolumeAdjustFL);
Right = (s16)(Right * VolumeAdjustFR);
LFE = (s16)(LFE * VolumeAdjustLFE);
}
};
@ -159,7 +159,7 @@ struct Stereo40Out16
s16 LeftBack;
s16 RightBack;
void ResampleFrom( const StereoOut32& src )
void ResampleFrom(const StereoOut32 &src)
{
Left = src.Left >> SndOutVolumeShift;
Right = src.Right >> SndOutVolumeShift;
@ -167,14 +167,14 @@ struct Stereo40Out16
RightBack = src.Right >> SndOutVolumeShift;
}
void AdjustFrom(const StereoOut32& src)
void AdjustFrom(const StereoOut32 &src)
{
ResampleFrom(src);
Left = (s16) (Left * VolumeAdjustFL);
Right = (s16) (Right * VolumeAdjustFR);
LeftBack = (s16) (LeftBack * VolumeAdjustBL);
RightBack = (s16) (RightBack * VolumeAdjustBR);
Left = (s16)(Left * VolumeAdjustFL);
Right = (s16)(Right * VolumeAdjustFR);
LeftBack = (s16)(LeftBack * VolumeAdjustBL);
RightBack = (s16)(RightBack * VolumeAdjustBR);
}
};
@ -185,7 +185,7 @@ struct Stereo40Out32
s32 LeftBack;
s32 RightBack;
void ResampleFrom( const StereoOut32& src )
void ResampleFrom(const StereoOut32 &src)
{
Left = src.Left << SndOutVolumeShift32;
Right = src.Right << SndOutVolumeShift32;
@ -193,14 +193,14 @@ struct Stereo40Out32
RightBack = src.Right << SndOutVolumeShift32;
}
void AdjustFrom(const StereoOut32& src)
void AdjustFrom(const StereoOut32 &src)
{
ResampleFrom(src);
Left = (s32) (Left * VolumeAdjustFL);
Right = (s32) (Right * VolumeAdjustFR);
LeftBack = (s32) (LeftBack * VolumeAdjustBL);
RightBack = (s32) (RightBack * VolumeAdjustBR);
Left = (s32)(Left * VolumeAdjustFL);
Right = (s32)(Right * VolumeAdjustFR);
LeftBack = (s32)(LeftBack * VolumeAdjustBL);
RightBack = (s32)(RightBack * VolumeAdjustBR);
}
};
@ -212,7 +212,7 @@ struct Stereo41Out16
s16 LeftBack;
s16 RightBack;
void ResampleFrom( const StereoOut32& src )
void ResampleFrom(const StereoOut32 &src)
{
Left = src.Left >> SndOutVolumeShift;
Right = src.Right >> SndOutVolumeShift;
@ -221,15 +221,15 @@ struct Stereo41Out16
RightBack = src.Right >> SndOutVolumeShift;
}
void AdjustFrom(const StereoOut32& src)
void AdjustFrom(const StereoOut32 &src)
{
ResampleFrom(src);
Left = (s32) (Left * VolumeAdjustFL);
Right = (s32) (Right * VolumeAdjustFR);
LeftBack = (s32) (LeftBack * VolumeAdjustBL);
RightBack = (s32) (RightBack * VolumeAdjustBR);
LFE = (s32) (LFE * VolumeAdjustLFE);
Left = (s32)(Left * VolumeAdjustFL);
Right = (s32)(Right * VolumeAdjustFR);
LeftBack = (s32)(LeftBack * VolumeAdjustBL);
RightBack = (s32)(RightBack * VolumeAdjustBR);
LFE = (s32)(LFE * VolumeAdjustLFE);
}
};
@ -247,7 +247,7 @@ struct Stereo51Out16
// systems do to their own low pass / crossover. Manual lowpass is wasted effort
// and can't match solid state results anyway.
void ResampleFrom( const StereoOut32& src )
void ResampleFrom(const StereoOut32 &src)
{
Left = src.Left >> SndOutVolumeShift;
Right = src.Right >> SndOutVolumeShift;
@ -257,16 +257,16 @@ struct Stereo51Out16
RightBack = src.Right >> SndOutVolumeShift;
}
void AdjustFrom(const StereoOut32& src)
void AdjustFrom(const StereoOut32 &src)
{
ResampleFrom(src);
Left = (s16) (Left * VolumeAdjustFL);
Right = (s16) (Right * VolumeAdjustFR);
LeftBack = (s16) (LeftBack * VolumeAdjustBL);
RightBack = (s16) (RightBack * VolumeAdjustBR);
Center = (s16) (Center * VolumeAdjustC);
LFE = (s16) (LFE * VolumeAdjustLFE);
Left = (s16)(Left * VolumeAdjustFL);
Right = (s16)(Right * VolumeAdjustFR);
LeftBack = (s16)(LeftBack * VolumeAdjustBL);
RightBack = (s16)(RightBack * VolumeAdjustBR);
Center = (s16)(Center * VolumeAdjustC);
LFE = (s16)(LFE * VolumeAdjustLFE);
}
};
@ -279,21 +279,21 @@ struct Stereo51Out16DplII
s16 LeftBack;
s16 RightBack;
void ResampleFrom( const StereoOut32& src )
void ResampleFrom(const StereoOut32 &src)
{
ProcessDplIISample16(src, this);
}
void AdjustFrom(const StereoOut32& src)
void AdjustFrom(const StereoOut32 &src)
{
ResampleFrom(src);
Left = (s32) (Left * VolumeAdjustFL);
Right = (s32) (Right * VolumeAdjustFR);
LeftBack = (s32) (LeftBack * VolumeAdjustBL);
RightBack = (s32) (RightBack * VolumeAdjustBR);
Center = (s32) (Center * VolumeAdjustC);
LFE = (s32) (LFE * VolumeAdjustLFE);
Left = (s32)(Left * VolumeAdjustFL);
Right = (s32)(Right * VolumeAdjustFR);
LeftBack = (s32)(LeftBack * VolumeAdjustBL);
RightBack = (s32)(RightBack * VolumeAdjustBR);
Center = (s32)(Center * VolumeAdjustC);
LFE = (s32)(LFE * VolumeAdjustLFE);
}
};
@ -306,21 +306,21 @@ struct Stereo51Out32DplII
s32 LeftBack;
s32 RightBack;
void ResampleFrom( const StereoOut32& src )
void ResampleFrom(const StereoOut32 &src)
{
ProcessDplIISample32(src, this);
}
void AdjustFrom(const StereoOut32& src)
void AdjustFrom(const StereoOut32 &src)
{
ResampleFrom(src);
Left = (s32) (Left * VolumeAdjustFL);
Right = (s32) (Right * VolumeAdjustFR);
LeftBack = (s32) (LeftBack * VolumeAdjustBL);
RightBack = (s32) (RightBack * VolumeAdjustBR);
Center = (s32) (Center * VolumeAdjustC);
LFE = (s32) (LFE * VolumeAdjustLFE);
Left = (s32)(Left * VolumeAdjustFL);
Right = (s32)(Right * VolumeAdjustFR);
LeftBack = (s32)(LeftBack * VolumeAdjustBL);
RightBack = (s32)(RightBack * VolumeAdjustBR);
Center = (s32)(Center * VolumeAdjustC);
LFE = (s32)(LFE * VolumeAdjustLFE);
}
};
@ -333,21 +333,21 @@ struct Stereo51Out16Dpl
s16 LeftBack;
s16 RightBack;
void ResampleFrom( const StereoOut32& src )
void ResampleFrom(const StereoOut32 &src)
{
ProcessDplSample16(src, this);
}
void AdjustFrom(const StereoOut32& src)
void AdjustFrom(const StereoOut32 &src)
{
ResampleFrom(src);
Left = (s32) (Left * VolumeAdjustFL);
Right = (s32) (Right * VolumeAdjustFR);
LeftBack = (s32) (LeftBack * VolumeAdjustBL);
RightBack = (s32) (RightBack * VolumeAdjustBR);
Center = (s32) (Center * VolumeAdjustC);
LFE = (s32) (LFE * VolumeAdjustLFE);
Left = (s32)(Left * VolumeAdjustFL);
Right = (s32)(Right * VolumeAdjustFR);
LeftBack = (s32)(LeftBack * VolumeAdjustBL);
RightBack = (s32)(RightBack * VolumeAdjustBR);
Center = (s32)(Center * VolumeAdjustC);
LFE = (s32)(LFE * VolumeAdjustLFE);
}
};
@ -360,21 +360,21 @@ struct Stereo51Out32Dpl
s32 LeftBack;
s32 RightBack;
void ResampleFrom( const StereoOut32& src )
void ResampleFrom(const StereoOut32 &src)
{
ProcessDplSample32(src, this);
}
void AdjustFrom(const StereoOut32& src)
void AdjustFrom(const StereoOut32 &src)
{
ResampleFrom(src);
Left = (s32) (Left * VolumeAdjustFL);
Right = (s32) (Right * VolumeAdjustFR);
LeftBack = (s32) (LeftBack * VolumeAdjustBL);
RightBack = (s32) (RightBack * VolumeAdjustBR);
Center = (s32) (Center * VolumeAdjustC);
LFE = (s32) (LFE * VolumeAdjustLFE);
Left = (s32)(Left * VolumeAdjustFL);
Right = (s32)(Right * VolumeAdjustFR);
LeftBack = (s32)(LeftBack * VolumeAdjustBL);
RightBack = (s32)(RightBack * VolumeAdjustBR);
Center = (s32)(Center * VolumeAdjustC);
LFE = (s32)(LFE * VolumeAdjustLFE);
}
};
@ -389,7 +389,7 @@ struct Stereo71Out16
s16 LeftSide;
s16 RightSide;
void ResampleFrom( const StereoOut32& src )
void ResampleFrom(const StereoOut32 &src)
{
Left = src.Left >> SndOutVolumeShift;
Right = src.Right >> SndOutVolumeShift;
@ -398,22 +398,22 @@ struct Stereo71Out16
LeftBack = src.Left >> SndOutVolumeShift;
RightBack = src.Right >> SndOutVolumeShift;
LeftSide = src.Left >> (SndOutVolumeShift+1);
RightSide = src.Right >> (SndOutVolumeShift+1);
LeftSide = src.Left >> (SndOutVolumeShift + 1);
RightSide = src.Right >> (SndOutVolumeShift + 1);
}
void AdjustFrom(const StereoOut32& src)
void AdjustFrom(const StereoOut32 &src)
{
ResampleFrom(src);
Left = (s16) (Left * VolumeAdjustFL);
Right = (s16) (Right * VolumeAdjustFR);
LeftBack = (s16) (LeftBack * VolumeAdjustBL);
RightBack = (s16) (RightBack * VolumeAdjustBR);
LeftSide = (s16) (LeftBack * VolumeAdjustSL);
RightSide = (s16) (RightBack * VolumeAdjustSR);
Center = (s16) (Center * VolumeAdjustC);
LFE = (s16) (LFE * VolumeAdjustLFE);
Left = (s16)(Left * VolumeAdjustFL);
Right = (s16)(Right * VolumeAdjustFR);
LeftBack = (s16)(LeftBack * VolumeAdjustBL);
RightBack = (s16)(RightBack * VolumeAdjustBR);
LeftSide = (s16)(LeftBack * VolumeAdjustSL);
RightSide = (s16)(RightBack * VolumeAdjustSR);
Center = (s16)(Center * VolumeAdjustC);
LFE = (s16)(LFE * VolumeAdjustLFE);
}
};
@ -428,7 +428,7 @@ struct Stereo71Out32
s32 LeftSide;
s32 RightSide;
void ResampleFrom( const StereoOut32& src )
void ResampleFrom(const StereoOut32 &src)
{
Left = src.Left << SndOutVolumeShift32;
Right = src.Right << SndOutVolumeShift32;
@ -441,18 +441,18 @@ struct Stereo71Out32
RightSide = src.Right << (SndOutVolumeShift32 - 1);
}
void AdjustFrom(const StereoOut32& src)
void AdjustFrom(const StereoOut32 &src)
{
ResampleFrom(src);
Left = (s32) (Left * VolumeAdjustFL);
Right = (s32) (Right * VolumeAdjustFR);
LeftBack = (s32) (LeftBack * VolumeAdjustBL);
RightBack = (s32) (RightBack * VolumeAdjustBR);
LeftSide = (s32) (LeftBack * VolumeAdjustSL);
RightSide = (s32) (RightBack * VolumeAdjustSR);
Center = (s32) (Center * VolumeAdjustC);
LFE = (s32) (LFE * VolumeAdjustLFE);
Left = (s32)(Left * VolumeAdjustFL);
Right = (s32)(Right * VolumeAdjustFR);
LeftBack = (s32)(LeftBack * VolumeAdjustBL);
RightBack = (s32)(RightBack * VolumeAdjustBR);
LeftSide = (s32)(LeftBack * VolumeAdjustSL);
RightSide = (s32)(RightBack * VolumeAdjustSR);
Center = (s32)(Center * VolumeAdjustC);
LFE = (s32)(LFE * VolumeAdjustLFE);
}
};
@ -461,18 +461,18 @@ struct Stereo20Out32
s32 Left;
s32 Right;
void ResampleFrom( const StereoOut32& src )
void ResampleFrom(const StereoOut32 &src)
{
Left = src.Left << SndOutVolumeShift32;
Right = src.Right << SndOutVolumeShift32;
}
void AdjustFrom(const StereoOut32& src)
void AdjustFrom(const StereoOut32 &src)
{
ResampleFrom(src);
Left = (s32) (Left * VolumeAdjustFL);
Right = (s32) (Right * VolumeAdjustFR);
Left = (s32)(Left * VolumeAdjustFL);
Right = (s32)(Right * VolumeAdjustFR);
}
};
@ -482,20 +482,20 @@ struct Stereo21Out32
s32 Right;
s32 LFE;
void ResampleFrom( const StereoOut32& src )
void ResampleFrom(const StereoOut32 &src)
{
Left = src.Left << SndOutVolumeShift32;
Right = src.Right << SndOutVolumeShift32;
LFE = (src.Left + src.Right) << (SndOutVolumeShift32 - 1);
}
void AdjustFrom(const StereoOut32& src)
void AdjustFrom(const StereoOut32 &src)
{
ResampleFrom(src);
Left = (s32) (Left * VolumeAdjustFL);
Right = (s32) (Right * VolumeAdjustFR);
LFE = (s32) (LFE * VolumeAdjustLFE);
Left = (s32)(Left * VolumeAdjustFL);
Right = (s32)(Right * VolumeAdjustFR);
LFE = (s32)(LFE * VolumeAdjustLFE);
}
};
@ -507,7 +507,7 @@ struct Stereo41Out32
s32 LeftBack;
s32 RightBack;
void ResampleFrom( const StereoOut32& src )
void ResampleFrom(const StereoOut32 &src)
{
Left = src.Left << SndOutVolumeShift32;
Right = src.Right << SndOutVolumeShift32;
@ -517,15 +517,15 @@ struct Stereo41Out32
RightBack = src.Right << SndOutVolumeShift32;
}
void AdjustFrom(const StereoOut32& src)
void AdjustFrom(const StereoOut32 &src)
{
ResampleFrom(src);
Left = (s32) (Left * VolumeAdjustFL);
Right = (s32) (Right * VolumeAdjustFR);
LeftBack = (s32) (LeftBack * VolumeAdjustBL);
RightBack = (s32) (RightBack * VolumeAdjustBR);
LFE = (s32) (LFE * VolumeAdjustLFE);
Left = (s32)(Left * VolumeAdjustFL);
Right = (s32)(Right * VolumeAdjustFR);
LeftBack = (s32)(LeftBack * VolumeAdjustBL);
RightBack = (s32)(RightBack * VolumeAdjustBR);
LFE = (s32)(LFE * VolumeAdjustLFE);
}
};
@ -538,7 +538,7 @@ struct Stereo51Out32
s32 LeftBack;
s32 RightBack;
void ResampleFrom( const StereoOut32& src )
void ResampleFrom(const StereoOut32 &src)
{
Left = src.Left << SndOutVolumeShift32;
Right = src.Right << SndOutVolumeShift32;
@ -548,16 +548,16 @@ struct Stereo51Out32
RightBack = src.Right << SndOutVolumeShift32;
}
void AdjustFrom(const StereoOut32& src)
void AdjustFrom(const StereoOut32 &src)
{
ResampleFrom(src);
Left = (s32) (Left * VolumeAdjustFL);
Right = (s32) (Right * VolumeAdjustFR);
LeftBack = (s32) (LeftBack * VolumeAdjustBL);
RightBack = (s32) (RightBack * VolumeAdjustBR);
Center = (s32) (Center * VolumeAdjustC);
LFE = (s32) (LFE * VolumeAdjustLFE);
Left = (s32)(Left * VolumeAdjustFL);
Right = (s32)(Right * VolumeAdjustFR);
LeftBack = (s32)(LeftBack * VolumeAdjustBL);
RightBack = (s32)(RightBack * VolumeAdjustBR);
Center = (s32)(Center * VolumeAdjustC);
LFE = (s32)(LFE * VolumeAdjustLFE);
}
};
@ -569,8 +569,8 @@ private:
static s32 m_predictData;
static float lastPct;
static StereoOut32* sndTempBuffer;
static StereoOut16* sndTempBuffer16;
static StereoOut32 *sndTempBuffer;
static StereoOut16 *sndTempBuffer16;
static int sndTempProgress;
static int m_dsp_progress;
@ -590,7 +590,7 @@ private:
static int ssFreeze;
static void _InitFail();
static bool CheckUnderrunStatus( int& nSamples, int& quietSampleCount );
static bool CheckUnderrunStatus(int &nSamples, int &quietSampleCount);
static void soundtouchInit();
static void soundtouchClearContents();
@ -599,15 +599,15 @@ private:
static void timeStretchUnderrun();
static s32 timeStretchOverrun();
static void PredictDataWrite( int samples );
static void PredictDataWrite(int samples);
static float GetStatusPct();
static void UpdateTempoChangeSoundTouch();
static void UpdateTempoChangeSoundTouch2();
static void _WriteSamples(StereoOut32* bData, int nSamples);
static void _WriteSamples(StereoOut32 *bData, int nSamples);
static void _WriteSamples_Safe(StereoOut32* bData, int nSamples);
static void _ReadSamples_Safe(StereoOut32* bData, int nSamples);
static void _WriteSamples_Safe(StereoOut32 *bData, int nSamples);
static void _ReadSamples_Safe(StereoOut32 *bData, int nSamples);
static void _WriteSamples_Internal(StereoOut32 *bData, int nSamples);
static void _DropSamples_Internal(int nSamples);
@ -619,7 +619,7 @@ public:
static void UpdateTempoChangeAsyncMixing();
static void Init();
static void Cleanup();
static void Write( const StereoOut32& Sample );
static void Write(const StereoOut32 &Sample);
static s32 Test();
static void ClearContents();
@ -627,8 +627,8 @@ public:
// 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 >
static void ReadSamples( T* bData );
template <typename T>
static void ReadSamples(T *bData);
};
class SndOutModule
@ -639,49 +639,49 @@ public:
// Returns a unique identification string for this driver.
// (usually just matches the driver's cpp filename)
virtual const wchar_t* GetIdent() const=0;
virtual const wchar_t *GetIdent() const = 0;
// Returns the long name / description for this driver.
// (for use in configuration screen)
virtual const wchar_t* GetLongName() const=0;
virtual const wchar_t *GetLongName() const = 0;
virtual s32 Init()=0;
virtual void Close()=0;
virtual s32 Test() const=0;
virtual s32 Init() = 0;
virtual void Close() = 0;
virtual s32 Test() const = 0;
// Gui function: Used to open the configuration box for this driver.
virtual void Configure(uptr parent)=0;
virtual void Configure(uptr parent) = 0;
// Loads settings from the INI file for this driver
virtual void ReadSettings()=0;
virtual void ReadSettings() = 0;
// Set output API for this driver
virtual void SetApiSettings(wxString api) =0;
virtual void SetApiSettings(wxString api) = 0;
// Saves settings to the INI file for this driver
virtual void WriteSettings() const=0;
virtual void WriteSettings() const = 0;
// Returns the number of empty samples in the output buffer.
// (which is effectively the amount of data played since the last update)
virtual int GetEmptySampleCount() =0;
virtual int GetEmptySampleCount() = 0;
};
#ifdef _MSC_VER
//internal
extern SndOutModule* WaveOut;
extern SndOutModule* DSoundOut;
extern SndOutModule* XAudio2_27_Out;
extern SndOutModule* XAudio2Out;
extern SndOutModule *WaveOut;
extern SndOutModule *DSoundOut;
extern SndOutModule *XAudio2_27_Out;
extern SndOutModule *XAudio2Out;
#endif
extern SndOutModule* PortaudioOut;
extern SndOutModule *PortaudioOut;
#if defined(SPU2X_SDL) || defined(SPU2X_SDL2)
extern SndOutModule * const SDLOut;
extern SndOutModule *const SDLOut;
#endif
#ifdef __linux__
extern SndOutModule* AlsaOut;
extern SndOutModule *AlsaOut;
#endif
extern SndOutModule* mods[];
extern SndOutModule *mods[];
// =====================================================================================================
@ -689,7 +689,7 @@ extern bool WavRecordEnabled;
extern void RecordStart();
extern void RecordStop();
extern void RecordWrite( const StereoOut16& sample );
extern void RecordWrite(const StereoOut16 &sample);
extern s32 DspLoadLibrary(wchar_t *fileName, int modNum);
extern void DspCloseLibrary();

View File

@ -30,11 +30,11 @@
#include "pa_win_wasapi.h"
#endif
int PaCallback( const void *inputBuffer, void *outputBuffer,
int PaCallback(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
const PaStreamCallbackTimeInfo *timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData );
void *userData);
class Portaudio : public SndOutModule
{
@ -62,42 +62,43 @@ private:
int actualUsedChannels;
bool started;
PaStream* stream;
PaStream *stream;
//////////////////////////////////////////////////////////////////////////////////////////
// Stuff necessary for speaker expansion
class SampleReader
{
public:
virtual int ReadSamples( const void *inputBuffer, void *outputBuffer,
virtual int ReadSamples(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
const PaStreamCallbackTimeInfo *timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData ) = 0;
void *userData) = 0;
};
template<class T>
template <class T>
class ConvertedSampleReader : public SampleReader
{
int* written;
int *written;
public:
ConvertedSampleReader(int* pWritten)
ConvertedSampleReader(int *pWritten)
{
written = pWritten;
}
virtual int ReadSamples( const void *inputBuffer, void *outputBuffer,
virtual int ReadSamples(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
const PaStreamCallbackTimeInfo *timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
void *userData)
{
T* p1 = (T*)outputBuffer;
T *p1 = (T *)outputBuffer;
int packets = framesPerBuffer / SndOutPacketSize;
for(int p=0; p<packets; p++, p1+=SndOutPacketSize )
SndBuffer::ReadSamples( p1 );
for (int p = 0; p < packets; p++, p1 += SndOutPacketSize)
SndBuffer::ReadSamples(p1);
(*written) += packets * SndOutPacketSize;
@ -106,7 +107,7 @@ private:
};
public:
SampleReader* ActualPaCallback;
SampleReader *ActualPaCallback;
Portaudio()
{
@ -116,7 +117,7 @@ public:
started = false;
stream = NULL;
ActualPaCallback = NULL;
m_ApiId=-1;
m_ApiId = -1;
m_SuggestedLatencyMS = 20;
actualUsedChannels = 0;
writtenSoFar = 0;
@ -126,113 +127,110 @@ public:
s32 Init()
{
started=false;
stream=NULL;
started = false;
stream = NULL;
ReadSettings();
PaError err = Pa_Initialize();
if( err != paNoError )
{
fprintf(stderr,"* SPU2-X: PortAudio error: %s\n", Pa_GetErrorText( err ) );
if (err != paNoError) {
fprintf(stderr, "* SPU2-X: PortAudio error: %s\n", Pa_GetErrorText(err));
return -1;
}
started=true;
started = true;
int deviceIndex = -1;
fprintf(stderr,"* SPU2-X: Enumerating PortAudio devices:\n");
for(int i=0, j=0;i<Pa_GetDeviceCount();i++)
{
const PaDeviceInfo * info = Pa_GetDeviceInfo(i);
fprintf(stderr, "* SPU2-X: Enumerating PortAudio devices:\n");
for (int i = 0, j = 0; i < Pa_GetDeviceCount(); i++) {
const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
if(info->maxOutputChannels > 0)
{
const PaHostApiInfo * apiinfo = Pa_GetHostApiInfo(info->hostApi);
if (info->maxOutputChannels > 0) {
const PaHostApiInfo *apiinfo = Pa_GetHostApiInfo(info->hostApi);
fprintf(stderr," *** Device %d: '%s' (%s)", j, info->name, apiinfo->name);
fprintf(stderr, " *** Device %d: '%s' (%s)", j, info->name, apiinfo->name);
if(apiinfo->type == m_ApiId)
{
if(m_Device == wxString::FromUTF8(info->name))
{
if (apiinfo->type == m_ApiId) {
if (m_Device == wxString::FromUTF8(info->name)) {
deviceIndex = i;
fprintf(stderr," (selected)");
fprintf(stderr, " (selected)");
}
}
fprintf(stderr,"\n");
fprintf(stderr, "\n");
j++;
}
}
fflush(stderr);
if(deviceIndex<0 && m_ApiId>=0)
{
for(int i=0;i<Pa_GetHostApiCount();i++)
{
const PaHostApiInfo * apiinfo = Pa_GetHostApiInfo(i);
if(apiinfo->type == m_ApiId)
{
if (deviceIndex < 0 && m_ApiId >= 0) {
for (int i = 0; i < Pa_GetHostApiCount(); i++) {
const PaHostApiInfo *apiinfo = Pa_GetHostApiInfo(i);
if (apiinfo->type == m_ApiId) {
deviceIndex = apiinfo->defaultOutputDevice;
}
}
}
if(deviceIndex>=0)
{
void* infoPtr = NULL;
if (deviceIndex >= 0) {
void *infoPtr = NULL;
const PaDeviceInfo * devinfo = Pa_GetDeviceInfo(deviceIndex);
const PaDeviceInfo *devinfo = Pa_GetDeviceInfo(deviceIndex);
int speakers;
switch(numSpeakers) // speakers = (numSpeakers + 1) *2; ?
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;
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;
}
actualUsedChannels = std::min(speakers, devinfo->maxOutputChannels);
switch( actualUsedChannels )
{
switch (actualUsedChannels) {
case 2:
ConLog( "* SPU2 > Using normal 2 speaker stereo output.\n" );
ConLog("* SPU2 > Using normal 2 speaker stereo output.\n");
ActualPaCallback = new ConvertedSampleReader<Stereo20Out32>(&writtenSoFar);
break;
case 3:
ConLog( "* SPU2 > 2.1 speaker expansion enabled.\n" );
ConLog("* SPU2 > 2.1 speaker expansion enabled.\n");
ActualPaCallback = new ConvertedSampleReader<Stereo21Out32>(&writtenSoFar);
break;
case 4:
ConLog( "* SPU2 > 4 speaker expansion enabled [quadraphenia]\n" );
ConLog("* SPU2 > 4 speaker expansion enabled [quadraphenia]\n");
ActualPaCallback = new ConvertedSampleReader<Stereo40Out32>(&writtenSoFar);
break;
case 5:
ConLog( "* SPU2 > 4.1 speaker expansion enabled.\n" );
ConLog("* SPU2 > 4.1 speaker expansion enabled.\n");
ActualPaCallback = new ConvertedSampleReader<Stereo41Out32>(&writtenSoFar);
break;
case 6:
case 7:
switch(dplLevel)
{
switch (dplLevel) {
case 0:
ConLog( "* SPU2 > 5.1 speaker expansion enabled.\n" );
ConLog("* SPU2 > 5.1 speaker expansion enabled.\n");
ActualPaCallback = new ConvertedSampleReader<Stereo51Out32>(&writtenSoFar); //"normal" stereo upmix
break;
case 1:
ConLog( "* SPU2 > 5.1 speaker expansion with basic ProLogic dematrixing enabled.\n" );
ConLog("* SPU2 > 5.1 speaker expansion with basic ProLogic dematrixing enabled.\n");
ActualPaCallback = new ConvertedSampleReader<Stereo51Out32Dpl>(&writtenSoFar); // basic Dpl decoder without rear stereo balancing
break;
case 2:
ConLog( "* SPU2 > 5.1 speaker expansion with experimental ProLogicII dematrixing enabled.\n" );
ConLog("* SPU2 > 5.1 speaker expansion with experimental ProLogicII dematrixing enabled.\n");
ActualPaCallback = new ConvertedSampleReader<Stereo51Out32DplII>(&writtenSoFar); //gigas PLII
break;
}
@ -240,7 +238,7 @@ public:
break;
default: // anything 8 or more gets the 7.1 treatment!
ConLog( "* SPU2 > 7.1 speaker expansion enabled.\n" );
ConLog("* SPU2 > 7.1 speaker expansion enabled.\n");
ActualPaCallback = new ConvertedSampleReader<Stereo71Out32>(&writtenSoFar);
actualUsedChannels = 8; // we do not support 7.2 or more, downgrade to 7.1
break;
@ -251,11 +249,9 @@ public:
sizeof(PaWasapiStreamInfo),
paWASAPI,
1,
paWinWasapiExclusive
};
paWinWasapiExclusive};
if((m_ApiId == paWASAPI) && m_WasapiExclusiveMode)
{
if ((m_ApiId == paWASAPI) && m_WasapiExclusiveMode) {
// Pass it the Exclusive mode enable flag
infoPtr = &info;
}
@ -271,9 +267,8 @@ public:
deviceIndex,
actualUsedChannels,
paInt32,
m_SuggestedLatencyMinimal?(SndOutPacketSize/(float)SampleRate):(m_SuggestedLatencyMS/1000.0f),
infoPtr
};
m_SuggestedLatencyMinimal ? (SndOutPacketSize / (float)SampleRate) : (m_SuggestedLatencyMS / 1000.0f),
infoPtr};
err = Pa_OpenStream(&stream,
NULL, &outParams, SampleRate,
@ -282,28 +277,24 @@ public:
PaCallback,
NULL);
}
else
{
err = Pa_OpenDefaultStream( &stream,
} else {
err = Pa_OpenDefaultStream(&stream,
0, actualUsedChannels, paInt32, 48000,
SndOutPacketSize,
PaCallback,
NULL );
NULL);
}
if( err != paNoError )
{
fprintf(stderr,"* SPU2-X: PortAudio error: %s\n", Pa_GetErrorText( err ) );
if (err != paNoError) {
fprintf(stderr, "* SPU2-X: PortAudio error: %s\n", Pa_GetErrorText(err));
Pa_Terminate();
return -1;
}
err = Pa_StartStream( stream );
if( err != paNoError )
{
fprintf(stderr,"* SPU2-X: PortAudio error: %s\n", Pa_GetErrorText( err ) );
err = Pa_StartStream(stream);
if (err != paNoError) {
fprintf(stderr, "* SPU2-X: PortAudio error: %s\n", Pa_GetErrorText(err));
Pa_CloseStream(stream);
stream=NULL;
stream = NULL;
Pa_Terminate();
return -1;
}
@ -314,22 +305,19 @@ public:
void Close()
{
PaError err;
if(started)
{
if(stream)
{
if(Pa_IsStreamActive(stream))
{
if (started) {
if (stream) {
if (Pa_IsStreamActive(stream)) {
err = Pa_StopStream(stream);
if( err != paNoError )
fprintf(stderr,"* SPU2-X: PortAudio error: %s\n", Pa_GetErrorText( err ) );
if (err != paNoError)
fprintf(stderr, "* SPU2-X: PortAudio error: %s\n", Pa_GetErrorText(err));
}
err = Pa_CloseStream(stream);
if( err != paNoError )
fprintf(stderr,"* SPU2-X: PortAudio error: %s\n", Pa_GetErrorText( err ) );
if (err != paNoError)
fprintf(stderr, "* SPU2-X: PortAudio error: %s\n", Pa_GetErrorText(err));
stream=NULL;
stream = NULL;
}
// Seems to do more harm than good.
@ -337,186 +325,165 @@ public:
//if( err != paNoError )
// fprintf(stderr,"* SPU2-X: PortAudio error: %s\n", Pa_GetErrorText( err ) );
started=false;
started = false;
}
}
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
#ifdef _WIN32
private:
bool _ConfigProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
bool _ConfigProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
int wmId,wmEvent;
int wmId, wmEvent;
int tSel = 0;
switch(uMsg)
{
case WM_INITDIALOG:
{
switch (uMsg) {
case WM_INITDIALOG: {
wchar_t temp[128];
SendMessage(GetDlgItem(hWnd,IDC_PA_DEVICE),CB_RESETCONTENT,0,0);
SendMessageA(GetDlgItem(hWnd,IDC_PA_DEVICE),CB_ADDSTRING,0,(LPARAM)"Default Device");
SendMessage(GetDlgItem(hWnd,IDC_PA_DEVICE),CB_SETCURSEL,0,0);
SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_RESETCONTENT, 0, 0);
SendMessageA(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_ADDSTRING, 0, (LPARAM) "Default Device");
SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_SETCURSEL, 0, 0);
SendMessage(GetDlgItem(hWnd,IDC_PA_HOSTAPI),CB_RESETCONTENT,0,0);
SendMessageA(GetDlgItem(hWnd,IDC_PA_HOSTAPI),CB_ADDSTRING,0,(LPARAM)"Unspecified");
SendMessage(GetDlgItem(hWnd, IDC_PA_HOSTAPI), CB_RESETCONTENT, 0, 0);
SendMessageA(GetDlgItem(hWnd, IDC_PA_HOSTAPI), CB_ADDSTRING, 0, (LPARAM) "Unspecified");
int idx = 0;
for(int i=0;i<Pa_GetHostApiCount();i++)
{
const PaHostApiInfo * apiinfo = Pa_GetHostApiInfo(i);
if(apiinfo->deviceCount > 0)
{
SendMessageA(GetDlgItem(hWnd,IDC_PA_HOSTAPI),CB_ADDSTRING,0,(LPARAM)apiinfo->name);
SendMessageA(GetDlgItem(hWnd,IDC_PA_HOSTAPI),CB_SETITEMDATA,i+1,apiinfo->type);
for (int i = 0; i < Pa_GetHostApiCount(); i++) {
const PaHostApiInfo *apiinfo = Pa_GetHostApiInfo(i);
if (apiinfo->deviceCount > 0) {
SendMessageA(GetDlgItem(hWnd, IDC_PA_HOSTAPI), CB_ADDSTRING, 0, (LPARAM)apiinfo->name);
SendMessageA(GetDlgItem(hWnd, IDC_PA_HOSTAPI), CB_SETITEMDATA, i + 1, apiinfo->type);
}
if(apiinfo->type == m_ApiId)
{
idx = i+1;
if (apiinfo->type == m_ApiId) {
idx = i + 1;
}
}
SendMessage(GetDlgItem(hWnd,IDC_PA_HOSTAPI),CB_SETCURSEL,idx,0);
SendMessage(GetDlgItem(hWnd, IDC_PA_HOSTAPI), CB_SETCURSEL, idx, 0);
if(idx > 0)
{
int api_idx = idx-1;
SendMessage(GetDlgItem(hWnd,IDC_PA_DEVICE),CB_RESETCONTENT,0,0);
SendMessageA(GetDlgItem(hWnd,IDC_PA_DEVICE),CB_ADDSTRING,0,(LPARAM)"Default Device");
SendMessage(GetDlgItem(hWnd,IDC_PA_DEVICE),CB_SETITEMDATA,0,0);
int _idx=0;
int i=1;
for(int j=0;j<Pa_GetDeviceCount();j++)
{
const PaDeviceInfo * info = Pa_GetDeviceInfo(j);
if(info->hostApi == api_idx && info->maxOutputChannels > 0)
{
SendMessage(GetDlgItem(hWnd,IDC_PA_DEVICE),CB_ADDSTRING,0,(LPARAM)wxString::FromUTF8(info->name).wc_str());
SendMessage(GetDlgItem(hWnd,IDC_PA_DEVICE),CB_SETITEMDATA,i,(LPARAM)info);
if(wxString::FromUTF8(info->name) == m_Device)
{
if (idx > 0) {
int api_idx = idx - 1;
SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_RESETCONTENT, 0, 0);
SendMessageA(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_ADDSTRING, 0, (LPARAM) "Default Device");
SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_SETITEMDATA, 0, 0);
int _idx = 0;
int i = 1;
for (int j = 0; j < Pa_GetDeviceCount(); j++) {
const PaDeviceInfo *info = Pa_GetDeviceInfo(j);
if (info->hostApi == api_idx && info->maxOutputChannels > 0) {
SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_ADDSTRING, 0, (LPARAM)wxString::FromUTF8(info->name).wc_str());
SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_SETITEMDATA, i, (LPARAM)info);
if (wxString::FromUTF8(info->name) == m_Device) {
_idx = i;
}
i++;
}
}
SendMessage(GetDlgItem(hWnd,IDC_PA_DEVICE),CB_SETCURSEL,_idx,0);
SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_SETCURSEL, _idx, 0);
}
INIT_SLIDER( IDC_LATENCY, 10, 200, 10, 1, 1 );
SendMessage(GetDlgItem(hWnd,IDC_LATENCY),TBM_SETPOS,TRUE,m_SuggestedLatencyMS);
swprintf_s(temp, L"%d ms",m_SuggestedLatencyMS);
SetWindowText(GetDlgItem(hWnd,IDC_LATENCY_LABEL),temp);
INIT_SLIDER(IDC_LATENCY, 10, 200, 10, 1, 1);
SendMessage(GetDlgItem(hWnd, IDC_LATENCY), TBM_SETPOS, TRUE, m_SuggestedLatencyMS);
swprintf_s(temp, L"%d ms", m_SuggestedLatencyMS);
SetWindowText(GetDlgItem(hWnd, IDC_LATENCY_LABEL), temp);
if(m_SuggestedLatencyMinimal)
SET_CHECK( IDC_MINIMIZE, true );
if (m_SuggestedLatencyMinimal)
SET_CHECK(IDC_MINIMIZE, true);
else
SET_CHECK( IDC_MANUAL, true );
SET_CHECK(IDC_MANUAL, true);
SET_CHECK( IDC_EXCLUSIVE, m_WasapiExclusiveMode );
}
break;
SET_CHECK(IDC_EXCLUSIVE, m_WasapiExclusiveMode);
} break;
case WM_COMMAND:
{
case WM_COMMAND: {
//wchar_t temp[128];
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDOK:
{
int idx = (int)SendMessage(GetDlgItem(hWnd,IDC_PA_HOSTAPI),CB_GETCURSEL,0,0);
m_ApiId = SendMessage(GetDlgItem(hWnd,IDC_PA_HOSTAPI),CB_GETITEMDATA,idx,0);
switch (wmId) {
case IDOK: {
int idx = (int)SendMessage(GetDlgItem(hWnd, IDC_PA_HOSTAPI), CB_GETCURSEL, 0, 0);
m_ApiId = SendMessage(GetDlgItem(hWnd, IDC_PA_HOSTAPI), CB_GETITEMDATA, idx, 0);
idx = (int)SendMessage(GetDlgItem(hWnd,IDC_PA_DEVICE),CB_GETCURSEL,0,0);
const PaDeviceInfo * info = (const PaDeviceInfo *)SendMessage(GetDlgItem(hWnd,IDC_PA_DEVICE),CB_GETITEMDATA,idx,0);
if(info)
m_Device = wxString::FromUTF8( info->name );
idx = (int)SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_GETCURSEL, 0, 0);
const PaDeviceInfo *info = (const PaDeviceInfo *)SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_GETITEMDATA, idx, 0);
if (info)
m_Device = wxString::FromUTF8(info->name);
else
m_Device = L"default";
m_SuggestedLatencyMS = (int)SendMessage( GetDlgItem( hWnd, IDC_LATENCY ), TBM_GETPOS, 0, 0 );
m_SuggestedLatencyMS = (int)SendMessage(GetDlgItem(hWnd, IDC_LATENCY), TBM_GETPOS, 0, 0);
if( m_SuggestedLatencyMS < 10 ) m_SuggestedLatencyMS = 10;
if( m_SuggestedLatencyMS > 200 ) m_SuggestedLatencyMS = 200;
if (m_SuggestedLatencyMS < 10)
m_SuggestedLatencyMS = 10;
if (m_SuggestedLatencyMS > 200)
m_SuggestedLatencyMS = 200;
m_SuggestedLatencyMinimal = SendMessage(GetDlgItem(hWnd,IDC_MINIMIZE),BM_GETCHECK,0,0)==BST_CHECKED;
m_SuggestedLatencyMinimal = SendMessage(GetDlgItem(hWnd, IDC_MINIMIZE), BM_GETCHECK, 0, 0) == BST_CHECKED;
m_WasapiExclusiveMode = SendMessage(GetDlgItem(hWnd,IDC_EXCLUSIVE),BM_GETCHECK,0,0)==BST_CHECKED;
m_WasapiExclusiveMode = SendMessage(GetDlgItem(hWnd, IDC_EXCLUSIVE), BM_GETCHECK, 0, 0) == BST_CHECKED;
EndDialog(hWnd,0);
}
break;
EndDialog(hWnd, 0);
} break;
case IDCANCEL:
EndDialog(hWnd,0);
EndDialog(hWnd, 0);
break;
case IDC_PA_HOSTAPI:
{
if(wmEvent == CBN_SELCHANGE)
{
int api_idx = (int)SendMessage(GetDlgItem(hWnd,IDC_PA_HOSTAPI),CB_GETCURSEL,0,0)-1;
int apiId = SendMessageA(GetDlgItem(hWnd,IDC_PA_HOSTAPI),CB_GETITEMDATA,api_idx,0);
SendMessage(GetDlgItem(hWnd,IDC_PA_DEVICE),CB_RESETCONTENT,0,0);
SendMessageA(GetDlgItem(hWnd,IDC_PA_DEVICE),CB_ADDSTRING,0,(LPARAM)"Default Device");
SendMessage(GetDlgItem(hWnd,IDC_PA_DEVICE),CB_SETITEMDATA,0,0);
int idx=0;
int i=1;
for(int j=0;j<Pa_GetDeviceCount();j++)
{
const PaDeviceInfo * info = Pa_GetDeviceInfo(j);
if(info->hostApi == api_idx && info->maxOutputChannels > 0)
{
SendMessage(GetDlgItem(hWnd,IDC_PA_DEVICE),CB_ADDSTRING,0,(LPARAM)wxString::FromUTF8(info->name).wc_str());
SendMessage(GetDlgItem(hWnd,IDC_PA_DEVICE),CB_SETITEMDATA,i,(LPARAM)info);
case IDC_PA_HOSTAPI: {
if (wmEvent == CBN_SELCHANGE) {
int api_idx = (int)SendMessage(GetDlgItem(hWnd, IDC_PA_HOSTAPI), CB_GETCURSEL, 0, 0) - 1;
int apiId = SendMessageA(GetDlgItem(hWnd, IDC_PA_HOSTAPI), CB_GETITEMDATA, api_idx, 0);
SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_RESETCONTENT, 0, 0);
SendMessageA(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_ADDSTRING, 0, (LPARAM) "Default Device");
SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_SETITEMDATA, 0, 0);
int idx = 0;
int i = 1;
for (int j = 0; j < Pa_GetDeviceCount(); j++) {
const PaDeviceInfo *info = Pa_GetDeviceInfo(j);
if (info->hostApi == api_idx && info->maxOutputChannels > 0) {
SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_ADDSTRING, 0, (LPARAM)wxString::FromUTF8(info->name).wc_str());
SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_SETITEMDATA, i, (LPARAM)info);
i++;
}
}
SendMessage(GetDlgItem(hWnd,IDC_PA_DEVICE),CB_SETCURSEL,idx,0);
SendMessage(GetDlgItem(hWnd, IDC_PA_DEVICE), CB_SETCURSEL, idx, 0);
}
}
break;
} break;
default:
return FALSE;
}
}
break;
} break;
case WM_HSCROLL:
{
case WM_HSCROLL: {
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch(wmId)
{
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:
{
wmEvent = (int)SendMessage((HWND)lParam, TBM_GETPOS, 0, 0);
case TB_THUMBTRACK: {
wchar_t temp[128];
if( wmEvent < 10 ) wmEvent = 10;
if( wmEvent > 200 ) wmEvent = 200;
SendMessage((HWND)lParam,TBM_SETPOS,TRUE,wmEvent);
swprintf_s(temp, L"%d ms",wmEvent);
SetWindowText(GetDlgItem(hWnd,IDC_LATENCY_LABEL),temp);
if (wmEvent < 10)
wmEvent = 10;
if (wmEvent > 200)
wmEvent = 200;
SendMessage((HWND)lParam, TBM_SETPOS, TRUE, wmEvent);
swprintf_s(temp, L"%d ms", wmEvent);
SetWindowText(GetDlgItem(hWnd, IDC_LATENCY_LABEL), temp);
break;
}
default:
return FALSE;
}
}
break;
} break;
default:
return FALSE;
@ -524,25 +491,23 @@ private:
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)
{
PaError err = Pa_Initialize(); // Initialization can be done multiple times, PA keeps a counter
if( err != paNoError )
{
fprintf(stderr,"* SPU2-X: PortAudio error: %s\n", Pa_GetErrorText( err ) );
if (err != paNoError) {
fprintf(stderr, "* SPU2-X: PortAudio error: %s\n", Pa_GetErrorText(err));
return;
}
// keep portaudio initialized until the dialog closes
INT_PTR ret;
ret=DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_PORTAUDIO),(HWND)parent,(DLGPROC)ConfigProc,1);
if(ret==-1)
{
MessageBox((HWND)parent,L"Error Opening the config dialog.",L"OMG ERROR!",MB_OK | MB_SETFOREGROUND);
ret = DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_PORTAUDIO), (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;
}
@ -571,105 +536,149 @@ public:
return playedSinceLastTime;
}
const wchar_t* GetIdent() const
const wchar_t *GetIdent() const
{
return L"portaudio";
}
const wchar_t* GetLongName() const
const wchar_t *GetLongName() const
{
return L"Portaudio (crossplatform)";
}
void ReadSettings()
{
wxString api( L"EMPTYEMPTYEMPTY" );
wxString api(L"EMPTYEMPTYEMPTY");
m_Device = L"EMPTYEMPTYEMPTY";
#ifdef __linux__
// By default on linux use the ALSA API (+99% users) -- Gregory
CfgReadStr( L"PORTAUDIO", L"HostApi", api, L"ALSA" );
CfgReadStr(L"PORTAUDIO", L"HostApi", api, L"ALSA");
#elif defined(__APPLE__)
// Suppose OSX only has CoreAudio...
CfgReadStr( L"PORTAUDIO", L"HostApi", api, L"CoreAudio" );
CfgReadStr(L"PORTAUDIO", L"HostApi", api, L"CoreAudio");
#else
CfgReadStr( L"PORTAUDIO", L"HostApi", api, L"WASAPI" );
CfgReadStr(L"PORTAUDIO", L"HostApi", api, L"WASAPI");
#endif
CfgReadStr( L"PORTAUDIO", L"Device", m_Device, L"default" );
CfgReadStr(L"PORTAUDIO", L"Device", m_Device, L"default");
SetApiSettings(api);
m_WasapiExclusiveMode = CfgReadBool( L"PORTAUDIO", L"Wasapi_Exclusive_Mode", false);
m_SuggestedLatencyMinimal = CfgReadBool( L"PORTAUDIO", L"Minimal_Suggested_Latency", true);
m_SuggestedLatencyMS = CfgReadInt( L"PORTAUDIO", L"Manual_Suggested_Latency_MS", 20);
m_WasapiExclusiveMode = CfgReadBool(L"PORTAUDIO", L"Wasapi_Exclusive_Mode", false);
m_SuggestedLatencyMinimal = CfgReadBool(L"PORTAUDIO", L"Minimal_Suggested_Latency", true);
m_SuggestedLatencyMS = CfgReadInt(L"PORTAUDIO", L"Manual_Suggested_Latency_MS", 20);
if( m_SuggestedLatencyMS < 10 ) m_SuggestedLatencyMS = 10;
if( m_SuggestedLatencyMS > 200 ) m_SuggestedLatencyMS = 200;
if (m_SuggestedLatencyMS < 10)
m_SuggestedLatencyMS = 10;
if (m_SuggestedLatencyMS > 200)
m_SuggestedLatencyMS = 200;
}
void SetApiSettings(wxString api)
{
m_ApiId = -1;
if(api == L"InDevelopment") m_ApiId = paInDevelopment; /* use while developing support for a new host API */
if(api == L"DirectSound") m_ApiId = paDirectSound;
if(api == L"MME") m_ApiId = paMME;
if(api == L"ASIO") m_ApiId = paASIO;
if(api == L"SoundManager") m_ApiId = paSoundManager;
if(api == L"CoreAudio") m_ApiId = paCoreAudio;
if(api == L"OSS") m_ApiId = paOSS;
if(api == L"ALSA") m_ApiId = paALSA;
if(api == L"AL") m_ApiId = paAL;
if(api == L"BeOS") m_ApiId = paBeOS;
if(api == L"WDMKS") m_ApiId = paWDMKS;
if(api == L"JACK") m_ApiId = paJACK;
if(api == L"WASAPI") m_ApiId = paWASAPI;
if(api == L"AudioScienceHPI") m_ApiId = paAudioScienceHPI;
if (api == L"InDevelopment")
m_ApiId = paInDevelopment; /* use while developing support for a new host API */
if (api == L"DirectSound")
m_ApiId = paDirectSound;
if (api == L"MME")
m_ApiId = paMME;
if (api == L"ASIO")
m_ApiId = paASIO;
if (api == L"SoundManager")
m_ApiId = paSoundManager;
if (api == L"CoreAudio")
m_ApiId = paCoreAudio;
if (api == L"OSS")
m_ApiId = paOSS;
if (api == L"ALSA")
m_ApiId = paALSA;
if (api == L"AL")
m_ApiId = paAL;
if (api == L"BeOS")
m_ApiId = paBeOS;
if (api == L"WDMKS")
m_ApiId = paWDMKS;
if (api == L"JACK")
m_ApiId = paJACK;
if (api == L"WASAPI")
m_ApiId = paWASAPI;
if (api == L"AudioScienceHPI")
m_ApiId = paAudioScienceHPI;
}
void WriteSettings() const
{
wxString api;
switch(m_ApiId)
{
case paInDevelopment: api = L"InDevelopment"; break; /* use while developing support for a new host API */
case paDirectSound: api = L"DirectSound"; break;
case paMME: api = L"MME"; break;
case paASIO: api = L"ASIO"; break;
case paSoundManager: api = L"SoundManager"; break;
case paCoreAudio: api = L"CoreAudio"; break;
case paOSS: api = L"OSS"; break;
case paALSA: api = L"ALSA"; break;
case paAL: api = L"AL"; break;
case paBeOS: api = L"BeOS"; break;
case paWDMKS: api = L"WDMKS"; break;
case paJACK: api = L"JACK"; break;
case paWASAPI: api = L"WASAPI"; break;
case paAudioScienceHPI: api = L"AudioScienceHPI"; break;
default: api = L"Unknown";
switch (m_ApiId) {
case paInDevelopment:
api = L"InDevelopment";
break; /* use while developing support for a new host API */
case paDirectSound:
api = L"DirectSound";
break;
case paMME:
api = L"MME";
break;
case paASIO:
api = L"ASIO";
break;
case paSoundManager:
api = L"SoundManager";
break;
case paCoreAudio:
api = L"CoreAudio";
break;
case paOSS:
api = L"OSS";
break;
case paALSA:
api = L"ALSA";
break;
case paAL:
api = L"AL";
break;
case paBeOS:
api = L"BeOS";
break;
case paWDMKS:
api = L"WDMKS";
break;
case paJACK:
api = L"JACK";
break;
case paWASAPI:
api = L"WASAPI";
break;
case paAudioScienceHPI:
api = L"AudioScienceHPI";
break;
default:
api = L"Unknown";
}
CfgWriteStr( L"PORTAUDIO", L"HostApi", api);
CfgWriteStr( L"PORTAUDIO", L"Device", m_Device);
CfgWriteStr(L"PORTAUDIO", L"HostApi", api);
CfgWriteStr(L"PORTAUDIO", L"Device", m_Device);
CfgWriteBool( L"PORTAUDIO", L"Wasapi_Exclusive_Mode", m_WasapiExclusiveMode);
CfgWriteBool( L"PORTAUDIO", L"Minimal_Suggested_Latency", m_SuggestedLatencyMinimal);
CfgWriteInt( L"PORTAUDIO", L"Manual_Suggested_Latency_MS", m_SuggestedLatencyMS);
CfgWriteBool(L"PORTAUDIO", L"Wasapi_Exclusive_Mode", m_WasapiExclusiveMode);
CfgWriteBool(L"PORTAUDIO", L"Minimal_Suggested_Latency", m_SuggestedLatencyMinimal);
CfgWriteInt(L"PORTAUDIO", L"Manual_Suggested_Latency_MS", m_SuggestedLatencyMS);
}
} static PA;
int PaCallback( const void *inputBuffer, void *outputBuffer,
int PaCallback(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
const PaStreamCallbackTimeInfo *timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
void *userData)
{
return PA.ActualPaCallback->ReadSamples(inputBuffer,outputBuffer,framesPerBuffer,timeInfo,statusFlags,userData);
return PA.ActualPaCallback->ReadSamples(inputBuffer, outputBuffer, framesPerBuffer, timeInfo, statusFlags, userData);
}
#ifdef _WIN32
BOOL CALLBACK Portaudio::ConfigProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
BOOL CALLBACK Portaudio::ConfigProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return PA._ConfigProc( hWnd, uMsg, wParam, lParam );
return PA._ConfigProc(hWnd, uMsg, wParam, lParam);
}
#endif

View File

@ -29,22 +29,24 @@
#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) {
void callback_fillBuffer(void *userdata, Uint8 *stream, int len)
{
Uint16 sdl_samples = samples;
#if SDL_MAJOR_VERSION >= 2
@ -57,17 +59,19 @@ namespace {
// Length should always be samples in bytes.
assert(len / sizeof(StereoOut_SDL) == sdl_samples);
for(Uint16 i = 0; i < sdl_samples; i += SndOutPacketSize)
for (Uint16 i = 0; i < sdl_samples; i += SndOutPacketSize)
SndBuffer::ReadSamples(&buffer[i]);
SDL_MixAudio(stream, (Uint8*) buffer.get() , len, SDL_MIX_MAXVOLUME);
}
SDL_MixAudio(stream, (Uint8 *)buffer.get(), len, SDL_MIX_MAXVOLUME);
}
}
struct SDLAudioMod : public SndOutModule {
struct SDLAudioMod : public SndOutModule
{
static SDLAudioMod mod;
std::string m_api;
s32 Init() {
s32 Init()
{
ReadSettings();
#if SDL_MAJOR_VERSION >= 2
@ -106,9 +110,9 @@ struct SDLAudioMod : public SndOutModule {
#endif
/* This is so ugly. It is hilariously ugly. I didn't use a vector to save reallocs. */
if(samples != spec.samples || buffer == NULL)
if (samples != spec.samples || buffer == NULL)
buffer = std::unique_ptr<StereoOut_SDL[]>(new StereoOut_SDL[spec.samples]);
if(samples != 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.
@ -119,10 +123,11 @@ struct SDLAudioMod : public SndOutModule {
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() {
void Close()
{
// Related to SDL_Init(SDL_INIT_AUDIO)
SDL_QuitSubSystem(SDL_INIT_AUDIO);
}
@ -134,17 +139,20 @@ struct SDLAudioMod : public SndOutModule {
void Configure(uptr parent) {}
void ReadSettings() {
void ReadSettings()
{
wxString api(L"EMPTYEMPTYEMPTY");
CfgReadStr(L"SDL", L"HostApi", api, L"pulseaudio");
SetApiSettings(api);
}
void WriteSettings() const {
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;
@ -163,11 +171,12 @@ struct SDLAudioMod : public SndOutModule {
}
private:
private:
SDL_AudioSpec spec;
SDLAudioMod() : m_api("pulseaudio"),
spec({SampleRate, format, channels, 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.
@ -177,4 +186,4 @@ struct SDLAudioMod : public SndOutModule {
SDLAudioMod SDLAudioMod::mod;
SndOutModule * const SDLOut = &SDLAudioMod::mod;
SndOutModule *const SDLOut = &SDLAudioMod::mod;

View File

@ -20,72 +20,77 @@
#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)
s2rfile = fopen(filename, "wb");
if (s2rfile)
s2r_write32(ticks);
return s2rfile?0:-1;
return s2rfile ? 0 : -1;
}
void s2r_readreg(u32 ticks,u32 addr)
void s2r_readreg(u32 ticks, u32 addr)
{
if(!s2rfile) return;
if (!s2rfile)
return;
s2r_write32(ticks);
EMITC(0,addr);
EMITC(0, addr);
}
void s2r_writereg(u32 ticks,u32 addr,s16 value)
void s2r_writereg(u32 ticks, u32 addr, s16 value)
{
if(!s2rfile) return;
if (!s2rfile)
return;
s2r_write32(ticks);
EMITC(1,addr);
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;
if (!s2rfile)
return;
s2r_write32(ticks);
EMITC(2,len);
for(i=0;i<len;i++,data++)
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;
if (!s2rfile)
return;
s2r_write32(ticks);
EMITC(3,len);
for(i=0;i<len;i++,data++)
EMITC(3, len);
for (i = 0; i < len; i++, data++)
s2r_write16(*data);
}
void s2r_close()
{
if(!s2rfile) return;
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,18 +115,18 @@ bool Running = false;
#ifdef _MSC_VER
int conprintf(const char* fmt, ...)
int conprintf(const char *fmt, ...)
{
#ifdef _WIN32
char s[1024];
va_list list;
va_start(list, fmt);
vsprintf(s,fmt, list);
vsprintf(s, fmt, list);
va_end(list);
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
if(handle == INVALID_HANDLE_VALUE)
if (handle == INVALID_HANDLE_VALUE)
return 0;
DWORD written = 0;
@ -132,7 +137,7 @@ int conprintf(const char* fmt, ...)
#else
va_list list;
va_start(list, fmt);
int ret = vsprintf(stderr,fmt,list);
int ret = vsprintf(stderr, fmt, list);
va_end(list);
return ret;
#endif
@ -160,9 +165,9 @@ u64 HighResFrequency()
{
u64 freq;
#ifdef _WIN32
QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
QueryPerformanceFrequency((LARGE_INTEGER *)&freq);
#else
// TODO
// TODO
#endif
return freq;
}
@ -171,9 +176,9 @@ u64 HighResCounter()
{
u64 time;
#ifdef _WIN32
QueryPerformanceCounter((LARGE_INTEGER*)&time);
QueryPerformanceCounter((LARGE_INTEGER *)&time);
#else
// TODO
// TODO
#endif
return time;
}
@ -185,19 +190,19 @@ void InitWaitSync() // not extremely accurate but enough.
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)
if (WaitTime > 10)
WaitTime = 10;
if(WaitTime == 0)
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
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;
@ -215,10 +220,11 @@ BOOL WINAPI HandlerRoutine(DWORD dwCtrlType)
#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;
@ -226,14 +232,11 @@ EXPORT_C_(void) s2r_replay(HWND hwnd, HINSTANCE hinst, LPSTR filename, int nCmdS
AllocConsole();
SetConsoleCtrlHandler(HandlerRoutine, TRUE);
conprintf("Playing %s file on %x...",filename,hwnd);
conprintf("Playing %s file on %x...", filename, hwnd);
if (IsWindows8OrGreater())
{
for (int n = 0; mods[n] != nullptr; ++n)
{
if (mods[n] == XAudio2_27_Out)
{
if (IsWindows8OrGreater()) {
for (int n = 0; mods[n] != nullptr; ++n) {
if (mods[n] == XAudio2_27_Out) {
mods[n] = XAudio2Out;
break;
}
@ -243,69 +246,69 @@ EXPORT_C_(void) s2r_replay(HWND hwnd, HINSTANCE hinst, LPSTR filename, int nCmdS
#endif
// load file
FILE *file=fopen(filename,"rb");
FILE *file = fopen(filename, "rb");
if(!file)
{
if (!file) {
conprintf("Could not open the replay file.");
return;
}
// if successful, init the plugin
// 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);
TryRead(&CurrentIOPCycle, 4, 1, file);
replay_mode=true;
replay_mode = true;
InitWaitSync(); // Initialize the WaitSync stuff
SPU2init();
SPU2irqCallback(dummy1,dummy4,dummy7);
SPU2irqCallback(dummy1, dummy4, dummy7);
SPU2setClockPtr(&CurrentIOPCycle);
SPU2open(&hwnd);
CurrentIOPCycle=0;
CurrentIOPCycle = 0;
SPU2async(0);
while(!feof(file) && Running)
{
u32 ccycle=0;
u32 evid=0;
u32 sval=0;
u32 tval=0;
while (!feof(file) && Running) {
u32 ccycle = 0;
u32 evid = 0;
u32 sval = 0;
u32 tval = 0;
TryRead(&ccycle,4,1,file);
TryRead(&sval,4,1,file);
TryRead(&ccycle, 4, 1, file);
TryRead(&sval, 4, 1, file);
evid=sval>>29;
sval&=0x1FFFFFFF;
evid = sval >> 29;
sval &= 0x1FFFFFFF;
u32 TargetCycle = ccycle * 768;
while(TargetCycle > CurrentIOPCycle)
{
while (TargetCycle > CurrentIOPCycle) {
u32 delta = WaitSync(TargetCycle);
SPU2async(delta);
}
switch(evid)
{
switch (evid) {
case 0:
SPU2read(sval);
break;
case 1:
TryRead(&tval,2,1,file);
SPU2write(sval,tval);
TryRead(&tval, 2, 1, file);
SPU2write(sval, tval);
break;
case 2:
TryRead(dmabuffer,sval,2,file);
SPU2writeDMA4Mem(dmabuffer,sval);
TryRead(dmabuffer, sval, 2, file);
SPU2writeDMA4Mem(dmabuffer, sval);
break;
case 3:
TryRead(dmabuffer,sval,2,file);
SPU2writeDMA7Mem(dmabuffer,sval);
TryRead(dmabuffer, sval, 2, file);
SPU2writeDMA7Mem(dmabuffer, sval);
break;
default:
// not implemented
@ -322,13 +325,13 @@ Finish:
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();
#endif
replay_mode=false;
replay_mode = false;
#endif
}
#endif

View File

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

View File

@ -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,7 +36,7 @@ float SndBuffer::lastEmergencyAdj;
float SndBuffer::cTempo = 1;
float SndBuffer::eTempo = 1;
void SndBuffer::PredictDataWrite( int samples )
void SndBuffer::PredictDataWrite(int samples)
{
m_predictData += samples;
}
@ -56,8 +56,8 @@ float SndBuffer::GetStatusPct()
//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);
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).
@ -102,13 +102,14 @@ int targetIPS=750;
//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){
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.
@ -122,8 +123,7 @@ float addToAvg(float 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;
unsigned int first = (nextAvgPos - actualWindow + AVERAGING_BUFFER_SIZE) % 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)
@ -132,7 +132,7 @@ float addToAvg(float val){
// 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++) {
for (unsigned int i = first; i < first + actualWindow; i++) {
sum += avg_fullness[i % AVERAGING_BUFFER_SIZE];
}
sum = sum / actualWindow;
@ -141,48 +141,49 @@ float addToAvg(float val){
}
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
long targetSamplesReservoir = 48 * SndOutLatencyMS; //48000*SndOutLatencyMS/1000
//base aim at buffer filled %
float baseTargetFullness=(double)targetSamplesReservoir;///(double)m_size;//0.05;
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;
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;
inside_hysteresis = false;
hys_ok_count = 0;
dynamicTargetFullness = baseTargetFullness;
}
int data = _GetApproximateDataInBuffer();
float bufferFullness=(float)data;///(float)m_size;
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();
{ //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);
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;
last = unow;
iters = 0;
}
iters++;
}
@ -191,10 +192,10 @@ void SndBuffer::UpdateTempoChangeSoundTouch2()
//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);
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 tempoAdjust = bufferFullness / dynamicTargetFullness;
float avgerage = addToAvg(tempoAdjust);
tempoAdjust = avgerage;
@ -204,50 +205,48 @@ void SndBuffer::UpdateTempoChangeSoundTouch2()
// 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);
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;
dynamicTargetFullness += (baseTargetFullness / tempoAdjust - dynamicTargetFullness) / (double)compensationDivider;
if (IsInRange(tempoAdjust, 0.9f, 1.1f) && IsInRange(dynamicTargetFullness, baseTargetFullness * 0.9f, baseTargetFullness * 1.1f))
dynamicTargetFullness = baseTargetFullness;
if( !inside_hysteresis )
{
if( IsInRange( tempoAdjust, 1.0f/hys_ok_factor, hys_ok_factor ) )
if (!inside_hysteresis) {
if (IsInRange(tempoAdjust, 1.0f / hys_ok_factor, hys_ok_factor))
hys_ok_count++;
else
hys_ok_count=0;
hys_ok_count = 0;
if( hys_ok_count >= hys_min_ok_count ){
inside_hysteresis=true;
if(MsgOverruns()) ConLog("======> stretch: None (1:1)\n");
if (hys_ok_count >= hys_min_ok_count) {
inside_hysteresis = true;
if (MsgOverruns())
ConLog("======> stretch: None (1:1)\n");
}
}
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;
} 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)
tempoAdjust=1.0;
if (inside_hysteresis)
tempoAdjust = 1.0;
if(MsgOverruns()){
static int iters=0;
static wxDateTime last=wxDateTime::UNow();
wxDateTime unow=wxDateTime::UNow();
if (MsgOverruns()) {
static int iters = 0;
static wxDateTime last = wxDateTime::UNow();
wxDateTime unow = wxDateTime::UNow();
wxTimeSpan delta = unow.Subtract(last);
if(delta.GetMilliseconds()>1000){//report buffers state and tempo adjust every second
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;
(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++;
}
@ -284,8 +283,7 @@ void SndBuffer::UpdateTempoChangeSoundTouch()
tempoChange = pctChange * 0.75f;
if( statusPct * tempoChange < 0.0f )
{
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.
@ -320,20 +318,19 @@ void SndBuffer::UpdateTempoChangeSoundTouch()
// 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 ||
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 )
{
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);
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:
emergencyAdj = (emergencyAdj * 0.75f) + (lastEmergencyAdj * 0.25f );
emergencyAdj = (emergencyAdj * 0.75f) + (lastEmergencyAdj * 0.25f);
lastEmergencyAdj = emergencyAdj;
lastPct = statusPct;
@ -345,29 +342,32 @@ void SndBuffer::UpdateTempoChangeSoundTouch()
// 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)
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 )
{
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",
//(relation < 0.0) ? "Normalize" : "",
@ -377,22 +377,17 @@ void SndBuffer::UpdateTempoChangeSoundTouch()
(int)(newTempo * 100.0),
(int)(statusPct * 100.0)
);*/
}
else
{
} else {
// Nominal operation -- turn off stretching.
// note: eTempo 'slides' toward 1.0 for smoother audio and better
// protection against spikes.
if( cTempo != 1.0f )
{
if (cTempo != 1.0f) {
cTempo = 1.0f;
eTempo = ( 1.0f + eTempo ) * 0.5f;
pSoundTouch->setTempo( eTempo );
}
else
{
if( eTempo != cTempo )
pSoundTouch->setTempo( eTempo=cTempo );
eTempo = (1.0f + eTempo) * 0.5f;
pSoundTouch->setTempo(eTempo);
} else {
if (eTempo != cTempo)
pSoundTouch->setTempo(eTempo = cTempo);
}
}
}
@ -403,20 +398,20 @@ void SndBuffer::UpdateTempoChangeAsyncMixing()
float statusPct = GetStatusPct();
lastPct = statusPct;
if( statusPct < -0.1f )
{
if (statusPct < -0.1f) {
TickInterval -= 4;
if( statusPct < -0.3f ) TickInterval = 64;
if( TickInterval < 64 ) TickInterval = 64;
if (statusPct < -0.3f)
TickInterval = 64;
if (TickInterval < 64)
TickInterval = 64;
//printf("-- %d, %f\n",TickInterval,statusPct);
}
else if( statusPct > 0.2f )
{
} else if (statusPct > 0.2f) {
TickInterval += 1;
if( TickInterval >= 7000 ) TickInterval = 7000;
if (TickInterval >= 7000)
TickInterval = 7000;
//printf("++ %d, %f\n",TickInterval,statusPct);
}
else TickInterval = 768;
} else
TickInterval = 768;
}
void SndBuffer::timeStretchUnderrun()
@ -426,8 +421,9 @@ void SndBuffer::timeStretchUnderrun()
cTempo -= (cTempo * 0.12f);
eTempo -= (eTempo * 0.30f);
if( eTempo < 0.1f ) eTempo = 0.1f;
// pSoundTouch->setTempo( eTempo );
if (eTempo < 0.1f)
eTempo = 0.1f;
// pSoundTouch->setTempo( eTempo );
//pSoundTouch->setTempoChange(-30); // temporary (until stretcher is called) slow down
}
@ -437,33 +433,34 @@ s32 SndBuffer::timeStretchOverrun()
// up audio playback.
cTempo += cTempo * 0.12f;
eTempo += eTempo * 0.40f;
if( eTempo > 7.5f ) eTempo = 7.5f;
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;
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 )
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 );
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 )
for (uint i = 0; i < size; ++i, ++dest, ++src)
*dest = (StereoOut32)*src;
}
@ -475,20 +472,19 @@ void SndBuffer::timeStretchWrite()
// 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 )
{
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
@ -496,7 +492,6 @@ void SndBuffer::timeStretchWrite()
#else
UpdateTempoChangeSoundTouch2();
#endif
}
void SndBuffer::soundtouchInit()
@ -505,10 +500,10 @@ void SndBuffer::soundtouchInit()
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);
@ -525,7 +520,8 @@ void SndBuffer::soundtouchInit()
// 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);
@ -540,5 +536,5 @@ void SndBuffer::soundtouchClearContents()
void SndBuffer::soundtouchCleanup()
{
safe_delete( pSoundTouch );
safe_delete(pSoundTouch);
}

View File

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

View File

@ -107,7 +107,6 @@ public:
void write(const short *buffer, ///< Pointer to sample data buffer.
int numElems ///< How many array items are to be written to file.
);
};
#endif

View File

@ -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] =
static const char *m_tbl_CoreOutputTypeNames[CoreSrc_Count] =
{
"Input",
"DryVoiceMix",
"WetVoiceMix",
"PreReverb",
"PostReverb",
"External"
};
"External"};
void Open()
{
if( !IsDevBuild ) return;
if( !WaveLog() ) return;
void Open()
{
if (!IsDevBuild)
return;
if (!WaveLog())
return;
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() );
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,22 +101,19 @@ using namespace Threading;
bool WavRecordEnabled = false;
static WavOutFile* m_wavrecord = NULL;
static WavOutFile *m_wavrecord = NULL;
static Mutex WavRecordMutex;
void RecordStart()
{
WavRecordEnabled = false;
try
{
ScopedLock lock( WavRecordMutex );
safe_delete( m_wavrecord );
m_wavrecord = new WavOutFile( "recording.wav", 48000, 16, 2 );
try {
ScopedLock lock(WavRecordMutex);
safe_delete(m_wavrecord);
m_wavrecord = new WavOutFile("recording.wav", 48000, 16, 2);
WavRecordEnabled = true;
}
catch( std::runtime_error& )
{
} 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");
}
@ -129,13 +122,14 @@ void RecordStart()
void RecordStop()
{
WavRecordEnabled = false;
ScopedLock lock( WavRecordMutex );
safe_delete( m_wavrecord );
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);
}

View File

@ -22,27 +22,24 @@
static LRESULT WINAPI AboutProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG:
{
switch (uMsg) {
case WM_INITDIALOG: {
wchar_t outstr[256];
if( IsDevBuild )
swprintf_s( outstr, L"Build %lld -- Compiled on " _T(__DATE__), SVN_REV );
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 );
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 );
SetWindowText(GetDlgItem(hDlg, IDC_LABEL_VERSION_INFO), outstr);
ShowWindow(hDlg, true);
}
return TRUE;
case WM_COMMAND:
switch( LOWORD(wParam) )
{
switch (LOWORD(wParam)) {
case IDOK:
EndDialog(hDlg, TRUE );
EndDialog(hDlg, TRUE);
return TRUE;
case IDC_LINK_WEBSITE:
@ -65,5 +62,5 @@ static LRESULT WINAPI AboutProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPar
void AboutBox()
{
DialogBox( hInstance, MAKEINTRESOURCE(IDD_ABOUT), GetActiveWindow(), (DLGPROC)AboutProc );
DialogBox(hInstance, MAKEINTRESOURCE(IDD_ABOUT), GetActiveWindow(), (DLGPROC)AboutProc);
}

View File

@ -28,22 +28,22 @@ void SysMessage(const char *fmt, ...)
char tmp[512];
wchar_t wtmp[512];
va_start(list,fmt);
vsprintf_s(tmp,fmt,list);
va_start(list, fmt);
vsprintf_s(tmp, fmt, list);
va_end(list);
swprintf_s(wtmp, L"%S", tmp);
MessageBox( (!!gsWindowHandle) ? (HWND)gsWindowHandle : GetActiveWindow(), wtmp,
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);
va_start(list, fmt);
wxString wtmp;
wtmp.PrintfV( fmt, list );
wtmp.PrintfV(fmt, list);
va_end(list);
MessageBox( (!!gsWindowHandle) ? (HWND)gsWindowHandle : GetActiveWindow(), wtmp,
MessageBox((!!gsWindowHandle) ? (HWND)gsWindowHandle : GetActiveWindow(), wtmp,
L"SPU2-X System Message", MB_OK | MB_SETFOREGROUND);
}
@ -51,11 +51,11 @@ void SysMessage(const wchar_t *fmt, ...)
#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,20 +74,20 @@ 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 );
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);
_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);
@ -99,50 +99,55 @@ 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};
GetPrivateProfileString( Section, Name, L"", Data, 255, CfgFile );
Data[254]=0;
if(wcslen(Data)==0) {
CfgWriteBool(Section,Name,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;
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);
if (wcslen(Data) == 0) {
CfgWriteInt(Section, Name, Default);
return Default;
}
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 };
TCHAR Data[255] = {0};
GetPrivateProfileString(Section, Name, L"", Data, 255, CfgFile);
Data[254] = 0;
@ -154,39 +159,39 @@ float CfgReadFloat(const TCHAR* Section, const TCHAR* Name, float Default)
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);
GetPrivateProfileString(Section, Name, L"", workspace, ArraySize(workspace), CfgFile);
Data = workspace;
if(Data.empty())
{
if (Data.empty()) {
Data = Default;
CfgWriteStr( Section, Name, 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;
TCHAR Data[24] = {0};
GetPrivateProfileString(Section, Name, L"", Data, 24, CfgFile);
Data[23] = 0;
if(wcslen(Data)==0) return false;
if (wcslen(Data) == 0)
return false;
return true;
}

View File

@ -85,12 +85,13 @@ 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);
@ -111,14 +112,14 @@ void ReadSettings()
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
if ((SynchMode == 0) && (SndOutLatencyMS < LATENCY_MIN_TS)) // can't use low-latency with timestretcher atm
SndOutLatencyMS = LATENCY_MIN_TS;
else if(SndOutLatencyMS < LATENCY_MIN)
else if (SndOutLatencyMS < LATENCY_MIN)
SndOutLatencyMS = LATENCY_MIN;
wchar_t omodid[128];
@ -126,22 +127,22 @@ void ReadSettings()
// 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());
// 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 );
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 );
CfgReadStr(L"WAVEOUT", L"Device", Config_WaveOut.Device, L"default");
Config_WaveOut.NumBuffers = CfgReadInt(L"WAVEOUT", L"Buffer_Count", 4);
DSoundOut->ReadSettings();
PortaudioOut->ReadSettings();
@ -152,14 +153,13 @@ void ReadSettings()
// Sanity Checks
// -------------
Clampify( SndOutLatencyMS, LATENCY_MIN, LATENCY_MAX );
Clampify(SndOutLatencyMS, LATENCY_MIN, LATENCY_MAX);
if( mods[OutputModule] == NULL )
{
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() );
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());
}
}
@ -167,11 +167,11 @@ void ReadSettings()
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);
@ -183,175 +183,162 @@ void WriteSettings()
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);
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);
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)
{
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_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_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_OUTPUT, CB_RESETCONTENT,0,0 );
SendDialogMsg(hWnd, IDC_OUTPUT, CB_RESETCONTENT, 0, 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 );
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_SETCURSEL, OutputModule, 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 );
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);
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_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);
int configvol = (int)(FinalVolume * 100 + 0.5f);
INIT_SLIDER( IDC_VOLUME_SLIDER, 0, 100, 10, 42, 1 );
INIT_SLIDER(IDC_VOLUME_SLIDER, 0, 100, 10, 42, 1);
SendDialogMsg( hWnd, IDC_VOLUME_SLIDER, TBM_SETPOS, TRUE, configvol );
swprintf_s(temp,L"%d%%",configvol);
SetWindowText(GetDlgItem(hWnd,IDC_VOLUME_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 );
EnableWindow(GetDlgItem(hWnd, IDC_OPEN_CONFIG_SOUNDTOUCH), (SynchMode == 0));
EnableWindow(GetDlgItem(hWnd, IDC_OPEN_CONFIG_DEBUG), DebugEnabled);
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;
} 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 );
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);
WriteSettings();
EndDialog(hWnd,0);
}
break;
EndDialog(hWnd, 0);
} break;
case IDCANCEL:
EndDialog(hWnd,0);
EndDialog(hWnd, 0);
break;
case IDC_OUTCONF:
{
const int module = (int)SendMessage(GetDlgItem(hWnd,IDC_OUTPUT),CB_GETCURSEL,0,0);
if( mods[module] == NULL ) 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;
} break;
case IDC_OPEN_CONFIG_DEBUG:
{
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;
} 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 );
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 );
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);
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;
} break;
case IDC_OPEN_CONFIG_SOUNDTOUCH:
SoundtouchCfg::OpenDialog( hWnd );
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 );
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:
@ -359,54 +346,48 @@ BOOL CALLBACK ConfigProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
}
break;
case WM_HSCROLL:
{
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)
int curpos = HIWORD( wParam );
int curpos = HIWORD(wParam);
switch( wmEvent )
{
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);
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)
);
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 );
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);
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);
if (hwndDlg == GetDlgItem(hWnd, IDC_VOLUME_SLIDER)) {
swprintf_s(temp, L"%d%%", curpos);
SetDlgItemText(hWnd, IDC_VOLUME_LABEL, temp);
}
break;
default:
return FALSE;
}
}
break;
} break;
default:
return FALSE;
@ -418,10 +399,9 @@ 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);
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();

View File

@ -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,66 +57,66 @@ 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 )
{
if (!LogLocationSetByPcsx2) {
LogsFolder = CfgLogsFolder;
DumpsFolder = CfgLogsFolder;
}
@ -125,131 +125,127 @@ void ReadSettings()
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);
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_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 );
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_DUMPCORE, DebugEnabled);
ENABLE_CONTROL(IDC_DUMPMEM, DebugEnabled);
ENABLE_CONTROL(IDC_DUMPREGS,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};
switch(uMsg)
{
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_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_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_DUMPCORE, _CoresDump);
SET_CHECK(IDC_DUMPMEM, _MemDump);
SET_CHECK(IDC_DUMPREGS,_RegDump);
SET_CHECK(IDC_DEBUG_VISUAL,_visual_debug_enabled);
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)
{
switch (wmId) {
case IDOK:
WriteSettings();
EndDialog(hWnd,0);
EndDialog(hWnd, 0);
break;
case IDCANCEL:
EndDialog(hWnd,0);
EndDialog(hWnd, 0);
break;
HANDLE_CHECKNB(IDC_MSGSHOW,_MsgToConsole);
EnableMessages( hWnd );
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);
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_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_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);
HANDLE_CHECK(IDC_DUMPREGS, _RegDump);
HANDLE_CHECK(IDC_DEBUG_VISUAL, _visual_debug_enabled);
default:
return FALSE;
}
@ -259,18 +255,15 @@ static BOOL CALLBACK DialogProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
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);
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();
}
}

View File

@ -34,90 +34,83 @@ 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();
}
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};
switch(uMsg)
{
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 );
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 )
{
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);
} else if (wmId == IDCANCEL) {
EndDialog(hWnd, 0);
}
break;
case WM_HSCROLL:
DoHandleScrollMessage( hWnd, wParam, lParam );
DoHandleScrollMessage(hWnd, wParam, lParam);
break;
default:
@ -126,12 +119,11 @@ BOOL CALLBACK SoundtouchCfg::DialogProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM
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)
{
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;
}

View File

@ -18,56 +18,56 @@
#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
{
@ -75,4 +75,3 @@ struct ds_device_data
GUID guid;
bool hasGuid;
};

View File

@ -18,28 +18,28 @@
#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));
}
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 },
{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);
@ -47,44 +47,41 @@ BOOL DrawRectangle(HDC dc, int left, int top, int width, int height)
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.
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);
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] );
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
@ -99,69 +96,64 @@ 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);
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;
if(vcd.displayPeak >= 32700) // leave a little bit of margin
if (vcd.displayPeak >= 32700) // leave a little bit of margin
{
SetDCBrushColor(hdc,RGB( 255, 0, 0));
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++)
{
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) {
y = val;
} else
val = -val;
if(val!=0)
{
FillRectangle(hdc,IX+90+i,IY+24-y, 1, val);
if (val != 0) {
FillRectangle(hdc, IX + 90 + i, IY + 24 - y, 1, val);
}
}
}
SetTextColor(hdc,RGB( 0,255, 0));
SetBkColor (hdc,RGB( 0, 0, 0));
SetTextColor(hdc, RGB(0, 255, 0));
SetBkColor(hdc, RGB(0, 0, 0));
static wchar_t t[256];
swprintf_s(t,L"%06x",vc.StartA);
TextOut(hdc,IX+4,IY+4,t,6);
swprintf_s(t, L"%06x", vc.StartA);
TextOut(hdc, IX + 4, IY + 4, t, 6);
swprintf_s(t,L"%06x",vc.NextA);
TextOut(hdc,IX+4,IY+18,t,6);
swprintf_s(t, L"%06x", vc.NextA);
TextOut(hdc, IX + 4, IY + 18, t, 6);
swprintf_s(t,L"%06x",vc.LoopStartA);
TextOut(hdc,IX+4,IY+32,t,6);
swprintf_s(t, L"%06x", vc.LoopStartA);
TextOut(hdc, IX + 4, IY + 32, t, 6);
vcd.displayPeak = 0;
}
@ -170,103 +162,95 @@ void UpdateDebugDialog()
int JX = 8 + c * 256;
int JY = 584;
SetDCBrushColor(hdc,RGB( 0, 0, 0));
SetDCPenColor(hdc,RGB( 255, 128, 32));
SetDCBrushColor(hdc, RGB(0, 0, 0));
SetDCPenColor(hdc, RGB(255, 128, 32));
FillRectangle(hdc,JX,JY,252,60);
DrawRectangle(hdc,JX,JY,252,60);
FillRectangle(hdc, JX, JY, 252, 60);
DrawRectangle(hdc, JX, JY, 252, 60);
SetTextColor(hdc,RGB(255,255,255));
SetBkColor (hdc,RGB( 0, 0, 0));
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);
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));
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);
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);
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);
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.FxEnable) {
FillRectangle(hdc, JX + 40, JY + 4, 10, 10);
}
if(cx.IRQEnable)
{
FillRectangle(hdc,JX+40,JY+18,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.AutoDMACtrl != 0) {
FillRectangle(hdc, JX + 40, JY + 32, 10, 10);
for(int j=0;j<64;j++)
{
int i=j*256/64;
for (int j = 0; j < 64; j++) {
int i = j * 256 / 64;
int val = (cd.admaWaveformL[i] * 26) / 32768;
int y=0;
int y = 0;
if(val>0)
y=val;
if (val > 0)
y = val;
else
val=-val;
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;
for (int j = 0; j < 64; j++) {
int i = j * 256 / 64;
int val = (cd.admaWaveformR[i] * 26) / 32768;
int y=0;
int y = 0;
if(val>0)
y=val;
if (val > 0)
y = val;
else
val=-val;
val = -val;
if(val!=0)
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
{
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);
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);
TextOut(hdc, JX + 64, JY + 46, t, wcslen(t));
FillRectangle(hdc, JX + 40, JY + 46, 10, 10);
cd.dmaFlag--;
}
}
ReleaseDC(hDebugDialog,hdc);
lCount=0;
ReleaseDC(hDebugDialog, hdc);
lCount = 0;
}
MSG msg;
while(PeekMessage(&msg,hDebugDialog,0,0,PM_REMOVE))
{
while (PeekMessage(&msg, hDebugDialog, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}

View File

@ -53,48 +53,46 @@ private:
HANDLE thread;
DWORD tid;
IDirectSound8* dsound;
IDirectSoundBuffer8* buffer;
IDirectSoundNotify8* buffer_notify;
IDirectSound8 *dsound;
IDirectSoundBuffer8 *buffer;
IDirectSoundNotify8 *buffer_notify;
HANDLE buffer_events[MAX_BUFFER_COUNT];
WAVEFORMATEX wfx;
HANDLE waitEvent;
template< typename T >
static DWORD CALLBACK RThread( DSound* obj )
template <typename T>
static DWORD CALLBACK RThread(DSound *obj)
{
return obj->Thread<T>();
}
template< typename T >
template <typename T>
DWORD CALLBACK Thread()
{
static const int BufferSizeBytes = BufferSize * sizeof( T );
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;
T *p1, *oldp1;
LPVOID p2;
DWORD s1,s2;
DWORD s1, s2;
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 );
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;
@ -105,31 +103,28 @@ private:
public:
s32 Init()
{
CoInitializeEx( NULL, COINIT_MULTITHREADED );
CoInitializeEx(NULL, COINIT_MULTITHREADED);
//
// 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& )
{
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(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 >_<
@ -137,7 +132,7 @@ public:
DWORD speakerConfig = 2;
//dsound->GetSpeakerConfig( &speakerConfig );
IDirectSoundBuffer* buffer_;
IDirectSoundBuffer *buffer_;
DSBUFFERDESC desc;
// Set up WAV format structure.
@ -147,7 +142,7 @@ public:
wfx.nSamplesPerSec = SampleRate;
wfx.nChannels = (WORD)speakerConfig;
wfx.wBitsPerSample = 16;
wfx.nBlockAlign = 2*(WORD)speakerConfig;
wfx.nBlockAlign = 2 * (WORD)speakerConfig;
wfx.nAvgBytesPerSec = SampleRate * wfx.nBlockAlign;
wfx.cbSize = 0;
@ -167,52 +162,49 @@ public:
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 )
{
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." );
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." );
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) );
verifyc(buffer->QueryInterface(IID_IDirectSoundNotify8, (void **)&buffer_notify));
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;
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));
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);
thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RThread<StereoOut16>, this, 0, &tid);
SetThreadPriority(thread, THREAD_PRIORITY_ABOVE_NORMAL);
return 0;
}
@ -220,114 +212,99 @@ public:
void Close()
{
// Stop Thread
fprintf(stderr,"* SPU2-X: Waiting for DSound thread to finish...");
dsound_running=false;
fprintf(stderr, "* SPU2-X: Waiting for DSound thread to finish...");
dsound_running = false;
WaitForSingleObject(thread,INFINITE);
WaitForSingleObject(thread, INFINITE);
CloseHandle(thread);
fprintf(stderr," Done.\n");
fprintf(stderr, " Done.\n");
//
// Clean up
//
if( buffer != NULL )
{
if (buffer != NULL) {
buffer->Stop();
for(u32 i=0;i<m_NumBuffers;i++)
{
if( 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 );
safe_release(dsound);
CoUninitialize();
}
private:
bool _DSEnumCallback( LPGUID lpGuid, LPCTSTR lpcstrDescription, LPCTSTR lpcstrModule, LPVOID lpContext )
bool _DSEnumCallback(LPGUID lpGuid, LPCTSTR lpcstrDescription, LPCTSTR lpcstrModule, LPVOID lpContext)
{
m_devices[ndevs].name = lpcstrDescription;
if(lpGuid)
{
if (lpGuid) {
m_devices[ndevs].guid = *lpGuid;
m_devices[ndevs].hasGuid = true;
}
else
{
} else {
m_devices[ndevs].hasGuid = false;
}
ndevs++;
if(ndevs<32) return TRUE;
if (ndevs < 32)
return TRUE;
return FALSE;
}
bool _ConfigProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
bool _ConfigProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
int wmId,wmEvent;
int wmId, wmEvent;
int tSel = 0;
switch(uMsg)
{
case WM_INITDIALOG:
{
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);
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 = -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:
{
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);
switch (wmId) {
case IDOK: {
int i = (int)SendMessage(GetDlgItem(hWnd, IDC_DS_DEVICE), CB_GETCURSEL, 0, 0);
if(!m_devices[i].hasGuid)
{
if (!m_devices[i].hasGuid) {
m_Device[0] = 0; // clear device name to ""
}
else
{
} 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,
@ -339,61 +316,58 @@ private:
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_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);
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;
} break;
case WM_HSCROLL:
{
case WM_HSCROLL: {
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch(wmId)
{
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:
{
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);
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;
} break;
default:
return FALSE;
@ -401,17 +375,16 @@ private:
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);
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;
}
}
@ -424,35 +397,35 @@ public:
int GetEmptySampleCount()
{
DWORD play, write;
buffer->GetCurrentPosition( &play, &write );
buffer->GetCurrentPosition(&play, &write);
// Note: Dsound's write cursor is bogus. Use our own instead:
int empty = play - myLastWrite;
if( empty < 0 )
if (empty < 0)
empty = -empty;
return empty / 2;
}
const wchar_t* GetIdent() const
const wchar_t *GetIdent() const
{
return L"dsound";
}
const wchar_t* GetLongName() const
const wchar_t *GetLongName() const
{
return L"DirectSound (nice)";
}
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 );
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);
Clampify( m_NumBuffers, (u8)3, (u8)8 );
Clampify(m_NumBuffers, (u8)3, (u8)8);
}
void SetApiSettings(wxString api)
@ -461,23 +434,23 @@ public:
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 );
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;

View File

@ -26,10 +26,10 @@
namespace Exception
{
class XAudio2Error : public std::runtime_error
{
protected:
static const char* SomeKindaErrorString(HRESULT hr)
class XAudio2Error : public std::runtime_error
{
protected:
static const char *SomeKindaErrorString(HRESULT hr)
{
switch (hr) {
case XAUDIO2_E_INVALID_CALL:
@ -41,26 +41,26 @@ namespace Exception
return "Unknown error code!";
}
public:
public:
const HRESULT ErrorCode;
std::string m_Message;
const char* CMessage() const
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()
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));
@ -74,8 +74,8 @@ private:
class BaseStreamingVoice : public IXAudio2VoiceCallback
{
protected:
IXAudio2SourceVoice* pSourceVoice;
s16* qbuffer;
IXAudio2SourceVoice *pSourceVoice;
s16 *qbuffer;
const uint m_nBuffers;
const uint m_nChannels;
@ -96,20 +96,20 @@ private:
{
}
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)
void _init(IXAudio2 *pXAudio2, uint chanConfig)
{
WAVEFORMATEXTENSIBLE wfx;
@ -129,7 +129,7 @@ private:
// Create an XAudio2 voice to stream this wave
//
HRESULT hr;
if (FAILED(hr = pXAudio2->CreateSourceVoice(&pSourceVoice, (WAVEFORMATEX*)&wfx,
if (FAILED(hr = pXAudio2->CreateSourceVoice(&pSourceVoice, (WAVEFORMATEX *)&wfx,
XAUDIO2_VOICE_NOSRC, 1.0f, this))) {
throw Exception::XAudio2Error(hr, "XAudio2 CreateSourceVoice failure.");
}
@ -146,37 +146,44 @@ private:
// Start some buffers.
for (uint i = 0; i < m_nBuffers; i++) {
XAUDIO2_BUFFER buf = { 0 };
XAUDIO2_BUFFER buf = {0};
buf.AudioBytes = m_BufferSizeBytes;
buf.pContext = &qbuffer[i*m_BufferSize];
buf.pAudioData = (BYTE*)buf.pContext;
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) {}
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 >
template <typename T>
class StreamingVoice : public BaseStreamingVoice
{
public:
StreamingVoice(IXAudio2* pXAudio2) :
BaseStreamingVoice(sizeof(T) / sizeof(s16))
StreamingVoice(IXAudio2 *pXAudio2)
: BaseStreamingVoice(sizeof(T) / sizeof(s16))
{
}
virtual ~StreamingVoice()
{
IXAudio2SourceVoice* killMe = pSourceVoice;
IXAudio2SourceVoice *killMe = pSourceVoice;
pSourceVoice = NULL;
killMe->FlushSourceBuffers();
killMe->DestroyVoice();
@ -187,23 +194,38 @@ private:
DeleteCriticalSection(&cs);
}
void Init(IXAudio2* pXAudio2)
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;
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)
STDMETHOD_(void, OnBufferEnd)
(void *context)
{
EnterCriticalSection(&cs);
@ -213,30 +235,28 @@ private:
return;
}
T* qb = (T*)context;
T *qb = (T *)context;
for (int p = 0; p < PacketsPerBuffer; p++, qb += SndOutPacketSize)
SndBuffer::ReadSamples(qb);
XAUDIO2_BUFFER buf = { 0 };
XAUDIO2_BUFFER buf = {0};
buf.AudioBytes = m_BufferSizeBytes;
buf.pAudioData = (BYTE*)context;
buf.pAudioData = (BYTE *)context;
buf.pContext = context;
pSourceVoice->SubmitSourceBuffer(&buf);
LeaveCriticalSection(&cs);
}
};
HMODULE xAudio2DLL;
decltype(&XAudio2Create) pXAudio2Create;
CComPtr<IXAudio2> pXAudio2;
IXAudio2MasteringVoice* pMasteringVoice;
BaseStreamingVoice* voiceContext;
IXAudio2MasteringVoice *pMasteringVoice;
BaseStreamingVoice *voiceContext;
public:
s32 Init()
{
HRESULT hr;
@ -267,11 +287,20 @@ public:
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;
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;
}
//
@ -329,7 +358,7 @@ public:
}
voiceContext->Init(pXAudio2);
} catch (Exception::XAudio2Error& ex) {
} catch (Exception::XAudio2Error &ex) {
SysMessage(ex.CMessage());
pXAudio2.Release();
CoUninitialize();
@ -371,16 +400,17 @@ public:
int GetEmptySampleCount()
{
if (voiceContext == NULL) return 0;
if (voiceContext == NULL)
return 0;
return voiceContext->GetEmptySampleCount();
}
const wchar_t* GetIdent() const
const wchar_t *GetIdent() const
{
return L"xaudio2";
}
const wchar_t* GetLongName() const
const wchar_t *GetLongName() const
{
return L"XAudio 2 (Recommended)";
}

View File

@ -24,13 +24,12 @@
namespace Exception
{
class XAudio2_27Error : public std::runtime_error
{
protected:
static const char* SomeKindaErrorString( HRESULT hr )
{
switch( hr )
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.";
@ -40,31 +39,31 @@ namespace Exception
return "Unknown error code!";
}
public:
public:
const HRESULT ErrorCode;
std::string m_Message;
const char* CMessage() const
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()
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 ) );
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));
static const double SndOutNormalizer = (double)(1UL << (SndOutVolumeShift + 16));
class XAudio2_27_Mod: public SndOutModule
class XAudio2_27_Mod : public SndOutModule
{
private:
static const int PacketsPerBuffer = 8;
@ -73,8 +72,8 @@ private:
class BaseStreamingVoice : public IXAudio2VoiceCallback
{
protected:
IXAudio2SourceVoice* pSourceVoice;
s16* qbuffer;
IXAudio2SourceVoice *pSourceVoice;
s16 *qbuffer;
const uint m_nBuffers;
const uint m_nChannels;
@ -87,28 +86,28 @@ private:
int GetEmptySampleCount()
{
XAUDIO2_VOICE_STATE state;
pSourceVoice->GetState( &state );
return state.SamplesPlayed & (m_BufferSize-1);
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) )
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 )
void _init(IXAudio2 *pXAudio2, uint chanConfig)
{
WAVEFORMATEXTENSIBLE wfx;
@ -117,9 +116,9 @@ private:
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.nBlockAlign = wfx.Format.nChannels * wfx.Format.wBitsPerSample / 8;
wfx.Format.nAvgBytesPerSec = SampleRate * wfx.Format.nBlockAlign;
wfx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
wfx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
wfx.Samples.wValidBitsPerSample = 16;
wfx.dwChannelMask = chanConfig;
wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
@ -128,127 +127,143 @@ private:
// 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." );
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 );
InitializeCriticalSection(&cs);
EnterCriticalSection(&cs);
pSourceVoice->FlushSourceBuffers();
pSourceVoice->Start( 0, 0 );
pSourceVoice->Start(0, 0);
qbuffer = new s16[m_nBuffers * m_BufferSize];
ZeroMemory( qbuffer, m_BufferSizeBytes * m_nBuffers );
ZeroMemory(qbuffer, m_BufferSizeBytes * m_nBuffers);
// Start some buffers.
for( uint i=0; i<m_nBuffers; i++ )
{
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 );
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 >
template <typename T>
class StreamingVoice : public BaseStreamingVoice
{
public:
StreamingVoice( IXAudio2* pXAudio2 ) :
BaseStreamingVoice( sizeof(T) / sizeof( s16 ) )
StreamingVoice(IXAudio2 *pXAudio2)
: BaseStreamingVoice(sizeof(T) / sizeof(s16))
{
}
virtual ~StreamingVoice()
{
IXAudio2SourceVoice* killMe = pSourceVoice;
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 )
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;
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 );
_init(pXAudio2, chanMask);
}
protected:
STDMETHOD_(void, OnBufferEnd) ( void* context )
STDMETHOD_(void, OnBufferEnd)
(void *context)
{
EnterCriticalSection( &cs );
EnterCriticalSection(&cs);
// All of these checks are necessary because XAudio2 is wonky shizat.
if( pSourceVoice == NULL || context == NULL )
{
LeaveCriticalSection( &cs );
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.pAudioData = (BYTE *)context;
buf.pContext = context;
pSourceVoice->SubmitSourceBuffer( &buf );
LeaveCriticalSection( &cs );
pSourceVoice->SubmitSourceBuffer(&buf);
LeaveCriticalSection(&cs);
}
};
HMODULE xAudio2DLL;
CComPtr<IXAudio2> pXAudio2;
IXAudio2MasteringVoice* pMasteringVoice;
BaseStreamingVoice* voiceContext;
IXAudio2MasteringVoice *pMasteringVoice;
BaseStreamingVoice *voiceContext;
public:
s32 Init()
{
HRESULT hr;
pxAssume( pXAudio2 == NULL );
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
// 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");
#else
@ -258,103 +273,105 @@ public:
//
// Initialize XAudio2
//
CoInitializeEx( NULL, COINIT_MULTITHREADED );
CoInitializeEx(NULL, COINIT_MULTITHREADED);
UINT32 flags = 0;
if( IsDebugBuild )
if (IsDebugBuild)
flags |= XAUDIO2_DEBUG_ENGINE;
try
{
if ( FAILED(hr = XAudio2Create( &pXAudio2, flags ) ) )
throw Exception::XAudio2_27Error( hr,
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:"
);
"DirectX / WaveOut drivers instead. Error Details:");
XAUDIO2_DEVICE_DETAILS deviceDetails;
pXAudio2->GetDeviceDetails( 0, &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.
int speakers;
switch(numSpeakers) // speakers = (numSpeakers + 1) *2; ?
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;
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 );
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 );
if (FAILED(hr = pXAudio2->CreateMasteringVoice(&pMasteringVoice, speakers, SampleRate))) {
SysMessage("Failed creating mastering voice: %#X\n", hr);
CoUninitialize();
return -1;
}
switch( speakers )
{
switch (speakers) {
case 2:
ConLog( "* SPU2 > Using normal 2 speaker stereo output.\n" );
voiceContext = new StreamingVoice<StereoOut16>( pXAudio2 );
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 );
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 );
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 );
ConLog("* SPU2 > 4.1 speaker expansion enabled.\n");
voiceContext = new StreamingVoice<Stereo41Out16>(pXAudio2);
break;
case 6:
case 7:
switch(dplLevel)
{
switch (dplLevel) {
case 0:
ConLog( "* SPU2 > 5.1 speaker expansion enabled.\n" );
voiceContext = new StreamingVoice<Stereo51Out16>( pXAudio2 ); //"normal" stereo upmix
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
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
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 );
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() );
voiceContext->Init(pXAudio2);
} catch (Exception::XAudio2_27Error &ex) {
SysMessage(ex.CMessage());
pXAudio2.Release();
CoUninitialize();
return -1;
@ -374,11 +391,11 @@ public:
// 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;
if( pMasteringVoice != NULL )
if (pMasteringVoice != NULL)
pMasteringVoice->DestroyVoice();
pMasteringVoice = NULL;
@ -403,16 +420,17 @@ public:
int GetEmptySampleCount()
{
if( voiceContext == NULL ) return 0;
if (voiceContext == NULL)
return 0;
return voiceContext->GetEmptySampleCount();
}
const wchar_t* GetIdent() const
const wchar_t *GetIdent() const
{
return L"xaudio2";
}
const wchar_t* GetLongName() const
const wchar_t *GetLongName() const
{
return L"XAudio 2.7 (Recommended)";
}

View File

@ -19,22 +19,22 @@
#include "Dialogs.h"
class WaveOutModule: public SndOutModule
class WaveOutModule : public SndOutModule
{
private:
static const uint MAX_BUFFER_COUNT = 8;
static const int PacketsPerBuffer = (1024 / SndOutPacketSize);
static const int BufferSize = SndOutPacketSize*PacketsPerBuffer;
static const int BufferSize = SndOutPacketSize * PacketsPerBuffer;
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;
@ -42,32 +42,31 @@ private:
wchar_t ErrText[256];
template< typename T >
template <typename T>
DWORD CALLBACK Thread()
{
static const int BufferSizeBytes = BufferSize * sizeof( T );
static const int BufferSizeBytes = BufferSize * sizeof(T);
while( waveout_running )
{
while (waveout_running) {
bool didsomething = false;
for(u32 i=0;i<numBuffers;i++)
{
if(!(whbuffer[i].dwFlags & WHDR_DONE) ) continue;
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;
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) );
waveOutWrite(hwodevice, buf, sizeof(WAVEHDR));
didsomething = true;
}
if( didsomething )
if (didsomething)
Sleep(1);
else
Sleep(0);
@ -75,8 +74,8 @@ private:
return 0;
}
template< typename T >
static DWORD CALLBACK RThread(WaveOutModule*obj)
template <typename T>
static DWORD CALLBACK RThread(WaveOutModule *obj)
{
return obj->Thread<T>();
}
@ -88,11 +87,12 @@ public:
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,7 +129,7 @@ public:
speakerConfig = 8;
break;
}
#endif
#endif
wformat.wFormatTag = WAVE_FORMAT_PCM;
wformat.nSamplesPerSec = SampleRate;
@ -139,30 +139,28 @@ public:
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);
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;
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
@ -171,7 +169,7 @@ public:
// 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);
thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RThread<StereoOut16>, this, 0, &tid);
return 0;
}
@ -179,61 +177,58 @@ public:
void Close()
{
// Stop Thread
fprintf(stderr,"* SPU2-X: Waiting for waveOut thread to finish...");
waveout_running=false;
fprintf(stderr, "* SPU2-X: Waiting for waveOut thread to finish...");
waveout_running = false;
WaitForSingleObject(thread,INFINITE);
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));
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)
static BOOL CALLBACK ConfigProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
int wmId,wmEvent;
int wmId, wmEvent;
switch(uMsg)
{
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);
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 );
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;
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);
EndDialog(hWnd, 0);
break;
case IDCANCEL:
EndDialog(hWnd,0);
EndDialog(hWnd, 0);
break;
default:
return FALSE;
@ -243,20 +238,22 @@ private:
case WM_HSCROLL:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch(wmId) {
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);
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);
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;
@ -273,9 +270,8 @@ public:
virtual void Configure(uptr parent)
{
INT_PTR ret;
ret=DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_WAVEOUT), (HWND)parent, (DLGPROC)ConfigProc,1);
if(ret==-1)
{
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;
}
@ -284,7 +280,8 @@ public:
s32 Test() const
{
if (waveOutGetNumDevs() == 0) {
SysMessage("No waveOut Devices Present\n"); return -1;
SysMessage("No waveOut Devices Present\n");
return -1;
}
return 0;
}
@ -292,19 +289,18 @@ public:
int GetEmptySampleCount()
{
int result = 0;
for(int i=0;i<MAX_BUFFER_COUNT;i++)
{
for (int i = 0; i < MAX_BUFFER_COUNT; i++) {
result += (whbuffer[i].dwFlags & WHDR_DONE) ? BufferSize : 0;
}
return result;
}
const wchar_t* GetIdent() const
const wchar_t *GetIdent() const
{
return L"waveout";
}
const wchar_t* GetLongName() const
const wchar_t *GetLongName() const
{
return L"waveOut (Laggy)";
}

View File

@ -18,9 +18,9 @@
#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)
@ -33,7 +33,7 @@ HRESULT GUIDFromString(const wchar_t *str, LPGUID guid)
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}",
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],
@ -44,10 +44,10 @@ HRESULT GUIDFromString(const wchar_t *str, LPGUID guid)
&guid_u8[4],
&guid_u8[5],
&guid_u8[6],
&guid_u8[7]
);
&guid_u8[7]);
if(r!=11) return -1;
if (r != 11)
return -1;
guid->Data1 = guid_u32;
guid->Data2 = guid_u16[0];
@ -63,49 +63,47 @@ HRESULT GUIDFromString(const wchar_t *str, LPGUID guid)
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 );
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)
{
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);
wmEvent = (int)SendMessage((HWND)lParam, TBM_GETPOS, 0, 0);
case TB_THUMBTRACK:
AssignSliderValue( (HWND)lParam, hwndDisplay, wmEvent );
AssignSliderValue((HWND)lParam, hwndDisplay, wmEvent);
break;
default:
@ -114,9 +112,8 @@ BOOL DoHandleScrollMessage( HWND hwndDisplay, WPARAM wParam, LPARAM lParam )
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);
}

View File

@ -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 ***
@ -55,9 +63,9 @@ struct CONFIG_XAUDIO2
wxString Device;
s8 NumBuffers;
CONFIG_XAUDIO2() :
Device(),
NumBuffers( 2 )
CONFIG_XAUDIO2()
: Device()
, NumBuffers(2)
{
}
};
@ -67,9 +75,9 @@ struct CONFIG_WAVEOUT
wxString Device;
s8 NumBuffers;
CONFIG_WAVEOUT() :
Device(),
NumBuffers( 4 )
CONFIG_WAVEOUT()
: Device()
, NumBuffers(4)
{
}
};

View File

@ -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,30 +50,30 @@ 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)
{
hLib = LoadLibraryW(fileName);
if (!hLib) {
return 1;
}
pGetHeader = (pWinampDSPGetHeader2)GetProcAddress(hLib,"winampDSPGetHeader2");
pGetHeader = (pWinampDSPGetHeader2)GetProcAddress(hLib, "winampDSPGetHeader2");
if(!pGetHeader)
{
if (!pGetHeader) {
FreeLibrary(hLib);
hLib=NULL;
hLib = NULL;
return 1;
}
@ -81,17 +81,16 @@ s32 DspLoadLibrary2( wchar_t *fileName, int modNum )
pModule = pHeader->getModule(modNum);
if(!pModule)
{
pGetHeader=NULL;
pHeader=NULL;
if (!pModule) {
pGetHeader = NULL;
pHeader = NULL;
FreeLibrary(hLib);
hLib=NULL;
hLib = NULL;
return -1;
}
pModule->hDllInstance = hLib;
pModule->hwndParent=0;
pModule->hwndParent = 0;
pModule->Init(pModule);
return 0;
@ -100,40 +99,40 @@ s32 DspLoadLibrary2( wchar_t *fileName, int modNum )
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)
{
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);
TerminateThread(hUpdateThread, 1);
}
}
void DspCloseLibrary2()
#endif
{
if(!dspPluginEnabled) return ;
if (!dspPluginEnabled)
return;
if(hLib)
{
if (hLib) {
pModule->Quit(pModule);
FreeLibrary(hLib);
}
pModule=NULL;
pHeader=NULL;
pGetHeader=NULL;
hLib=NULL;
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);
if (hLib) {
return pModule->ModifySamples(pModule, buffer, samples, 16, 2, SampleRate);
}
return samples;
}
@ -145,17 +144,16 @@ void DspUpdate()
DWORD WINAPI DspUpdateThread(PVOID param)
{
if( !dspPluginEnabled ) return -1;
if (!dspPluginEnabled)
return -1;
if( DspLoadLibrary2( dspPlugin, dspPluginModule ) )
if (DspLoadLibrary2(dspPlugin, dspPluginModule))
return -1;
MSG msg;
while(running)
{
GetMessage(&msg,0,0,0);
if((msg.hwnd==NULL)&&(msg.message==WM_QUIT))
{
while (running) {
GetMessage(&msg, 0, 0, 0);
if ((msg.hwnd == NULL) && (msg.message == WM_QUIT)) {
break;
}
TranslateMessage(&msg);
@ -168,11 +166,11 @@ DWORD WINAPI DspUpdateThread(PVOID param)
#else
{
if(!dspPluginEnabled) return;
if (!dspPluginEnabled)
return;
MSG msg;
while(PeekMessage(&msg,0,0,0,PM_REMOVE))
{
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}

View File

@ -27,7 +27,8 @@
#pragma once
typedef struct winampDSPModule {
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)
@ -45,14 +46,15 @@ typedef struct winampDSPModule {
void *userData; // user data, optional
} winampDSPModule;
typedef struct {
typedef struct
{
int version; // DSP_HDRVER
char *description; // description of library
winampDSPModule* (*getModule)(int); // module retrieval function
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

View File

@ -23,13 +23,13 @@
// 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
@ -40,13 +40,13 @@ struct V_VolumeLR
s32 Right;
V_VolumeLR() {}
V_VolumeLR( s32 both ) :
Left( both ),
Right( both )
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
@ -61,17 +61,17 @@ struct V_VolumeSlide
public:
V_VolumeSlide() {}
V_VolumeSlide( s16 regval, s32 fullvol ) :
Reg_VOL( regval ),
Value( fullvol ),
Increment( 0 ),
Mode( 0 )
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 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
@ -84,9 +84,9 @@ struct V_VolumeSlideLR
public:
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)
{
}
@ -96,7 +96,7 @@ public:
Right.Update();
}
void DebugDump( FILE* dump, const char* title );
void DebugDump(FILE *dump, const char *title);
};
struct V_ADSR
@ -113,15 +113,15 @@ struct V_ADSR
struct
{
u32 SustainLevel:4,
DecayRate:4,
AttackRate:7,
AttackMode:1, // 0 for linear (+lin), 1 for pseudo exponential (+exp)
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
};
};
@ -140,17 +140,17 @@ struct V_Voice
V_VolumeSlideLR Volume;
// Envelope
// Envelope
V_ADSR ADSR;
// Pitch (also Reg_PITCH)
// Pitch (also Reg_PITCH)
u16 Pitch;
// Loop Start address (also Reg_LSAH/L)
// Loop Start address (also Reg_LSAH/L)
u32 LoopStartA;
// Sound Start address (also Reg_SSAH/L)
// Sound Start address (also Reg_SSAH/L)
u32 StartA;
// Next Read Data address (also Reg_NAXH/L)
// Next Read Data address (also Reg_NAXH/L)
u32 NextA;
// Voice Decoding State
// Voice Decoding State
s32 Prev1;
s32 Prev2;
@ -162,31 +162,31 @@ struct V_Voice
s8 LoopMode;
s8 LoopFlags;
// Sample pointer (19:12 bit fixed point)
// 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.
// 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).
// 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.
// 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.
// SBuffer now points directly to an ADPCM cache entry.
s16 *SBuffer;
// sample position within the current decoded packet.
// sample position within the current decoded packet.
s32 SCurrent;
// it takes a few ticks for voices to start on the real SPU2?
@ -210,7 +210,7 @@ struct V_VoiceDebug
struct V_CoreDebug
{
V_VoiceDebug Voices[24];
// Last Transfer Size
// Last Transfer Size
u32 lastsize;
// draw adma waveform in the visual debugger
@ -351,7 +351,6 @@ struct V_CoreGates
s16 ExtR; // External Input to Direct Output (Right)
};
};
};
struct VoiceMixSet
@ -360,9 +359,9 @@ struct VoiceMixSet
StereoOut32 Dry, Wet;
VoiceMixSet() {}
VoiceMixSet( const StereoOut32& dry, const StereoOut32& wet ) :
Dry( dry ),
Wet( wet )
VoiceMixSet(const StereoOut32 &dry, const StereoOut32 &wet)
: Dry(dry)
, Wet(wet)
{
}
};
@ -435,7 +434,7 @@ struct V_Core
u32 AutoDmaFree;
// old dma only
u16* DMAPtr;
u16 *DMAPtr;
u32 MADR;
u32 TADR;
@ -454,41 +453,45 @@ struct V_Core
// 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()
: Index(-1)
, DMAPtr(NULL)
{
}
V_Core(int idx); // our badass constructor
~V_Core() throw();
void Init( int index );
void Init(int index);
void UpdateEffectsBufferSize();
void AnalyzeReverbPreset();
s32 EffectsBufferIndexer( s32 offset ) const;
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 );
StereoOut32 Mix(const VoiceMixSet &inVoices, const StereoOut32 &Input, const StereoOut32 &Ext);
void Reverb_AdvanceBuffer();
StereoOut32 DoReverb( const StereoOut32& Input );
s32 RevbGetIndexer( s32 offset );
StereoOut32 DoReverb(const StereoOut32 &Input);
s32 RevbGetIndexer(s32 offset);
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
@ -505,25 +508,27 @@ struct V_Core
__forceinline u16 DmaRead()
{
const u16 ret = (u16)spu2M_Read(TSA);
++TSA; TSA &= 0xfffff;
++TSA;
TSA &= 0xfffff;
return ret;
}
__forceinline void DmaWrite(u16 value)
{
spu2M_Write( TSA, value );
++TSA; TSA &= 0xfffff;
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);
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);
void DoDMAwrite(u16 *pMem, u32 size);
void DoDMAread(u16 *pMem, u32 size);
void AutoDMAReadBuffer(int mode);
void StartADMAWrite(u16 *pMem, u32 sz);
@ -540,24 +545,24 @@ extern s16 InputPos;
// SPU Mixing Cycles ("Ticks mixed" counter)
extern u32 Cycles;
extern s16* spu2regs;
extern s16* _spu2mem;
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();
}
// --------------------------------------------------------------------------------------
@ -584,4 +589,4 @@ struct PcmCacheEntry
s16 Sampledata[pcm_DecodedSamplesPerBlock];
};
extern PcmCacheEntry* pcm_cache_data;
extern PcmCacheEntry *pcm_cache_data;

View File

@ -20,8 +20,8 @@
#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
@ -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];

View File

@ -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 ctrlbits : 4;
u8 reservd1 : 4;
u8 category;
u8 reservd2[22];
} chstatus:

View File

@ -20,17 +20,17 @@
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
@ -49,15 +49,17 @@ struct Savestate::DataBlock
int PlayMode;
};
s32 __fastcall Savestate::FreezeIt( DataBlock& spud )
s32 __fastcall Savestate::FreezeIt(DataBlock &spud)
{
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));
@ -76,20 +78,18 @@ s32 __fastcall Savestate::FreezeIt( DataBlock& spud )
return 0;
}
s32 __fastcall Savestate::ThawIt( DataBlock& spud )
s32 __fastcall Savestate::ThawIt(DataBlock &spud)
{
if( spud.spu2id != SAVE_ID || spud.version < SAVE_VERSION )
{
if (spud.spu2id != SAVE_ID || spud.version < SAVE_VERSION) {
fprintf(stderr, "\n*** SPU2-X Warning:\n");
if( spud.spu2id == SAVE_ID )
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"
);
"\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
@ -99,16 +99,16 @@ s32 __fastcall Savestate::ThawIt( DataBlock& spud )
// adpcm cache : Clear all the cache flags and buffers.
wipe_the_cache();
}
else
{
} 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));
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));
@ -124,10 +124,8 @@ s32 __fastcall Savestate::ThawIt( DataBlock& spud )
// 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++ )
{
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;
}

File diff suppressed because it is too large Load Diff