mirror of https://github.com/PCSX2/pcsx2.git
SPU2Ghz: Lots of changes as described in issue 31, thanks again to Jake.Stine.
git-svn-id: http://pcsx2-playground.googlecode.com/svn/trunk@244 a6443dda-0b58-4228-96e9-037be469359c
This commit is contained in:
parent
eaf15db0fe
commit
0e1f871606
|
@ -52,51 +52,57 @@ END
|
|||
// Dialog
|
||||
//
|
||||
|
||||
IDD_CONFIG DIALOGEX 3, 1, 414, 217
|
||||
IDD_CONFIG DIALOGEX 3, 1, 410, 237
|
||||
STYLE DS_SETFONT | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "SPU2ghz Settings"
|
||||
FONT 8, "MS Sans Serif", 0, 0, 0x0
|
||||
BEGIN
|
||||
PUSHBUTTON "OK",IDOK,300,198,54,15,NOT WS_TABSTOP
|
||||
PUSHBUTTON "Cancel",IDCANCEL,354,198,54,15,NOT WS_TABSTOP
|
||||
GROUPBOX "Effects (Reverb) Settings",IDC_STATIC,6,156,119,30
|
||||
CHECKBOX "Enable Effect Processing",IDC_EFFECTS,12,168,95,10,NOT WS_TABSTOP
|
||||
GROUPBOX "Output Settings",IDC_STATIC,132,6,119,103
|
||||
LTEXT "Buffer Size",IDC_STATIC,138,35,35,8,NOT WS_GROUP
|
||||
LTEXT "Sample Rate",IDC_STATIC,139,19,42,8,NOT WS_GROUP
|
||||
GROUPBOX "Mixing Settings",IDC_STATIC,6,6,119,80
|
||||
LTEXT "Interpolation:",IDC_STATIC,11,58,42,8,NOT WS_GROUP
|
||||
GROUPBOX "",IDC_STATIC,264,18,135,61
|
||||
GROUPBOX "Dumps (on close)",IDC_STATIC,264,131,135,51
|
||||
CHECKBOX "Dump Register Data",IDC_DUMPREGS,270,169,80,10,NOT WS_TABSTOP
|
||||
CHECKBOX "Dump Memory Contents",IDC_DUMPMEM,270,156,91,10,NOT WS_TABSTOP
|
||||
CHECKBOX "Dump Core and Voice State",IDC_DUMPCORE,270,145,104,10,NOT WS_TABSTOP
|
||||
GROUPBOX "Logging",IDC_STATIC,263,80,136,50
|
||||
CHECKBOX "Log Audio Output",IDC_LOGWAVE,269,116,71,10,NOT WS_TABSTOP
|
||||
CHECKBOX "Log DMA Writes",IDC_LOGDMA,269,104,68,10,NOT WS_TABSTOP
|
||||
CHECKBOX "Log Register/DMA Actions",IDC_LOGREGS,269,92,101,10,NOT WS_TABSTOP
|
||||
CHECKBOX "KeyOn/Off Events",IDC_MSGKEY,276,30,74,10,NOT WS_TABSTOP
|
||||
COMBOBOX IDC_INTERPOLATE,12,66,108,84,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
COMBOBOX IDC_SRATE,192,18,54,201,CBS_DROPDOWN | WS_DISABLED | WS_TABSTOP,WS_EX_RIGHT
|
||||
CONTROL "Slider2",IDC_BUFFER,"msctls_trackbar32",TBS_AUTOTICKS | WS_TABSTOP,138,42,65,10
|
||||
EDITTEXT IDC_BSIZE,204,42,42,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
|
||||
LTEXT "Output Module:",IDC_STATIC,12,16,50,8,NOT WS_GROUP
|
||||
COMBOBOX IDC_OUTPUT,12,24,108,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "Number of Buffers:",IDC_STATIC,139,62,60,8
|
||||
EDITTEXT IDC_BCOUNT,204,60,42,12,ES_RIGHT | ES_AUTOHSCROLL
|
||||
GROUPBOX "",IDC_STATIC,258,6,150,180
|
||||
CHECKBOX "Enable Debug Options",IDC_DEBUG,264,6,87,10,NOT WS_TABSTOP
|
||||
CONTROL "DMA Operations",IDC_MSGDMA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,276,54,68,10
|
||||
CONTROL "AutoDMA Operations",IDC_MSGADMA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,282,66,83,10
|
||||
CONTROL "Voice Stop Events",IDC_MSGVOICE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,276,42,75,10
|
||||
CONTROL "Show In Console",IDC_MSGSHOW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,270,18,69,10
|
||||
LTEXT "Size = 1024, Numbers = 10",IDC_STATIC,137,94,108,12
|
||||
PUSHBUTTON "Configure...",IDC_OUTCONF,72,42,48,12
|
||||
LTEXT "WARNING: The effects processing is experimental and _could_ hurt your ears .\n If that happens, tell me about what game, so I can fix it!",IDC_STATIC,20,191,255,21
|
||||
GROUPBOX "DSP",IDC_STATIC,6,87,119,68
|
||||
CONTROL "Enable Winamp DSP plugin",IDC_DSP_ENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,100,103,10
|
||||
LTEXT "(configure in the .ini)",IDC_STATIC,43,110,64,8
|
||||
LTEXT "Recommended:",IDC_STATIC,137,80,108,9
|
||||
PUSHBUTTON "OK",IDOK,291,219,54,15,NOT WS_TABSTOP
|
||||
PUSHBUTTON "Cancel",IDCANCEL,351,219,54,15,NOT WS_TABSTOP
|
||||
GROUPBOX "Mixing Settings",IDC_STATIC,6,6,119,116
|
||||
GROUPBOX "Speed Limiter (obsolete)",IDC_STATIC,6,127,120,98
|
||||
GROUPBOX "Output Settings",IDC_STATIC,132,6,119,182
|
||||
GROUPBOX "",IDC_DEBUG_GROUP,257,7,148,208
|
||||
GROUPBOX "",IDC_STATIC,264,19,135,85
|
||||
GROUPBOX "Logging",IDC_STATIC,264,107,136,50
|
||||
GROUPBOX "Dumps (on close)",IDC_STATIC,264,160,135,49
|
||||
COMBOBOX IDC_OUTPUT,138,27,108,120,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
PUSHBUTTON "Configure...",IDC_OUTCONF,198,42,48,12
|
||||
COMBOBOX IDC_INTERPOLATE,12,28,108,84,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
CONTROL "Enable at start-up",IDC_SPEEDLIMIT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,176,106,12
|
||||
COMBOBOX IDC_SRATE,188,62,58,201,CBS_DROPDOWN | WS_DISABLED | WS_TABSTOP,WS_EX_RIGHT
|
||||
CONTROL "Slider2",IDC_LATENCY_SLIDER,"msctls_trackbar32",TBS_AUTOTICKS | WS_TABSTOP,177,94,72,10
|
||||
CONTROL "Use Time-stretching",IDC_TS_ENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,138,114,79,11
|
||||
CONTROL "Use a Winamp DSP plugin",IDC_DSP_ENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,138,160,103,11
|
||||
CHECKBOX "Enable Debug Options",IDC_DEBUG,264,7,87,10,NOT WS_TABSTOP
|
||||
CONTROL "Show In Console",IDC_MSGSHOW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,270,19,69,10
|
||||
CHECKBOX "KeyOn/Off Events",IDC_MSGKEY,276,31,74,10,NOT WS_TABSTOP
|
||||
CONTROL "Voice Stop Events",IDC_MSGVOICE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,276,43,75,10
|
||||
CONTROL "DMA Operations",IDC_MSGDMA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,276,55,68,10
|
||||
CONTROL "AutoDMA Operations",IDC_MSGADMA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,283,67,83,10
|
||||
CONTROL "Buffer Over/Underruns",IDC_DBG_OVERRUNS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,276,79,97,11
|
||||
CONTROL "ADPCM Cache Statistics",IDC_DBG_CACHE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,276,91,114,9
|
||||
CHECKBOX "Dump Core and Voice State",IDC_DUMPCORE,270,172,104,10,NOT WS_TABSTOP
|
||||
CHECKBOX "Dump Memory Contents",IDC_DUMPMEM,270,184,91,10,NOT WS_TABSTOP
|
||||
CHECKBOX "Dump Register Data",IDC_DUMPREGS,270,196,80,10,NOT WS_TABSTOP
|
||||
CHECKBOX "Enable Effects Processing",IDC_EFFECTS,12,49,99,10,NOT WS_TABSTOP
|
||||
LTEXT "Latency:",IDC_STATIC,138,89,33,8,NOT WS_GROUP
|
||||
LTEXT "Sample Rate:",IDC_STATIC,137,63,44,8,NOT WS_GROUP
|
||||
LTEXT "Interpolation:",IDC_STATIC,12,18,42,10,NOT WS_GROUP
|
||||
LTEXT "Module:",IDC_STATIC,138,17,50,9,NOT WS_GROUP
|
||||
LTEXT "Experimental: Enabling this could break sound badly.",IDC_STATIC,24,61,96,17
|
||||
LTEXT "(configure in the .ini)",IDC_STATIC,150,172,64,8
|
||||
LTEXT "Uses the SPU2 to limit framerate for games that cause buffer overruns. Use Timestretching instead.",IDC_STATIC,11,138,109,34
|
||||
CTEXT "100 ms (avg)",IDC_LATENCY_LABEL,185,84,58,10
|
||||
LTEXT "Helps reduce latency and usually eliminates audio skips. Uses a little extra CPU.",IDC_STATIC,150,127,96,25
|
||||
CHECKBOX "Log Register/DMA Actions",IDC_LOGREGS,269,119,101,10,WS_GROUP | NOT WS_TABSTOP
|
||||
CHECKBOX "Log DMA Writes",IDC_LOGDMA,269,131,68,10,NOT WS_TABSTOP
|
||||
CHECKBOX "Log Audio Output",IDC_LOGWAVE,269,143,71,10,NOT WS_TABSTOP
|
||||
CONTROL "Enable runtime toggle",IDC_SPEEDLIMIT_RUNTIME_TOGGLE,
|
||||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,190,110,10
|
||||
LTEXT "Allows speed limiter to be toggled with the minus (-) key.",IDC_STATIC,23,202,95,17
|
||||
CONTROL "Volume Boost",IDC_VOLBOOST,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,86,85,11
|
||||
LTEXT "Can break sound in games that are already loud.",IDC_STATIC,24,99,96,17
|
||||
END
|
||||
|
||||
IDD_DEBUG DIALOGEX 0, 0, 326, 525
|
||||
|
@ -107,49 +113,58 @@ BEGIN
|
|||
DEFPUSHBUTTON "Close",IDOK,269,504,50,14
|
||||
END
|
||||
|
||||
IDD_DSOUND DIALOGEX 0, 0, 186, 58
|
||||
IDD_DSOUND DIALOGEX 0, 0, 170, 122
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "DirectSound Output Module Settings"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "OK",IDOK,75,37,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,129,37,50,14
|
||||
COMBOBOX IDC_DS_DEVICE,7,17,172,62,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "DirectSound Device",IDC_STATIC,7,7,63,8
|
||||
DEFPUSHBUTTON "OK",IDOK,52,104,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,115,104,50,14
|
||||
COMBOBOX IDC_DS_DEVICE,4,15,161,62,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "DirectSound Device",IDC_STATIC,4,3,63,8
|
||||
LTEXT "Number of Buffers",IDC_STATIC,4,40,61,11
|
||||
CONTROL "",IDC_BUFFERS_SLIDER,"msctls_trackbar32",TBS_AUTOTICKS | WS_TABSTOP,71,48,94,10
|
||||
LTEXT "Use extra buffers if you are experiencing loopy or studdery audio even when games run at high FPS.",IDC_STATIC,8,66,151,27
|
||||
CTEXT "8 (80 ms latency)",IDC_LATENCY_LABEL,70,37,95,11
|
||||
END
|
||||
|
||||
IDD_DSOUND51 DIALOGEX 0, 0, 265, 182
|
||||
IDD_DSOUND51 DIALOGEX 0, 0, 336, 180
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "DirectSound 5.1 Output Module Settings"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "OK",IDOK,154,161,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,208,161,50,14
|
||||
COMBOBOX IDC_DS_DEVICE,7,17,251,62,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "DirectSound Device",IDC_STATIC,7,7,63,8
|
||||
CONTROL "",IDC_SLIDER1,"msctls_trackbar32",TBS_VERT | TBS_BOTH | WS_TABSTOP,18,54,30,36
|
||||
CONTROL "",IDC_SLIDER2,"msctls_trackbar32",TBS_VERT | TBS_BOTH | WS_TABSTOP,60,56,30,34
|
||||
CONTROL "",IDC_SLIDER3,"msctls_trackbar32",TBS_VERT | TBS_BOTH | WS_TABSTOP,102,56,30,34
|
||||
GROUPBOX "Surround Volume Correction",IDC_STATIC,7,36,142,139
|
||||
CTEXT "Center",IDC_STATIC,54,48,42,8
|
||||
CTEXT "Left",IDC_STATIC,12,48,42,8
|
||||
CTEXT "Right",IDC_STATIC,96,48,42,8
|
||||
CONTROL "",IDC_SLIDER4,"msctls_trackbar32",TBS_VERT | TBS_BOTH | WS_TABSTOP,18,116,30,40
|
||||
CONTROL "",IDC_SLIDER5,"msctls_trackbar32",TBS_VERT | TBS_BOTH | WS_TABSTOP,60,116,30,40
|
||||
CONTROL "",IDC_SLIDER6,"msctls_trackbar32",TBS_VERT | TBS_BOTH | WS_TABSTOP,102,116,30,40
|
||||
CTEXT "LFE (sub)",IDC_STATIC,54,108,42,8
|
||||
CTEXT "Rear Left",IDC_STATIC,12,108,42,8
|
||||
CTEXT "Rear Right",IDC_STATIC,96,108,42,8
|
||||
GROUPBOX "Other Tweaks",IDC_STATIC,155,36,103,120
|
||||
CONTROL "",IDC_SLIDER7,"msctls_trackbar32",TBS_VERT | TBS_BOTH | WS_TABSTOP,168,56,30,49
|
||||
CTEXT "Center in LR",IDC_STATIC,162,48,42,8
|
||||
EDITTEXT IDC_EDIT1,18,90,30,14,ES_AUTOHSCROLL
|
||||
EDITTEXT IDC_EDIT2,60,90,30,14,ES_AUTOHSCROLL
|
||||
EDITTEXT IDC_EDIT3,102,90,30,14,ES_AUTOHSCROLL
|
||||
EDITTEXT IDC_EDIT4,18,156,30,14,ES_AUTOHSCROLL
|
||||
EDITTEXT IDC_EDIT5,60,156,30,14,ES_AUTOHSCROLL
|
||||
EDITTEXT IDC_EDIT6,102,156,30,14,ES_AUTOHSCROLL
|
||||
EDITTEXT IDC_EDIT7,168,108,30,14,ES_AUTOHSCROLL
|
||||
DEFPUSHBUTTON "OK",IDOK,228,161,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,281,161,50,14
|
||||
COMBOBOX IDC_DS_DEVICE,5,17,142,62,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "DirectSound Device",IDC_STATIC,5,5,63,8
|
||||
CONTROL "",IDC_SLIDER1,"msctls_trackbar32",TBS_VERT | TBS_BOTH | WS_TABSTOP,15,53,30,36
|
||||
CONTROL "",IDC_SLIDER2,"msctls_trackbar32",TBS_VERT | TBS_BOTH | WS_TABSTOP,57,54,30,34
|
||||
CONTROL "",IDC_SLIDER3,"msctls_trackbar32",TBS_VERT | TBS_BOTH | WS_TABSTOP,99,54,30,34
|
||||
GROUPBOX "Surround Volume Correction",IDC_STATIC,5,35,138,139
|
||||
CTEXT "Center",IDC_STATIC,51,46,42,8
|
||||
CTEXT "Left",IDC_STATIC,9,46,42,8
|
||||
CTEXT "Right",IDC_STATIC,93,46,42,8
|
||||
CONTROL "",IDC_SLIDER4,"msctls_trackbar32",TBS_VERT | TBS_BOTH | WS_TABSTOP,15,115,30,40
|
||||
CONTROL "",IDC_SLIDER5,"msctls_trackbar32",TBS_VERT | TBS_BOTH | WS_TABSTOP,57,115,30,40
|
||||
CONTROL "",IDC_SLIDER6,"msctls_trackbar32",TBS_VERT | TBS_BOTH | WS_TABSTOP,99,115,30,40
|
||||
CTEXT "LFE (sub)",IDC_STATIC,51,107,42,8
|
||||
CTEXT "Rear Left",IDC_STATIC,9,107,42,8
|
||||
CTEXT "Rear Right",IDC_STATIC,93,107,42,8
|
||||
GROUPBOX "Other Tweaks",IDC_STATIC,153,77,63,97
|
||||
CONTROL "",IDC_SLIDER7,"msctls_trackbar32",TBS_VERT | TBS_BOTH | WS_TABSTOP,169,98,30,49
|
||||
CTEXT "Center in LR",IDC_STATIC,163,90,42,8
|
||||
EDITTEXT IDC_EDIT1,15,88,30,14,ES_AUTOHSCROLL
|
||||
EDITTEXT IDC_EDIT2,57,88,30,14,ES_AUTOHSCROLL
|
||||
EDITTEXT IDC_EDIT3,99,88,30,14,ES_AUTOHSCROLL
|
||||
EDITTEXT IDC_EDIT4,15,155,30,14,ES_AUTOHSCROLL
|
||||
EDITTEXT IDC_EDIT5,57,155,30,14,ES_AUTOHSCROLL
|
||||
EDITTEXT IDC_EDIT6,99,155,30,14,ES_AUTOHSCROLL
|
||||
EDITTEXT IDC_EDIT7,169,150,30,14,ES_AUTOHSCROLL
|
||||
LTEXT "Number of Buffers",IDC_STATIC,160,32,61,11
|
||||
CONTROL "",IDC_BUFFERS_SLIDER,"msctls_trackbar32",TBS_AUTOTICKS | WS_TABSTOP,229,40,94,10
|
||||
LTEXT "Use extra buffers if you are experiencing loopy or studdery audio even when games run at high FPS.",IDC_STATIC,226,69,102,46
|
||||
CTEXT "8 (80 ms latency)",IDC_LATENCY_LABEL2,227,29,95,11
|
||||
GROUPBOX "Latency",IDC_STATIC,154,13,174,48
|
||||
END
|
||||
|
||||
IDD_ASIO DIALOGEX 0, 0, 186, 58
|
||||
|
@ -163,15 +178,19 @@ BEGIN
|
|||
LTEXT "ASIO Driver",IDC_STATIC,7,7,39,8
|
||||
END
|
||||
|
||||
IDD_WAVEOUT DIALOGEX 0, 0, 186, 58
|
||||
IDD_WAVEOUT DIALOGEX 0, 0, 170, 122
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "waveOut Output Module Settings"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "OK",IDOK,75,37,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,129,37,50,14
|
||||
COMBOBOX IDC_DS_DEVICE,7,17,172,62,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "waveOut Device",IDC_STATIC,7,7,54,8
|
||||
DEFPUSHBUTTON "OK",IDOK,52,104,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,115,104,50,14
|
||||
COMBOBOX IDC_DS_DEVICE,4,15,161,62,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "waveOut Device",IDC_STATIC,4,3,54,8
|
||||
LTEXT "Number of Buffers",IDC_STATIC,4,39,61,11
|
||||
CONTROL "",IDC_BUFFERS_SLIDER,"msctls_trackbar32",TBS_AUTOTICKS | WS_TABSTOP,71,48,94,10
|
||||
LTEXT "Use extra buffers if you are experiencing loopy or studdery audio even when games run at high FPS.",IDC_STATIC,8,66,151,27
|
||||
CTEXT "8 (80 ms latency)",IDC_LATENCY_LABEL,70,37,95,11
|
||||
END
|
||||
|
||||
|
||||
|
@ -186,9 +205,8 @@ BEGIN
|
|||
IDD_CONFIG, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 6
|
||||
RIGHTMARGIN, 408
|
||||
TOPMARGIN, 5
|
||||
BOTTOMMARGIN, 212
|
||||
RIGHTMARGIN, 405
|
||||
BOTTOMMARGIN, 234
|
||||
END
|
||||
|
||||
IDD_DEBUG, DIALOG
|
||||
|
@ -201,17 +219,17 @@ BEGIN
|
|||
|
||||
IDD_DSOUND, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 179
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 51
|
||||
LEFTMARGIN, 4
|
||||
RIGHTMARGIN, 165
|
||||
TOPMARGIN, 3
|
||||
BOTTOMMARGIN, 118
|
||||
END
|
||||
|
||||
IDD_DSOUND51, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 258
|
||||
TOPMARGIN, 7
|
||||
LEFTMARGIN, 5
|
||||
RIGHTMARGIN, 331
|
||||
TOPMARGIN, 5
|
||||
BOTTOMMARGIN, 175
|
||||
END
|
||||
|
||||
|
@ -225,10 +243,10 @@ BEGIN
|
|||
|
||||
IDD_WAVEOUT, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 179
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 51
|
||||
LEFTMARGIN, 4
|
||||
RIGHTMARGIN, 165
|
||||
TOPMARGIN, 3
|
||||
BOTTOMMARGIN, 118
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
|
|
@ -36,8 +36,9 @@ private:
|
|||
|
||||
#ifndef __WIN64__
|
||||
|
||||
#define BufferSize (CurBufferSize<<1)
|
||||
#define BufferSizeBytes (BufferSize<<2)
|
||||
// [Air] : This needs fixed.
|
||||
static const int BufferSize = SndOutPacketSize;
|
||||
static const int BufferSizeBytes = BufferSize << 2;
|
||||
|
||||
s32* asio_lbuffer;
|
||||
|
||||
|
@ -175,7 +176,7 @@ private:
|
|||
#define DBL(t) ((t*)(asioDriverInfo.bufferInfos[0].buffers[index]))
|
||||
#define DBR(t) ((t*)(asioDriverInfo.bufferInfos[1].buffers[index]))
|
||||
|
||||
int BLen=BufferSize*CurBufferCount;
|
||||
int BLen=BufferSize*Config_Asio.NumBuffers;
|
||||
int ssize=2;
|
||||
|
||||
if(showBufferInfo)
|
||||
|
@ -241,7 +242,11 @@ private:
|
|||
bufferInfoReady=true;
|
||||
}
|
||||
|
||||
buff->ReadSamples(asio_lbuffer,buffSize<<1);
|
||||
// [Air] : Dunno if this is right...
|
||||
// Maybe there shouldn't be 2 packets? (doesn't make sense for low
|
||||
// latency drivers, but then again using ASIO at all doesn't make sense).
|
||||
buff->ReadSamples(asio_lbuffer);
|
||||
buff->ReadSamples(&asio_lbuffer[SndOutPacketSize]);
|
||||
s32 asio_read_num = 0;
|
||||
|
||||
// perform the processing
|
||||
|
@ -586,7 +591,7 @@ public:
|
|||
for(int i=0;i<driverMax;i++)
|
||||
{
|
||||
ConLog(" *** %u - %s\n",i+1,driverNames[i]);
|
||||
if(stricmp(driverNames[i],AsioDriver)==0)
|
||||
if(_stricmp(driverNames[i],AsioDriver)==0)
|
||||
{
|
||||
selected=i+1;
|
||||
break;
|
||||
|
@ -670,9 +675,9 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual bool Is51Out() { return false; }
|
||||
virtual bool Is51Out() const { return false; }
|
||||
|
||||
s32 Test()
|
||||
s32 Test() const
|
||||
{
|
||||
#ifndef __WIN64__
|
||||
if(asioDrivers->asioGetNumDev()>0)
|
||||
|
@ -680,6 +685,22 @@ public:
|
|||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
int GetEmptySampleCount() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* GetIdent() const
|
||||
{
|
||||
return "asio";
|
||||
}
|
||||
|
||||
const char* GetLongName() const
|
||||
{
|
||||
return "ASIO (BROKEN)";
|
||||
}
|
||||
|
||||
} ASIOMod;
|
||||
|
||||
SndOutModule *ASIOOut=&ASIOMod;
|
||||
|
|
|
@ -20,22 +20,31 @@
|
|||
#include "dialogs.h"
|
||||
// Config Vars
|
||||
|
||||
|
||||
static bool VolumeBoostEnabled = false;
|
||||
static int VolumeShiftModifier = 0;
|
||||
|
||||
|
||||
// DEBUG
|
||||
|
||||
bool DebugEnabled=false;
|
||||
bool MsgToConsole=false;
|
||||
bool MsgKeyOnOff=false;
|
||||
bool MsgVoiceOff=false;
|
||||
bool MsgDMA=false;
|
||||
bool MsgAutoDMA=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 _CoresDump=false;
|
||||
bool _MemDump=false;
|
||||
bool _RegDump=false;
|
||||
|
||||
bool AccessLog=false;
|
||||
bool DMALog=false;
|
||||
bool WaveLog=false;
|
||||
|
||||
bool CoresDump=false;
|
||||
bool MemDump=false;
|
||||
bool RegDump=false;
|
||||
|
||||
char AccessLogFileName[255];
|
||||
char WaveLogFileName[255];
|
||||
|
@ -59,19 +68,20 @@ int Interpolation=1;
|
|||
2. cubic interpolation
|
||||
*/
|
||||
|
||||
// EFFECTS
|
||||
bool EffectsEnabled=false;
|
||||
|
||||
// OUTPUT
|
||||
int SampleRate=48000;
|
||||
int CurBufferSize=1024;
|
||||
int MaxBufferCount=8;
|
||||
int CurBufferCount=MaxBufferCount;
|
||||
int SndOutLatencyMS=60;
|
||||
//int SndOutLatency=1024;
|
||||
//int MaxBufferCount=8;
|
||||
//int CurBufferCount=MaxBufferCount;
|
||||
bool timeStretchEnabled=false;
|
||||
|
||||
int OutputModule=OUTPUT_DSOUND;
|
||||
u32 OutputModule=0; //OUTPUT_DSOUND;
|
||||
|
||||
int VolumeMultiplier=1;
|
||||
int VolumeDivisor=1;
|
||||
//int VolumeMultiplier=1;
|
||||
//int VolumeDivisor=1;
|
||||
|
||||
int LimitMode=0;
|
||||
/* values:
|
||||
|
@ -80,17 +90,14 @@ int LimitMode=0;
|
|||
2. Hard limiter -- more cpu-intensive while limiting, but should give better (constant) speeds
|
||||
*/
|
||||
|
||||
u32 GainL =256;
|
||||
u32 GainR =256;
|
||||
u32 GainSL =200;
|
||||
u32 GainSR =200;
|
||||
u32 GainC =200;
|
||||
u32 GainLFE=256;
|
||||
u32 AddCLR = 56;
|
||||
u32 LowpassLFE=80;
|
||||
|
||||
CONFIG_DSOUNDOUT Config_DSoundOut;
|
||||
CONFIG_DSOUND51 Config_DSound51;
|
||||
CONFIG_WAVEOUT Config_WaveOut;
|
||||
CONFIG_ASIO Config_Asio;
|
||||
|
||||
// MISC
|
||||
bool LimiterToggleEnabled=true;
|
||||
bool LimiterToggleEnabled=false;
|
||||
int LimiterToggle=VK_SUBTRACT;
|
||||
|
||||
// DSP
|
||||
|
@ -98,19 +105,15 @@ bool dspPluginEnabled=false;
|
|||
char dspPlugin[256];
|
||||
int dspPluginModule=0;
|
||||
|
||||
bool timeStretchEnabled=false;
|
||||
|
||||
// OUTPUT MODULES
|
||||
char AsioDriver[129]="";
|
||||
|
||||
/// module-specific settings
|
||||
|
||||
char DSoundDevice[255];
|
||||
|
||||
|
||||
//////
|
||||
|
||||
char CfgFile[]="inis\\SPU2Ghz.ini";
|
||||
const char NewCfgFile[]="inis\\SPU2Ghz-v2.ini";
|
||||
const char LegacyCfgFile[]="inis\\SPU2Ghz.ini";
|
||||
const char* CfgFile=NewCfgFile;
|
||||
|
||||
|
||||
/*| Config File Format: |¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯*\
|
||||
|
@ -128,26 +131,26 @@ char CfgFile[]="inis\\SPU2Ghz.ini";
|
|||
\*_____________________________________________*/
|
||||
|
||||
|
||||
void CfgWriteBool(char *Section, char*Name, bool Value) {
|
||||
void CfgWriteBool(const char *Section, const char*Name, bool Value) {
|
||||
char *Data=Value?"TRUE":"FALSE";
|
||||
|
||||
WritePrivateProfileString(Section,Name,Data,CfgFile);
|
||||
}
|
||||
|
||||
void CfgWriteInt(char *Section, char*Name, int Value) {
|
||||
void CfgWriteInt(const char *Section, const char*Name, int Value) {
|
||||
char Data[255];
|
||||
_itoa(Value,Data,10);
|
||||
|
||||
WritePrivateProfileString(Section,Name,Data,CfgFile);
|
||||
}
|
||||
|
||||
void CfgWriteStr(char *Section, char*Name,char *Data) {
|
||||
void CfgWriteStr(const char *Section, const char* Name, const char *Data) {
|
||||
WritePrivateProfileString(Section,Name,Data,CfgFile);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
bool CfgReadBool(char *Section,char *Name,bool Default) {
|
||||
bool CfgReadBool(const char *Section,const char *Name,bool Default) {
|
||||
char Data[255]="";
|
||||
GetPrivateProfileString(Section,Name,"",Data,255,CfgFile);
|
||||
Data[254]=0;
|
||||
|
@ -164,7 +167,8 @@ bool CfgReadBool(char *Section,char *Name,bool Default) {
|
|||
return false;
|
||||
}
|
||||
|
||||
int CfgReadInt(char *Section, char*Name,int Default) {
|
||||
|
||||
int CfgReadInt(const char *Section, const char*Name,int Default) {
|
||||
char Data[255]="";
|
||||
GetPrivateProfileString(Section,Name,"",Data,255,CfgFile);
|
||||
Data[254]=0;
|
||||
|
@ -177,7 +181,8 @@ int CfgReadInt(char *Section, char*Name,int Default) {
|
|||
return atoi(Data);
|
||||
}
|
||||
|
||||
void CfgReadStr(char *Section, char*Name,char *Data,int DataSize,char *Default) {
|
||||
|
||||
void CfgReadStr(const char *Section, const char* Name, char *Data, int DataSize, const char *Default) {
|
||||
int sl;
|
||||
GetPrivateProfileString(Section,Name,"",Data,DataSize,CfgFile);
|
||||
|
||||
|
@ -188,24 +193,38 @@ void CfgReadStr(char *Section, char*Name,char *Data,int DataSize,char *Default)
|
|||
}
|
||||
}
|
||||
|
||||
// Tries to read the requested value.
|
||||
// Returns FALSE if the value isn't found.
|
||||
bool CfgFindName( const char *Section, const char* Name)
|
||||
{
|
||||
// Only load 24 characters. No need to load more.
|
||||
char Data[24]="";
|
||||
GetPrivateProfileString(Section,Name,"",Data,24,CfgFile);
|
||||
Data[23]=0;
|
||||
|
||||
if(strlen(Data)==0) return false;
|
||||
return true;
|
||||
}
|
||||
/*****************************************************************************/
|
||||
|
||||
void ReadSettings()
|
||||
{
|
||||
|
||||
DebugEnabled=CfgReadBool("DEBUG","Global_Debug_Enabled",0);
|
||||
MsgToConsole=DebugEnabled&CfgReadBool("DEBUG","Show_Messages",0);
|
||||
MsgKeyOnOff =DebugEnabled&MsgToConsole&CfgReadBool("DEBUG","Show_Messages_Key_On_Off",0);
|
||||
MsgVoiceOff =DebugEnabled&MsgToConsole&CfgReadBool("DEBUG","Show_Messages_Voice_Off",0);
|
||||
MsgDMA =DebugEnabled&MsgToConsole&CfgReadBool("DEBUG","Show_Messages_DMA_Transfer",0);
|
||||
MsgAutoDMA =DebugEnabled&MsgToConsole&CfgReadBool("DEBUG","Show_Messages_AutoDMA",0);
|
||||
AccessLog =DebugEnabled&CfgReadBool("DEBUG","Log_Register_Access",0);
|
||||
DMALog =DebugEnabled&CfgReadBool("DEBUG","Log_DMA_Transfers",0);
|
||||
WaveLog =DebugEnabled&CfgReadBool("DEBUG","Log_WAVE_Output",0);
|
||||
_MsgToConsole=CfgReadBool("DEBUG","Show_Messages",0);
|
||||
_MsgKeyOnOff =CfgReadBool("DEBUG","Show_Messages_Key_On_Off",0);
|
||||
_MsgVoiceOff =CfgReadBool("DEBUG","Show_Messages_Voice_Off",0);
|
||||
_MsgDMA =CfgReadBool("DEBUG","Show_Messages_DMA_Transfer",0);
|
||||
_MsgAutoDMA =CfgReadBool("DEBUG","Show_Messages_AutoDMA",0);
|
||||
_MsgOverruns =CfgReadBool("DEBUG","Show_Messages_Overruns",0);
|
||||
_MsgCache =CfgReadBool("DEBUG","Show_Messages_CacheStats",0);
|
||||
|
||||
CoresDump =DebugEnabled&CfgReadBool("DEBUG","Dump_Info",0);
|
||||
MemDump =DebugEnabled&CfgReadBool("DEBUG","Dump_Memory",0);
|
||||
RegDump =DebugEnabled&CfgReadBool("DEBUG","Dump_Regs",0);
|
||||
_AccessLog =CfgReadBool("DEBUG","Log_Register_Access",0);
|
||||
_DMALog =CfgReadBool("DEBUG","Log_DMA_Transfers",0);
|
||||
_WaveLog =CfgReadBool("DEBUG","Log_WAVE_Output",0);
|
||||
|
||||
_CoresDump =CfgReadBool("DEBUG","Dump_Info",0);
|
||||
_MemDump =CfgReadBool("DEBUG","Dump_Memory",0);
|
||||
_RegDump =CfgReadBool("DEBUG","Dump_Regs",0);
|
||||
|
||||
CfgReadStr("DEBUG","Access_Log_Filename",AccessLogFileName,255,"logs\\SPU2Log.txt");
|
||||
CfgReadStr("DEBUG","WaveLog_Filename", WaveLogFileName, 255,"logs\\SPU2log.wav");
|
||||
|
@ -218,55 +237,82 @@ void ReadSettings()
|
|||
|
||||
WaveDumpFormat=CfgReadInt("DEBUG","Wave_Log_Format",0);
|
||||
|
||||
|
||||
Interpolation=CfgReadInt("MIXING","Interpolation",1);
|
||||
|
||||
AutoDMAPlayRate[0]=CfgReadInt("MIXING","AutoDMA_Play_Rate_0",0);
|
||||
AutoDMAPlayRate[1]=CfgReadInt("MIXING","AutoDMA_Play_Rate_1",0);
|
||||
|
||||
EffectsEnabled=CfgReadBool("EFFECTS","Enable_Effects",0);
|
||||
Interpolation=CfgReadInt("MIXING","Interpolation",1);
|
||||
|
||||
// Moved Timestretch from DSP to Output
|
||||
timeStretchEnabled = CfgReadBool(
|
||||
CfgFindName( "OUTPUT", "Timestretch_Enable" ) ? "OUTPUT" : "DSP",
|
||||
"Timestretch_Enable", true
|
||||
);
|
||||
|
||||
// Moved Effects_Enable from Effects to Mixing
|
||||
EffectsEnabled = CfgReadBool(
|
||||
CfgFindName( "MIXING", "Enable_Effects" ) ? "MIXING" : "EFFECTS",
|
||||
"Enable_Effects", false
|
||||
);
|
||||
|
||||
SampleRate=CfgReadInt("OUTPUT","Sample_Rate",48000);
|
||||
SndOutLatencyMS=CfgReadInt("OUTPUT","Latency",120);
|
||||
|
||||
CurBufferSize=CfgReadInt("OUTPUT","Buffer_Size",1024);
|
||||
MaxBufferCount=CfgReadInt("OUTPUT","Buffer_Count",10);
|
||||
if(MaxBufferCount<3) MaxBufferCount=3;
|
||||
CurBufferCount=MaxBufferCount;
|
||||
//OutputModule = CfgReadInt("OUTPUT","Output_Module", OUTPUT_DSOUND );
|
||||
char omodid[128];
|
||||
CfgReadStr( "OUTPUT", "Output_Module", omodid, 127, DSoundOut->GetIdent() );
|
||||
|
||||
OutputModule=CfgReadInt("OUTPUT","Output_Module",OUTPUT_DSOUND);
|
||||
|
||||
VolumeMultiplier=CfgReadInt("OUTPUT","Volume_Multiplier",1);
|
||||
VolumeDivisor =CfgReadInt("OUTPUT","Volume_Divisor",1);
|
||||
|
||||
GainL =CfgReadInt("OUTPUT","Channel_Gain_L", 256);
|
||||
GainR =CfgReadInt("OUTPUT","Channel_Gain_R", 256);
|
||||
GainC =CfgReadInt("OUTPUT","Channel_Gain_C", 256);
|
||||
GainLFE=CfgReadInt("OUTPUT","Channel_Gain_LFE",256);
|
||||
GainSL =CfgReadInt("OUTPUT","Channel_Gain_SL", 200);
|
||||
GainSR =CfgReadInt("OUTPUT","Channel_Gain_SR", 200);
|
||||
AddCLR =CfgReadInt("OUTPUT","Channel_Center_In_LR", 56);
|
||||
LowpassLFE = CfgReadInt("OUTPUT","LFE_Lowpass_Frequency", 80);
|
||||
// find the driver index of this module:
|
||||
OutputModule = FindOutputModuleById( omodid );
|
||||
|
||||
VolumeShiftModifier = CfgReadInt( "OUTPUT","Volume_Shift", 0 );
|
||||
LimitMode=CfgReadInt("OUTPUT","Speed_Limit_Mode",0);
|
||||
|
||||
CfgReadStr("OUTPUT","Asio_Driver_Name",AsioDriver,128,"");
|
||||
|
||||
CfgReadStr("DSP PLUGIN","Filename",dspPlugin,255,"");
|
||||
dspPluginModule = CfgReadInt("DSP PLUGIN","ModuleNum",0);
|
||||
dspPluginEnabled= CfgReadBool("DSP PLUGIN","Enabled",false);
|
||||
|
||||
timeStretchEnabled = false; /*CfgReadBool("DSP","Timestretch_Enable",false);*/ //has to be false at init
|
||||
|
||||
LimiterToggleEnabled = CfgReadBool("KEYS","Limiter_Toggle_Enabled",false);
|
||||
LimiterToggle = CfgReadInt ("KEYS","Limiter_Toggle",VK_SUBTRACT);
|
||||
|
||||
CfgReadStr("DirectSound Output (Stereo)","Device",DSoundDevice,255,"");
|
||||
// Read DSOUNDOUT and WAVEOUT configs:
|
||||
CfgReadStr( "DSOUNDOUT", "Device", Config_DSoundOut.Device, 254, "default" );
|
||||
CfgReadStr( "WAVEOUT", "Device", Config_WaveOut.Device, 254, "default" );
|
||||
Config_DSoundOut.NumBuffers = CfgReadInt( "DSOUNDOUT", "Buffer_Count", 3 );
|
||||
Config_WaveOut.NumBuffers = CfgReadInt( "WAVEOUT", "Buffer_Count", 4 );
|
||||
|
||||
if(VolumeMultiplier<0) VolumeMultiplier=-VolumeMultiplier;
|
||||
else if(VolumeMultiplier==0) VolumeMultiplier=1;
|
||||
// Read DSOUND51 config:
|
||||
Config_DSound51.GainL =CfgReadInt("DSOUND51","Channel_Gain_L", 256);
|
||||
Config_DSound51.GainR =CfgReadInt("DSOUND51","Channel_Gain_R", 256);
|
||||
Config_DSound51.GainC =CfgReadInt("DSOUND51","Channel_Gain_C", 256);
|
||||
Config_DSound51.GainLFE=CfgReadInt("DSOUND51","Channel_Gain_LFE",256);
|
||||
Config_DSound51.GainSL =CfgReadInt("DSOUND51","Channel_Gain_SL", 200);
|
||||
Config_DSound51.GainSR =CfgReadInt("DSOUND51","Channel_Gain_SR", 200);
|
||||
Config_DSound51.AddCLR =CfgReadInt("DSOUND51","Channel_Center_In_LR", 56);
|
||||
Config_DSound51.LowpassLFE = CfgReadInt("DSOUND51","LFE_Lowpass_Frequency", 80);
|
||||
|
||||
// Read ASIOOUT config:
|
||||
CfgReadStr("ASIO","Asio_Driver_Name",AsioDriver,128,"");
|
||||
|
||||
// Sanity Checks
|
||||
// -------------
|
||||
|
||||
SampleRate = 48000; // Yup nothing else is supported for now.
|
||||
VolumeShiftModifier = min( max( VolumeShiftModifier, -2 ), 2 );
|
||||
SndOutVolumeShift = SndOutVolumeShiftBase - VolumeShiftModifier;
|
||||
SndOutLatencyMS = min( max( SndOutLatencyMS, 20 ), 420 );
|
||||
|
||||
Config_DSoundOut.NumBuffers = min( max( Config_DSoundOut.NumBuffers, 2 ), 8 );
|
||||
Config_WaveOut.NumBuffers = min( max( Config_DSoundOut.NumBuffers, 3 ), 8 );
|
||||
|
||||
if( mods[OutputModule] == NULL )
|
||||
{
|
||||
// Unsupported or legacy module.
|
||||
fprintf( stderr, " * SPU2: Unknown output module '%s' specified in configuration file.\n", omodid );
|
||||
fprintf( stderr, " * SPU2: Defaulting to DirectSound (%s).\n", DSoundOut->GetIdent() );
|
||||
OutputModule = FindOutputModuleById( DSoundOut->GetIdent() );
|
||||
}
|
||||
|
||||
if(VolumeDivisor<0) VolumeDivisor=-VolumeDivisor;
|
||||
else if(VolumeDivisor==0) VolumeDivisor=1;
|
||||
|
||||
}
|
||||
|
||||
|
@ -276,20 +322,24 @@ void WriteSettings()
|
|||
{
|
||||
CfgWriteBool("DEBUG","Global_Debug_Enabled",DebugEnabled);
|
||||
|
||||
if(DebugEnabled) {
|
||||
CfgWriteBool("DEBUG","Show_Messages", MsgToConsole);
|
||||
CfgWriteBool("DEBUG","Show_Messages_Key_On_Off", MsgKeyOnOff);
|
||||
CfgWriteBool("DEBUG","Show_Messages_Voice_Off", MsgVoiceOff);
|
||||
CfgWriteBool("DEBUG","Show_Messages_DMA_Transfer",MsgDMA);
|
||||
CfgWriteBool("DEBUG","Show_Messages_AutoDMA", MsgAutoDMA);
|
||||
// [Air] : Commented out so that we retain debug settings even if disabled...
|
||||
//if(DebugEnabled)
|
||||
{
|
||||
CfgWriteBool("DEBUG","Show_Messages", _MsgToConsole);
|
||||
CfgWriteBool("DEBUG","Show_Messages_Key_On_Off", _MsgKeyOnOff);
|
||||
CfgWriteBool("DEBUG","Show_Messages_Voice_Off", _MsgVoiceOff);
|
||||
CfgWriteBool("DEBUG","Show_Messages_DMA_Transfer",_MsgDMA);
|
||||
CfgWriteBool("DEBUG","Show_Messages_AutoDMA", _MsgAutoDMA);
|
||||
CfgWriteBool("DEBUG","Show_Messages_Overruns", _MsgOverruns);
|
||||
CfgWriteBool("DEBUG","Show_Messages_CacheStats", _MsgCache);
|
||||
|
||||
CfgWriteBool("DEBUG","Log_Register_Access",AccessLog);
|
||||
CfgWriteBool("DEBUG","Log_DMA_Transfers", DMALog);
|
||||
CfgWriteBool("DEBUG","Log_WAVE_Output", WaveLog);
|
||||
CfgWriteBool("DEBUG","Log_Register_Access",_AccessLog);
|
||||
CfgWriteBool("DEBUG","Log_DMA_Transfers", _DMALog);
|
||||
CfgWriteBool("DEBUG","Log_WAVE_Output", _WaveLog);
|
||||
|
||||
CfgWriteBool("DEBUG","Dump_Info", CoresDump);
|
||||
CfgWriteBool("DEBUG","Dump_Memory",MemDump);
|
||||
CfgWriteBool("DEBUG","Dump_Regs", RegDump);
|
||||
CfgWriteBool("DEBUG","Dump_Info", _CoresDump);
|
||||
CfgWriteBool("DEBUG","Dump_Memory",_MemDump);
|
||||
CfgWriteBool("DEBUG","Dump_Regs", _RegDump);
|
||||
|
||||
CfgWriteStr("DEBUG","Access_Log_Filename",AccessLogFileName);
|
||||
CfgWriteStr("DEBUG","WaveLog_Filename", WaveLogFileName);
|
||||
|
@ -308,67 +358,83 @@ void WriteSettings()
|
|||
CfgWriteInt("MIXING","AutoDMA_Play_Rate_0",AutoDMAPlayRate[0]);
|
||||
CfgWriteInt("MIXING","AutoDMA_Play_Rate_1",AutoDMAPlayRate[1]);
|
||||
|
||||
CfgWriteBool("EFFECTS","Enable_Effects",EffectsEnabled);
|
||||
CfgWriteBool("MIXING","Enable_Effects",EffectsEnabled);
|
||||
|
||||
CfgWriteInt("OUTPUT","Output_Module",OutputModule);
|
||||
CfgWriteStr("OUTPUT","Output_Module",mods[OutputModule]->GetIdent() );
|
||||
CfgWriteInt("OUTPUT","Sample_Rate",SampleRate);
|
||||
CfgWriteInt("OUTPUT","Buffer_Size",CurBufferSize);
|
||||
CfgWriteInt("OUTPUT","Buffer_Count",MaxBufferCount);
|
||||
|
||||
CfgWriteInt("OUTPUT","Volume_Multiplier",VolumeMultiplier);
|
||||
CfgWriteInt("OUTPUT","Volume_Divisor",VolumeDivisor);
|
||||
|
||||
CfgWriteInt("OUTPUT","Channel_Gain_L", GainL);
|
||||
CfgWriteInt("OUTPUT","Channel_Gain_R", GainR);
|
||||
CfgWriteInt("OUTPUT","Channel_Gain_C", GainC);
|
||||
CfgWriteInt("OUTPUT","Channel_Gain_LFE",GainLFE);
|
||||
CfgWriteInt("OUTPUT","Channel_Gain_SL", GainSL);
|
||||
CfgWriteInt("OUTPUT","Channel_Gain_SR", GainSR);
|
||||
CfgWriteInt("OUTPUT","Channel_Center_In_LR", AddCLR);
|
||||
CfgWriteInt("OUTPUT","LFE_Lowpass_Frequency", LowpassLFE);
|
||||
|
||||
CfgWriteInt("OUTPUT","Latency",SndOutLatencyMS);
|
||||
CfgWriteBool("OUTPUT","Timestretch_Enable",timeStretchEnabled);
|
||||
CfgWriteInt("OUTPUT","Speed_Limit_Mode",LimitMode);
|
||||
|
||||
CfgWriteStr("OUTPUT","Asio_Driver_Name",AsioDriver);
|
||||
CfgWriteInt("OUTPUT","Volume_Shift",SndOutVolumeShiftBase - SndOutVolumeShift);
|
||||
|
||||
CfgWriteStr("DSOUNDOUT","Device",Config_DSoundOut.Device);
|
||||
CfgWriteInt("DSOUNDOUT","Buffer_Count",Config_DSoundOut.NumBuffers);
|
||||
|
||||
CfgWriteStr("WAVEOUT","Device",Config_WaveOut.Device);
|
||||
CfgWriteInt("WAVEOUT","Buffer_Count",Config_WaveOut.NumBuffers);
|
||||
|
||||
CfgWriteInt("DSOUND51","Channel_Gain_L", Config_DSound51.GainL);
|
||||
CfgWriteInt("DSOUND51","Channel_Gain_R", Config_DSound51.GainR);
|
||||
CfgWriteInt("DSOUND51","Channel_Gain_C", Config_DSound51.GainC);
|
||||
CfgWriteInt("DSOUND51","Channel_Gain_LFE",Config_DSound51.GainLFE);
|
||||
CfgWriteInt("DSOUND51","Channel_Gain_SL", Config_DSound51.GainSL);
|
||||
CfgWriteInt("DSOUND51","Channel_Gain_SR", Config_DSound51.GainSR);
|
||||
CfgWriteInt("DSOUND51","Channel_Center_In_LR", Config_DSound51.AddCLR);
|
||||
CfgWriteInt("DSOUND51","LFE_Lowpass_Frequency", Config_DSound51.LowpassLFE);
|
||||
|
||||
CfgWriteStr("ASIO","Asio_Driver_Name",AsioDriver);
|
||||
|
||||
CfgWriteStr("DSP PLUGIN","Filename",dspPlugin);
|
||||
CfgWriteInt("DSP PLUGIN","ModuleNum",dspPluginModule);
|
||||
CfgWriteBool("DSP PLUGIN","Enabled",dspPluginEnabled);
|
||||
|
||||
CfgWriteBool("DSP","Timestretch_Enable",timeStretchEnabled);
|
||||
|
||||
CfgWriteBool("KEYS","Limiter_Toggle_Enabled",LimiterToggleEnabled);
|
||||
CfgWriteInt ("KEYS","Limiter_Toggle",LimiterToggle);
|
||||
|
||||
CfgWriteStr("DirectSound Output (Stereo)","Device",DSoundDevice);
|
||||
}
|
||||
|
||||
static void EnableDebugMessages( HWND hWnd )
|
||||
{
|
||||
ENABLE_CONTROL(IDC_MSGSHOW, DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_MSGKEY, MsgToConsole());
|
||||
ENABLE_CONTROL(IDC_MSGVOICE,MsgToConsole());
|
||||
ENABLE_CONTROL(IDC_MSGDMA, MsgToConsole());
|
||||
ENABLE_CONTROL(IDC_MSGADMA, MsgDMA());
|
||||
ENABLE_CONTROL(IDC_DBG_OVERRUNS, MsgToConsole());
|
||||
ENABLE_CONTROL(IDC_DBG_CACHE, MsgToConsole());
|
||||
}
|
||||
|
||||
static void EnableDebugControls( HWND hWnd )
|
||||
{
|
||||
EnableDebugMessages( hWnd );
|
||||
ENABLE_CONTROL(IDC_LOGREGS, DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_LOGDMA, DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_LOGWAVE, DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_DUMPCORE,DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_DUMPMEM, DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_DUMPREGS,DebugEnabled);
|
||||
}
|
||||
|
||||
static int myWidth, myDebugWidth;
|
||||
static int myHeight;
|
||||
static bool debugShow = false;
|
||||
|
||||
BOOL CALLBACK ConfigProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
|
||||
{
|
||||
int wmId,wmEvent;
|
||||
char temp[20]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
char temp[384]={0};
|
||||
|
||||
switch(uMsg)
|
||||
{
|
||||
|
||||
case WM_PAINT:
|
||||
SET_CHECK(IDC_EFFECTS, EffectsEnabled);
|
||||
SET_CHECK(IDC_DEBUG, DebugEnabled);
|
||||
SET_CHECK(IDC_MSGKEY, DebugEnabled&MsgToConsole);
|
||||
SET_CHECK(IDC_MSGKEY, DebugEnabled&MsgKeyOnOff);
|
||||
SET_CHECK(IDC_MSGVOICE,DebugEnabled&MsgVoiceOff);
|
||||
SET_CHECK(IDC_MSGDMA, DebugEnabled&MsgDMA);
|
||||
SET_CHECK(IDC_MSGADMA, DebugEnabled&MsgDMA&MsgAutoDMA);
|
||||
SET_CHECK(IDC_LOGREGS, AccessLog);
|
||||
SET_CHECK(IDC_LOGDMA, DMALog);
|
||||
SET_CHECK(IDC_LOGWAVE, WaveLog);
|
||||
SET_CHECK(IDC_DUMPCORE,CoresDump);
|
||||
SET_CHECK(IDC_DUMPMEM, MemDump);
|
||||
SET_CHECK(IDC_DUMPREGS,RegDump);
|
||||
SET_CHECK(IDC_SPEEDLIMIT,LimitMode);
|
||||
return FALSE;
|
||||
|
||||
case WM_INITDIALOG:
|
||||
|
||||
// If debugging is enabled, show the debug box by default:
|
||||
debugShow = DebugEnabled;
|
||||
|
||||
SendMessage(GetDlgItem(hWnd,IDC_SRATE),CB_RESETCONTENT,0,0);
|
||||
SendMessage(GetDlgItem(hWnd,IDC_SRATE),CB_ADDSTRING,0,(LPARAM)"16000");
|
||||
SendMessage(GetDlgItem(hWnd,IDC_SRATE),CB_ADDSTRING,0,(LPARAM)"22050");
|
||||
|
@ -377,62 +443,64 @@ BOOL CALLBACK ConfigProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
|
|||
SendMessage(GetDlgItem(hWnd,IDC_SRATE),CB_ADDSTRING,0,(LPARAM)"44100");
|
||||
SendMessage(GetDlgItem(hWnd,IDC_SRATE),CB_ADDSTRING,0,(LPARAM)"48000");
|
||||
|
||||
sprintf(temp,"%d",SampleRate);
|
||||
sprintf_s(temp,48,"%d",SampleRate);
|
||||
SetDlgItemText(hWnd,IDC_SRATE,temp);
|
||||
|
||||
SendMessage(GetDlgItem(hWnd,IDC_INTERPOLATE),CB_RESETCONTENT,0,0);
|
||||
SendMessage(GetDlgItem(hWnd,IDC_INTERPOLATE),CB_ADDSTRING,0,(LPARAM)"0 - Nearest (none)");
|
||||
SendMessage(GetDlgItem(hWnd,IDC_INTERPOLATE),CB_ADDSTRING,0,(LPARAM)"1 - Linear (mid)");
|
||||
SendMessage(GetDlgItem(hWnd,IDC_INTERPOLATE),CB_ADDSTRING,0,(LPARAM)"2 - Cubic (good)");
|
||||
SendMessage(GetDlgItem(hWnd,IDC_INTERPOLATE),CB_ADDSTRING,0,(LPARAM)"0 - Nearest (none/fast)");
|
||||
SendMessage(GetDlgItem(hWnd,IDC_INTERPOLATE),CB_ADDSTRING,0,(LPARAM)"1 - Linear (recommended)");
|
||||
SendMessage(GetDlgItem(hWnd,IDC_INTERPOLATE),CB_ADDSTRING,0,(LPARAM)"2 - Cubic (better/slower)");
|
||||
SendMessage(GetDlgItem(hWnd,IDC_INTERPOLATE),CB_SETCURSEL,Interpolation,0);
|
||||
|
||||
SendMessage(GetDlgItem(hWnd,IDC_OUTPUT),CB_RESETCONTENT,0,0);
|
||||
SendMessage(GetDlgItem(hWnd,IDC_OUTPUT),CB_ADDSTRING,0,(LPARAM)"0 - Disabled (Emulate only)");
|
||||
SendMessage(GetDlgItem(hWnd,IDC_OUTPUT),CB_ADDSTRING,0,(LPARAM)"1 - waveOut (Slow/Laggy)");
|
||||
SendMessage(GetDlgItem(hWnd,IDC_OUTPUT),CB_ADDSTRING,0,(LPARAM)"2 - DSound (Typical)");
|
||||
SendMessage(GetDlgItem(hWnd,IDC_OUTPUT),CB_ADDSTRING,0,(LPARAM)"3 - DSound 5.1 (Experimental)");
|
||||
SendMessage(GetDlgItem(hWnd,IDC_OUTPUT),CB_ADDSTRING,0,(LPARAM)"4 - ASIO (Low Latency, BROKEN)");
|
||||
SendMessage(GetDlgItem(hWnd,IDC_OUTPUT),CB_ADDSTRING,0,(LPARAM)"5 - XAudio2 (Experimental)");
|
||||
SendMessage(GetDlgItem(hWnd,IDC_OUTPUT),CB_RESETCONTENT,0,0);
|
||||
|
||||
{
|
||||
int modidx = 0;
|
||||
while( mods[modidx] != NULL )
|
||||
{
|
||||
sprintf_s( temp, 72, "%d - %s", modidx, mods[modidx]->GetLongName() );
|
||||
SendMessage(GetDlgItem(hWnd,IDC_OUTPUT),CB_ADDSTRING,0,(LPARAM)temp);
|
||||
++modidx;
|
||||
}
|
||||
SendMessage(GetDlgItem(hWnd,IDC_OUTPUT),CB_SETCURSEL,OutputModule,0);
|
||||
}
|
||||
|
||||
INIT_SLIDER(IDC_BUFFER,512,16384,4096,2048,512);
|
||||
//INIT_SLIDER(IDC_BUFFER,512,16384,4096,2048,512);
|
||||
INIT_SLIDER( IDC_LATENCY_SLIDER, 20, 420, 100, 20, 5 );
|
||||
|
||||
SendMessage(GetDlgItem(hWnd,IDC_BUFFER),TBM_SETPOS,TRUE,CurBufferSize);
|
||||
sprintf(temp,"%d",CurBufferSize);
|
||||
SetWindowText(GetDlgItem(hWnd,IDC_BSIZE),temp);
|
||||
SendMessage(GetDlgItem(hWnd,IDC_LATENCY_SLIDER),TBM_SETPOS,TRUE,SndOutLatencyMS);
|
||||
sprintf_s(temp,80,"%d ms (avg)",SndOutLatencyMS);
|
||||
SetWindowText(GetDlgItem(hWnd,IDC_LATENCY_LABEL),temp);
|
||||
|
||||
sprintf(temp,"%d",MaxBufferCount);
|
||||
SetWindowText(GetDlgItem(hWnd,IDC_BCOUNT),temp);
|
||||
|
||||
ENABLE_CONTROL(IDC_MSGSHOW, DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_MSGKEY, DebugEnabled&MsgToConsole);
|
||||
ENABLE_CONTROL(IDC_MSGVOICE,DebugEnabled&MsgToConsole);
|
||||
ENABLE_CONTROL(IDC_MSGDMA, DebugEnabled&MsgToConsole);
|
||||
ENABLE_CONTROL(IDC_MSGADMA, DebugEnabled&MsgToConsole&MsgDMA);
|
||||
ENABLE_CONTROL(IDC_LOGREGS, DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_LOGDMA, DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_LOGWAVE, DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_DUMPCORE,DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_DUMPMEM, DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_DUMPREGS,DebugEnabled);
|
||||
EnableDebugControls( hWnd );
|
||||
|
||||
// Debugging / Logging Flags:
|
||||
SET_CHECK(IDC_EFFECTS, EffectsEnabled);
|
||||
SET_CHECK(IDC_DEBUG, DebugEnabled);
|
||||
SET_CHECK(IDC_MSGSHOW, MsgToConsole);
|
||||
SET_CHECK(IDC_MSGKEY, MsgKeyOnOff);
|
||||
SET_CHECK(IDC_MSGVOICE,MsgVoiceOff);
|
||||
SET_CHECK(IDC_MSGDMA, MsgDMA);
|
||||
SET_CHECK(IDC_MSGADMA, MsgAutoDMA);
|
||||
SET_CHECK(IDC_LOGREGS, AccessLog);
|
||||
SET_CHECK(IDC_LOGDMA, DMALog);
|
||||
SET_CHECK(IDC_LOGWAVE, WaveLog);
|
||||
SET_CHECK(IDC_DUMPCORE,CoresDump);
|
||||
SET_CHECK(IDC_DUMPMEM, MemDump);
|
||||
SET_CHECK(IDC_DUMPREGS,RegDump);
|
||||
SET_CHECK(IDC_MSGKEY, _MsgToConsole);
|
||||
SET_CHECK(IDC_MSGKEY, _MsgKeyOnOff);
|
||||
SET_CHECK(IDC_MSGVOICE,_MsgVoiceOff);
|
||||
SET_CHECK(IDC_MSGDMA, _MsgDMA);
|
||||
SET_CHECK(IDC_MSGADMA, _MsgAutoDMA);
|
||||
SET_CHECK(IDC_DBG_OVERRUNS, _MsgOverruns );
|
||||
SET_CHECK(IDC_DBG_CACHE, _MsgCache );
|
||||
SET_CHECK(IDC_LOGREGS, _AccessLog);
|
||||
SET_CHECK(IDC_LOGDMA, _DMALog);
|
||||
SET_CHECK(IDC_LOGWAVE, _WaveLog);
|
||||
SET_CHECK(IDC_DUMPCORE,_CoresDump);
|
||||
SET_CHECK(IDC_DUMPMEM, _MemDump);
|
||||
SET_CHECK(IDC_DUMPREGS,_RegDump);
|
||||
|
||||
SET_CHECK(IDC_SPEEDLIMIT,LimitMode);
|
||||
SET_CHECK(IDC_SPEEDLIMIT_RUNTIME_TOGGLE,LimiterToggleEnabled);
|
||||
SET_CHECK(IDC_DSP_ENABLE,dspPluginEnabled);
|
||||
SET_CHECK(IDC_TS_ENABLE,timeStretchEnabled);
|
||||
|
||||
VolumeBoostEnabled = ( VolumeShiftModifier > 0 ) ? true : false;
|
||||
SET_CHECK(IDC_VOLBOOST, VolumeBoostEnabled );
|
||||
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
wmId = LOWORD(wParam);
|
||||
wmEvent = HIWORD(wParam);
|
||||
|
@ -444,49 +512,14 @@ BOOL CALLBACK ConfigProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
|
|||
temp[19]=0;
|
||||
SampleRate=atoi(temp);
|
||||
|
||||
GetDlgItemText(hWnd,IDC_BSIZE,temp,20);
|
||||
temp[19]=0;
|
||||
CurBufferSize=atoi(temp);
|
||||
SndOutLatencyMS = (int)SendMessage( GetDlgItem( hWnd, IDC_LATENCY_SLIDER ), TBM_GETPOS, 0, 0 );
|
||||
|
||||
if(CurBufferSize<512) CurBufferSize=512;
|
||||
if(CurBufferSize>16384) CurBufferSize=16384;
|
||||
|
||||
GetDlgItemText(hWnd,IDC_BCOUNT,temp,20);
|
||||
temp[19]=0;
|
||||
MaxBufferCount=atoi(temp);
|
||||
|
||||
if(MaxBufferCount<4) MaxBufferCount=4;
|
||||
if(MaxBufferCount>50) MaxBufferCount=50;
|
||||
if( SndOutLatencyMS > 420 ) SndOutLatencyMS = 420;
|
||||
if( SndOutLatencyMS < 20 ) SndOutLatencyMS = 20;
|
||||
|
||||
Interpolation=(int)SendMessage(GetDlgItem(hWnd,IDC_INTERPOLATE),CB_GETCURSEL,0,0);
|
||||
OutputModule=(int)SendMessage(GetDlgItem(hWnd,IDC_OUTPUT),CB_GETCURSEL,0,0);
|
||||
|
||||
/*
|
||||
if((BufferSize*CurBufferCount)<9600)
|
||||
{
|
||||
int ret=MessageBoxEx(hWnd,"The total buffer space is too small and might cause problems.\n"
|
||||
"Press [Cancel] to go back and increase the buffer size or number.",
|
||||
"WARNING",MB_OKCANCEL | MB_ICONEXCLAMATION, 0);
|
||||
if(ret==IDCANCEL)
|
||||
break;
|
||||
}
|
||||
*/
|
||||
|
||||
DebugEnabled=DebugEnabled;
|
||||
MsgToConsole=DebugEnabled&MsgToConsole;
|
||||
MsgKeyOnOff =DebugEnabled&MsgToConsole&MsgKeyOnOff;
|
||||
MsgVoiceOff =DebugEnabled&MsgToConsole&MsgVoiceOff;
|
||||
MsgDMA =DebugEnabled&MsgToConsole&MsgDMA;
|
||||
MsgAutoDMA =DebugEnabled&MsgToConsole&MsgAutoDMA;
|
||||
AccessLog =DebugEnabled&AccessLog;
|
||||
DMALog =DebugEnabled&DMALog;
|
||||
WaveLog =DebugEnabled&WaveLog;
|
||||
|
||||
CoresDump =DebugEnabled&CoresDump;
|
||||
MemDump =DebugEnabled&MemDump;
|
||||
RegDump =DebugEnabled&RegDump;
|
||||
|
||||
|
||||
WriteSettings();
|
||||
EndDialog(hWnd,0);
|
||||
break;
|
||||
|
@ -495,45 +528,41 @@ BOOL CALLBACK ConfigProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
|
|||
break;
|
||||
|
||||
case IDC_OUTCONF:
|
||||
SndConfigure(hWnd);
|
||||
SndConfigure( hWnd,
|
||||
(int)SendMessage(GetDlgItem(hWnd,IDC_OUTPUT),CB_GETCURSEL,0,0)
|
||||
);
|
||||
break;
|
||||
|
||||
HANDLE_CHECKNB( IDC_VOLBOOST, VolumeBoostEnabled );
|
||||
VolumeShiftModifier = (VolumeBoostEnabled ? 1 : 0 );
|
||||
SndOutVolumeShift = SndOutVolumeShiftBase - VolumeShiftModifier;
|
||||
break;
|
||||
|
||||
|
||||
HANDLE_CHECK(IDC_EFFECTS,EffectsEnabled);
|
||||
HANDLE_CHECKNB(IDC_DEBUG,DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_MSGSHOW, DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_MSGKEY, DebugEnabled&MsgToConsole);
|
||||
ENABLE_CONTROL(IDC_MSGVOICE,DebugEnabled&MsgToConsole);
|
||||
ENABLE_CONTROL(IDC_MSGDMA, DebugEnabled&MsgToConsole);
|
||||
ENABLE_CONTROL(IDC_MSGADMA, DebugEnabled&MsgToConsole&MsgDMA);
|
||||
ENABLE_CONTROL(IDC_LOGREGS, DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_LOGDMA, DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_LOGWAVE, DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_DUMPCORE,DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_DUMPMEM, DebugEnabled);
|
||||
ENABLE_CONTROL(IDC_DUMPREGS,DebugEnabled);
|
||||
EnableDebugControls( hWnd );
|
||||
break;
|
||||
HANDLE_CHECKNB(IDC_MSGSHOW,MsgToConsole);
|
||||
ENABLE_CONTROL(IDC_MSGKEY, DebugEnabled&MsgToConsole);
|
||||
ENABLE_CONTROL(IDC_MSGVOICE,DebugEnabled&MsgToConsole);
|
||||
ENABLE_CONTROL(IDC_MSGDMA, DebugEnabled&MsgToConsole);
|
||||
ENABLE_CONTROL(IDC_MSGADMA, DebugEnabled&MsgToConsole&MsgDMA);
|
||||
HANDLE_CHECKNB(IDC_MSGSHOW,_MsgToConsole);
|
||||
EnableDebugMessages( hWnd );
|
||||
break;
|
||||
HANDLE_CHECK(IDC_MSGKEY,MsgKeyOnOff);
|
||||
HANDLE_CHECK(IDC_MSGVOICE,MsgVoiceOff);
|
||||
HANDLE_CHECKNB(IDC_MSGDMA,MsgDMA);
|
||||
ENABLE_CONTROL(IDC_MSGADMA, DebugEnabled&MsgToConsole&MsgDMA);
|
||||
HANDLE_CHECK(IDC_MSGKEY,_MsgKeyOnOff);
|
||||
HANDLE_CHECK(IDC_MSGVOICE,_MsgVoiceOff);
|
||||
HANDLE_CHECKNB(IDC_MSGDMA,_MsgDMA);
|
||||
ENABLE_CONTROL(IDC_MSGADMA, MsgDMA());
|
||||
break;
|
||||
HANDLE_CHECK(IDC_MSGADMA,MsgAutoDMA);
|
||||
HANDLE_CHECK(IDC_LOGREGS,AccessLog);
|
||||
HANDLE_CHECK(IDC_LOGDMA, DMALog);
|
||||
HANDLE_CHECK(IDC_LOGWAVE,WaveLog);
|
||||
HANDLE_CHECK(IDC_DUMPCORE,CoresDump);
|
||||
HANDLE_CHECK(IDC_DUMPMEM, MemDump);
|
||||
HANDLE_CHECK(IDC_DUMPREGS,RegDump);
|
||||
HANDLE_CHECK(IDC_SPEEDLIMIT,LimitMode);
|
||||
HANDLE_CHECK(IDC_MSGADMA,_MsgAutoDMA);
|
||||
HANDLE_CHECK(IDC_DBG_OVERRUNS,_MsgOverruns);
|
||||
HANDLE_CHECK(IDC_DBG_CACHE,_MsgCache);
|
||||
HANDLE_CHECK(IDC_LOGREGS,_AccessLog);
|
||||
HANDLE_CHECK(IDC_LOGDMA, _DMALog);
|
||||
HANDLE_CHECK(IDC_LOGWAVE,_WaveLog);
|
||||
HANDLE_CHECK(IDC_DUMPCORE,_CoresDump);
|
||||
HANDLE_CHECK(IDC_DUMPMEM, _MemDump);
|
||||
HANDLE_CHECK(IDC_DUMPREGS,_RegDump);
|
||||
HANDLE_CHECK(IDC_DSP_ENABLE,dspPluginEnabled);
|
||||
HANDLE_CHECK(IDC_TS_ENABLE,timeStretchEnabled);
|
||||
HANDLE_CHECK(IDC_SPEEDLIMIT,LimitMode);
|
||||
HANDLE_CHECK(IDC_SPEEDLIMIT_RUNTIME_TOGGLE,LimiterToggleEnabled);
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -550,11 +579,11 @@ BOOL CALLBACK ConfigProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
|
|||
case TB_PAGEDOWN:
|
||||
wmEvent=(int)SendMessage((HWND)lParam,TBM_GETPOS,0,0);
|
||||
case TB_THUMBTRACK:
|
||||
if(wmEvent<512) wmEvent=512;
|
||||
if(wmEvent>24000) wmEvent=24000;
|
||||
if(wmEvent<20) wmEvent=20;
|
||||
if(wmEvent>420) wmEvent=420;
|
||||
SendMessage((HWND)lParam,TBM_SETPOS,TRUE,wmEvent);
|
||||
sprintf(temp,"%d",wmEvent);
|
||||
SetDlgItemText(hWnd,IDC_BSIZE,temp);
|
||||
sprintf_s(temp,80,"%d ms (avg)",wmEvent);
|
||||
SetDlgItemText(hWnd,IDC_LATENCY_LABEL,temp);
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
|
|
|
@ -21,19 +21,39 @@
|
|||
|
||||
extern bool DebugEnabled;
|
||||
|
||||
extern bool MsgToConsole;
|
||||
extern bool MsgKeyOnOff;
|
||||
extern bool MsgVoiceOff;
|
||||
extern bool MsgDMA;
|
||||
extern bool MsgAutoDMA;
|
||||
extern bool _MsgToConsole;
|
||||
extern bool _MsgKeyOnOff;
|
||||
extern bool _MsgVoiceOff;
|
||||
extern bool _MsgDMA;
|
||||
extern bool _MsgAutoDMA;
|
||||
extern bool _MsgOverruns;
|
||||
extern bool _MsgCache;
|
||||
|
||||
extern bool AccessLog;
|
||||
extern bool DMALog;
|
||||
extern bool WaveLog;
|
||||
extern bool _AccessLog;
|
||||
extern bool _DMALog;
|
||||
extern bool _WaveLog;
|
||||
|
||||
extern bool _CoresDump;
|
||||
extern bool _MemDump;
|
||||
extern bool _RegDump;
|
||||
|
||||
static __forceinline bool MsgToConsole() { return _MsgToConsole & DebugEnabled; }
|
||||
|
||||
static __forceinline bool MsgKeyOnOff() { return _MsgKeyOnOff & MsgToConsole(); }
|
||||
static __forceinline bool MsgVoiceOff() { return _MsgVoiceOff & MsgToConsole(); }
|
||||
static __forceinline bool MsgDMA() { return _MsgDMA & MsgToConsole(); }
|
||||
static __forceinline bool MsgAutoDMA() { return _MsgAutoDMA & MsgToConsole(); }
|
||||
static __forceinline bool MsgOverruns() { return _MsgOverruns & MsgToConsole(); }
|
||||
static __forceinline bool MsgCache() { return _MsgCache & MsgToConsole(); }
|
||||
|
||||
static __forceinline bool AccessLog() { return _AccessLog & DebugEnabled; }
|
||||
static __forceinline bool DMALog() { return _DMALog & DebugEnabled; }
|
||||
static __forceinline bool WaveLog() { return _WaveLog & DebugEnabled; }
|
||||
|
||||
static __forceinline bool CoresDump() { return _CoresDump & DebugEnabled; }
|
||||
static __forceinline bool MemDump() { return _MemDump & DebugEnabled; }
|
||||
static __forceinline bool RegDump() { return _RegDump & DebugEnabled; }
|
||||
|
||||
extern bool CoresDump;
|
||||
extern bool MemDump;
|
||||
extern bool RegDump;
|
||||
|
||||
extern char AccessLogFileName[255];
|
||||
extern char WaveLogFileName[255];
|
||||
|
@ -55,27 +75,16 @@ extern bool EffectsEnabled;
|
|||
|
||||
extern int AutoDMAPlayRate[2];
|
||||
|
||||
extern int OutputModule;
|
||||
extern int CurBufferSize;
|
||||
extern int CurBufferCount;
|
||||
extern int MaxBufferCount;
|
||||
extern u32 OutputModule;
|
||||
extern int SndOutLatencyMS;
|
||||
|
||||
extern int VolumeMultiplier;
|
||||
extern int VolumeDivisor;
|
||||
//extern int VolumeMultiplier;
|
||||
//extern int VolumeDivisor;
|
||||
|
||||
extern int LimitMode;
|
||||
|
||||
extern char AsioDriver[129];
|
||||
|
||||
extern u32 GainL;
|
||||
extern u32 GainR;
|
||||
extern u32 GainC;
|
||||
extern u32 GainLFE;
|
||||
extern u32 GainSL;
|
||||
extern u32 GainSR;
|
||||
extern u32 AddCLR;
|
||||
extern u32 LowpassLFE;
|
||||
|
||||
extern char dspPlugin[];
|
||||
extern int dspPluginModule;
|
||||
|
||||
|
@ -85,9 +94,82 @@ extern bool timeStretchEnabled;
|
|||
extern bool LimiterToggleEnabled;
|
||||
extern int LimiterToggle;
|
||||
|
||||
/// module-specific settings
|
||||
// *** BEGIN DRIVER-SPECIFIC CONFIGURATION ***
|
||||
// -------------------------------------------
|
||||
|
||||
extern char DSoundDevice[];
|
||||
// DSOUND
|
||||
struct CONFIG_DSOUNDOUT
|
||||
{
|
||||
char Device[256];
|
||||
s8 NumBuffers;
|
||||
|
||||
CONFIG_DSOUNDOUT() :
|
||||
NumBuffers( 3 )
|
||||
{
|
||||
memset( Device, 0, sizeof( Device ) );
|
||||
}
|
||||
};
|
||||
|
||||
// WAVEOUT
|
||||
struct CONFIG_WAVEOUT
|
||||
{
|
||||
char Device[255];
|
||||
s8 NumBuffers;
|
||||
|
||||
CONFIG_WAVEOUT() :
|
||||
NumBuffers( 4 )
|
||||
{
|
||||
memset( Device, 0, sizeof( Device ) );
|
||||
}
|
||||
};
|
||||
|
||||
// DSOUND51
|
||||
struct CONFIG_DSOUND51
|
||||
{
|
||||
char Device[256];
|
||||
u32 NumBuffers;
|
||||
|
||||
u32 GainL;
|
||||
u32 GainR;
|
||||
u32 GainSL;
|
||||
u32 GainSR;
|
||||
u32 GainC;
|
||||
u32 GainLFE;
|
||||
u32 AddCLR;
|
||||
u32 LowpassLFE;
|
||||
|
||||
// C++ style struct/class initializer
|
||||
CONFIG_DSOUND51() :
|
||||
NumBuffers( 4 )
|
||||
, GainL( 256 )
|
||||
, GainR( 256 )
|
||||
, GainSL( 200 )
|
||||
, GainSR( 200 )
|
||||
, GainC( 200 )
|
||||
, GainLFE( 256 )
|
||||
, AddCLR( 56 )
|
||||
, LowpassLFE( 80 )
|
||||
{
|
||||
memset( Device, 0, sizeof( Device ) );
|
||||
}
|
||||
};
|
||||
|
||||
struct CONFIG_ASIO
|
||||
{
|
||||
s8 NumBuffers;
|
||||
|
||||
CONFIG_ASIO() :
|
||||
NumBuffers( 8 )
|
||||
{
|
||||
//memset( Device, 0, sizeof( Device ) );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
extern CONFIG_DSOUNDOUT Config_DSoundOut;
|
||||
extern CONFIG_DSOUND51 Config_DSound51;
|
||||
extern CONFIG_WAVEOUT Config_WaveOut;
|
||||
extern CONFIG_ASIO Config_Asio;
|
||||
|
||||
|
||||
//////
|
||||
|
@ -96,4 +178,4 @@ void ReadSettings();
|
|||
void WriteSettings();
|
||||
void configure();
|
||||
|
||||
#endif // CONFIG_H_INCLUDED
|
||||
#endif // CONFIG_H_INCLUDED
|
||||
|
|
|
@ -29,8 +29,7 @@ void FileLog(const char *fmt, ...) {
|
|||
int n;
|
||||
va_list list;
|
||||
|
||||
if(!DebugEnabled) return;
|
||||
if(!AccessLog) return;
|
||||
if(!AccessLog()) return;
|
||||
if(!spu2Log) return;
|
||||
|
||||
va_start(list, fmt);
|
||||
|
@ -55,8 +54,7 @@ void ConLog(const char *fmt, ...) {
|
|||
int n;
|
||||
va_list list;
|
||||
|
||||
if(!DebugEnabled) return;
|
||||
if(!MsgToConsole) return;
|
||||
if(!MsgToConsole()) return;
|
||||
|
||||
va_start(list, fmt);
|
||||
n=vsprintf(s,fmt, list);
|
||||
|
@ -78,14 +76,14 @@ void DoFullDump() {
|
|||
FILE *dump;
|
||||
u8 c=0, v=0;
|
||||
|
||||
if(MemDump) {
|
||||
if(MemDump()) {
|
||||
dump=fopen(MemDumpFileName,"wb");
|
||||
if (dump) {
|
||||
fwrite(_spu2mem,0x200000,1,dump);
|
||||
fclose(dump);
|
||||
}
|
||||
}
|
||||
if(RegDump) {
|
||||
if(RegDump()) {
|
||||
dump=fopen(RegDumpFileName,"wb");
|
||||
if (dump) {
|
||||
fwrite(spu2regs,0x2000,1,dump);
|
||||
|
@ -93,7 +91,7 @@ void DoFullDump() {
|
|||
}
|
||||
}
|
||||
|
||||
if(!CoresDump) return;
|
||||
if(!CoresDump()) return;
|
||||
dump=fopen(CoresDumpFileName,"wt");
|
||||
if (dump) {
|
||||
for(c=0;c<2;c++) {
|
||||
|
|
|
@ -34,7 +34,7 @@ u16* MBASE[2] = {0,0};
|
|||
u16* DMABaseAddr;
|
||||
|
||||
void DMALogOpen() {
|
||||
if(!DMALog) return;
|
||||
if(!DMALog()) return;
|
||||
DMA4LogFile=fopen(DMA4LogFileName,"wb");
|
||||
DMA7LogFile=fopen(DMA7LogFileName,"wb");
|
||||
ADMA4LogFile=fopen("logs/adma4.raw","wb");
|
||||
|
@ -44,42 +44,42 @@ void DMALogOpen() {
|
|||
//REGWRTLogFile[1]=fopen("logs/RegWrite1.raw","wb");
|
||||
}
|
||||
void DMA4LogWrite(void *lpData, u32 ulSize) {
|
||||
if(!DMALog) return;
|
||||
if(!DMALog()) return;
|
||||
if (!DMA4LogFile) return;
|
||||
fwrite(lpData,ulSize,1,DMA4LogFile);
|
||||
}
|
||||
|
||||
void DMA7LogWrite(void *lpData, u32 ulSize) {
|
||||
if(!DMALog) return;
|
||||
if(!DMALog()) return;
|
||||
if (!DMA7LogFile) return;
|
||||
fwrite(lpData,ulSize,1,DMA7LogFile);
|
||||
}
|
||||
|
||||
void ADMA4LogWrite(void *lpData, u32 ulSize) {
|
||||
if(!DMALog) return;
|
||||
if(!DMALog()) return;
|
||||
if (!ADMA4LogFile) return;
|
||||
fwrite(lpData,ulSize,1,ADMA4LogFile);
|
||||
}
|
||||
void ADMA7LogWrite(void *lpData, u32 ulSize) {
|
||||
if(!DMALog) return;
|
||||
if(!DMALog()) return;
|
||||
if (!ADMA7LogFile) return;
|
||||
fwrite(lpData,ulSize,1,ADMA7LogFile);
|
||||
}
|
||||
void ADMAOutLogWrite(void *lpData, u32 ulSize) {
|
||||
if(!DMALog) return;
|
||||
if(!DMALog()) return;
|
||||
if (!ADMAOutLogFile) return;
|
||||
fwrite(lpData,ulSize,1,ADMAOutLogFile);
|
||||
}
|
||||
|
||||
void RegWriteLog(u32 core,u16 value)
|
||||
{
|
||||
if(!DMALog) return;
|
||||
if(!DMALog()) return;
|
||||
if (!REGWRTLogFile[core]) return;
|
||||
fwrite(&value,2,1,REGWRTLogFile[core]);
|
||||
}
|
||||
|
||||
void DMALogClose() {
|
||||
if(!DMALog) return;
|
||||
if(!DMALog()) return;
|
||||
if (DMA4LogFile) fclose(DMA4LogFile);
|
||||
if (DMA7LogFile) fclose(DMA7LogFile);
|
||||
if (REGWRTLogFile[0]) fclose(REGWRTLogFile[0]);
|
||||
|
@ -142,7 +142,7 @@ void AutoDMAReadBuffer(int core, int mode) //mode: 0= split stereo; 1 = do not s
|
|||
void StartADMAWrite(int core,u16 *pMem, u32 sz)
|
||||
{
|
||||
int size=(sz)&(~511);
|
||||
if(MsgAutoDMA) ConLog(" * SPU2: DMA%c AutoDMA Transfer of %d bytes to %x (%02x %x %04x).\n",(core==0)?'4':'7',size<<1,Cores[core].TSA,Cores[core].DMABits,Cores[core].AutoDMACtrl,(~Cores[core].Regs.ATTR)&0x7fff);
|
||||
if(MsgAutoDMA()) ConLog(" * SPU2: DMA%c AutoDMA Transfer of %d bytes to %x (%02x %x %04x).\n",(core==0)?'4':'7',size<<1,Cores[core].TSA,Cores[core].DMABits,Cores[core].AutoDMACtrl,(~Cores[core].Regs.ATTR)&0x7fff);
|
||||
|
||||
Cores[core].InputDataProgress=0;
|
||||
if((Cores[core].AutoDMACtrl&(core+1))==0)
|
||||
|
@ -202,7 +202,7 @@ void DoDMAWrite(int core,u16 *pMem,u32 size)
|
|||
else
|
||||
DMA7LogWrite(pMem,size<<1);
|
||||
|
||||
if(MsgDMA) ConLog(" * SPU2: DMA%c Transfer of %d bytes to %x (%02x %x %04x).\n",(core==0)?'4':'7',size<<1,Cores[core].TSA,Cores[core].DMABits,Cores[core].AutoDMACtrl,(~Cores[core].Regs.ATTR)&0x7fff);
|
||||
if(MsgDMA()) ConLog(" * SPU2: DMA%c Transfer of %d bytes to %x (%02x %x %04x).\n",(core==0)?'4':'7',size<<1,Cores[core].TSA,Cores[core].DMABits,Cores[core].AutoDMACtrl,(~Cores[core].Regs.ATTR)&0x7fff);
|
||||
|
||||
Cores[core].TDA=Cores[core].TSA;
|
||||
for (i=0;i<size;i++) {
|
||||
|
|
|
@ -48,11 +48,11 @@ extern HRESULT GUIDFromString(const char *str, LPGUID guid);
|
|||
class DSound51: public SndOutModule
|
||||
{
|
||||
private:
|
||||
# define PI 3.14159265f
|
||||
# define MAX_BUFFER_COUNT 8
|
||||
|
||||
# define BufferSize (CurBufferSize*6)
|
||||
# define BufferSizeBytes (BufferSize<<1)
|
||||
# define TBufferSize (BufferSize*CurBufferCount)
|
||||
static const int PacketsPerBuffer = (1024 / SndOutPacketSize);
|
||||
static const int BufferSize = SndOutPacketSize*PacketsPerBuffer * 6;
|
||||
static const int BufferSizeBytes = BufferSize << 1;
|
||||
|
||||
s32* tbuffer;
|
||||
|
||||
|
@ -64,8 +64,6 @@ private:
|
|||
HANDLE thread;
|
||||
DWORD tid;
|
||||
|
||||
#define MAX_BUFFER_COUNT 3
|
||||
|
||||
IDirectSound8* dsound;
|
||||
IDirectSoundBuffer8* buffer;
|
||||
IDirectSoundNotify8* buffer_notify;
|
||||
|
@ -206,12 +204,12 @@ private:
|
|||
SL = (SLd * 209 + SC * 148)>>8; //16.0
|
||||
SR = (SRd * 209 + SC * 148)>>8; //16.0
|
||||
|
||||
obuffer[0]=spdif_data[0] + (((L * GainL ) + (C * AddCLR))>>8);
|
||||
obuffer[1]=spdif_data[1] + (((R * GainR ) + (C * AddCLR))>>8);
|
||||
obuffer[2]=spdif_data[2] + (((C * GainC ))>>8);
|
||||
obuffer[3]=spdif_data[3] + (((LFE * GainLFE))>>8);
|
||||
obuffer[4]=spdif_data[4] + (((SL * GainSL ))>>8);
|
||||
obuffer[5]=spdif_data[5] + (((SR * GainSR ))>>8);
|
||||
obuffer[0]=spdif_data[0] + (((L * Config_DSound51.GainL ) + (C * Config_DSound51.AddCLR))>>8);
|
||||
obuffer[1]=spdif_data[1] + (((R * Config_DSound51.GainR ) + (C * Config_DSound51.AddCLR))>>8);
|
||||
obuffer[2]=spdif_data[2] + (((C * Config_DSound51.GainC ))>>8);
|
||||
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);
|
||||
#else
|
||||
obuffer[0]=spdif_data[0]+(ValL>>8);
|
||||
obuffer[1]=spdif_data[1]+(ValR>>8);
|
||||
|
@ -245,33 +243,35 @@ private:
|
|||
{
|
||||
while( dsound_running )
|
||||
{
|
||||
u32 rv = WaitForMultipleObjects(MAX_BUFFER_COUNT,buffer_events,FALSE,400);
|
||||
u32 rv = WaitForMultipleObjects(Config_DSound51.NumBuffers,buffer_events,FALSE,200);
|
||||
|
||||
LPVOID p1,p2;
|
||||
s16* p1, *oldp1;
|
||||
LPVOID p2;
|
||||
DWORD s1,s2;
|
||||
|
||||
for(int i=0;i<MAX_BUFFER_COUNT;i++)
|
||||
u32 poffset=BufferSizeBytes * rv;
|
||||
|
||||
verifyc(buffer->Lock(poffset,BufferSizeBytes,(LPVOID*)&p1,&s1,&p2,&s2,0));
|
||||
oldp1 = p1;
|
||||
|
||||
for(int p=0; p<PacketsPerBuffer; p++, p1+=SndOutPacketSize )
|
||||
{
|
||||
if (rv==WAIT_OBJECT_0+i)
|
||||
s32 temp[SndOutPacketSize];
|
||||
s32* s = temp;
|
||||
s16* t = p1;
|
||||
|
||||
buff->ReadSamples( temp );
|
||||
for(int j=0;j<SndOutPacketSize/2;j++)
|
||||
{
|
||||
u32 poffset=BufferSizeBytes * i;
|
||||
// DPL2 code here: inputs s[0] and s[1]. outputs t[0] to t[5]
|
||||
Convert(t,s[0],s[1]);
|
||||
|
||||
buff->ReadSamples(tbuffer,CurBufferSize*2);
|
||||
|
||||
verifyc(buffer->Lock(poffset,BufferSizeBytes,&p1,&s1,&p2,&s2,0));
|
||||
s16 *t = (s16*)p1;
|
||||
s32 *s = tbuffer;
|
||||
for(int j=0;j<CurBufferSize;j++)
|
||||
{
|
||||
// DPL2 code here: inputs s[0] and s[1]. outputs t[0] to t[5]
|
||||
Convert(t,s[0],s[1]);
|
||||
|
||||
t+=6;
|
||||
s+=2;
|
||||
}
|
||||
verifyc(buffer->Unlock(p1,s1,p2,s2));
|
||||
}
|
||||
t+=6;
|
||||
s+=2;
|
||||
}
|
||||
}
|
||||
|
||||
verifyc(buffer->Unlock(oldp1,s1,p2,s2));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -279,8 +279,6 @@ private:
|
|||
public:
|
||||
s32 Init(SndBuffer *sb)
|
||||
{
|
||||
if(CurBufferSize<1024) CurBufferSize=1024;
|
||||
|
||||
buff = sb;
|
||||
|
||||
//
|
||||
|
@ -313,7 +311,7 @@ public:
|
|||
memset(&desc, 0, sizeof(DSBUFFERDESC));
|
||||
desc.dwSize = sizeof(DSBUFFERDESC);
|
||||
desc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY;// _CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
|
||||
desc.dwBufferBytes = BufferSizeBytes * MAX_BUFFER_COUNT;
|
||||
desc.dwBufferBytes = BufferSizeBytes * Config_DSound51.NumBuffers;
|
||||
desc.lpwfxFormat = &wfx.Format;
|
||||
|
||||
desc.dwFlags |=DSBCAPS_LOCSOFTWARE;
|
||||
|
@ -327,14 +325,14 @@ public:
|
|||
|
||||
DSBPOSITIONNOTIFY not[MAX_BUFFER_COUNT];
|
||||
|
||||
for(int i=0;i<MAX_BUFFER_COUNT;i++)
|
||||
for(int i=0;i<Config_DSound51.NumBuffers;i++)
|
||||
{
|
||||
buffer_events[i]=CreateEvent(NULL,FALSE,FALSE,NULL);
|
||||
not[i].dwOffset=(wfx.Format.nBlockAlign*10 + BufferSizeBytes*(i+1))%desc.dwBufferBytes;
|
||||
not[i].hEventNotify=buffer_events[i];
|
||||
}
|
||||
|
||||
buffer_notify->SetNotificationPositions(MAX_BUFFER_COUNT,not);
|
||||
buffer_notify->SetNotificationPositions(Config_DSound51.NumBuffers,not);
|
||||
|
||||
LPVOID p1=0,p2=0;
|
||||
DWORD s1=0,s2=0;
|
||||
|
@ -344,13 +342,13 @@ public:
|
|||
memset(p1,0,s1);
|
||||
verifyc(buffer->Unlock(p1,s1,p2,s2));
|
||||
|
||||
LPF_init(&lpf_l,LowpassLFE,SampleRate);
|
||||
LPF_init(&lpf_r,LowpassLFE,SampleRate);
|
||||
LPF_init(&lpf_l,Config_DSound51.LowpassLFE,SampleRate);
|
||||
LPF_init(&lpf_r,Config_DSound51.LowpassLFE,SampleRate);
|
||||
|
||||
//Play the buffer !
|
||||
verifyc(buffer->Play(0,0,DSBPLAY_LOOPING));
|
||||
|
||||
tbuffer = new s32[BufferSize];
|
||||
tbuffer = new s32[SndOutPacketSize];
|
||||
|
||||
// Start Thread
|
||||
dsound_running=true;
|
||||
|
@ -376,7 +374,7 @@ public:
|
|||
//
|
||||
buffer->Stop();
|
||||
|
||||
for(int i=0;i<MAX_BUFFER_COUNT;i++)
|
||||
for(int i=0;i<Config_DSound51.NumBuffers;i++)
|
||||
CloseHandle(buffer_events[i]);
|
||||
|
||||
buffer_notify->Release();
|
||||
|
@ -425,7 +423,7 @@ private:
|
|||
if(wmEvent<vmin) wmEvent=vmin;
|
||||
if(wmEvent>vmax) wmEvent=vmax;
|
||||
SendMessage((HWND)lParam,TBM_SETPOS,TRUE,wmEvent);
|
||||
sprintf(temp,"%d",vmax-wmEvent);
|
||||
sprintf_s(temp,1024,"%d",vmax-wmEvent);
|
||||
SetWindowText(hwndDisplay,temp);
|
||||
break;
|
||||
default:
|
||||
|
@ -445,7 +443,7 @@ private:
|
|||
{
|
||||
case WM_INITDIALOG:
|
||||
|
||||
haveGuid = ! FAILED(GUIDFromString(DSoundDevice,&DevGuid));
|
||||
haveGuid = ! FAILED(GUIDFromString(Config_DSound51.Device,&DevGuid));
|
||||
SendMessage(GetDlgItem(hWnd,IDC_DS_DEVICE),CB_RESETCONTENT,0,0);
|
||||
|
||||
ndevs=0;
|
||||
|
@ -474,6 +472,12 @@ private:
|
|||
INIT_SLIDER(IDC_SLIDER6,0,512,64,16,8);
|
||||
INIT_SLIDER(IDC_SLIDER7,0,512,64,16,8);
|
||||
|
||||
char temp[128];
|
||||
INIT_SLIDER( IDC_BUFFERS_SLIDER, 2, MAX_BUFFER_COUNT, 2, 1, 1 );
|
||||
SendMessage(GetDlgItem(hWnd,IDC_BUFFERS_SLIDER),TBM_SETPOS,TRUE,Config_DSound51.NumBuffers);
|
||||
sprintf_s(temp, 128, "%d (%d ms latency)",Config_DSound51.NumBuffers, 1000 / (96000 / (Config_DSound51.NumBuffers * BufferSize)));
|
||||
SetWindowText(GetDlgItem(hWnd,IDC_LATENCY_LABEL),temp);
|
||||
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
wmId = LOWORD(wParam);
|
||||
|
@ -487,11 +491,11 @@ private:
|
|||
|
||||
if(!devices[i].hasGuid)
|
||||
{
|
||||
DSoundDevice[0]=0; // clear device name to ""
|
||||
Config_DSound51.Device[0]=0; // clear device name to ""
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf_s(DSoundDevice,256,"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
|
||||
sprintf_s(Config_DSound51.Device,256,"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
|
||||
devices[i].guid.Data1,
|
||||
devices[i].guid.Data2,
|
||||
devices[i].guid.Data3,
|
||||
|
@ -504,6 +508,11 @@ private:
|
|||
devices[i].guid.Data4[6],
|
||||
devices[i].guid.Data4[7]
|
||||
);
|
||||
|
||||
Config_DSound51.NumBuffers = (int)SendMessage( GetDlgItem( hWnd, IDC_BUFFERS_SLIDER ), TBM_GETPOS, 0, 0 );
|
||||
|
||||
if( Config_DSound51.NumBuffers < 2 ) Config_DSound51.NumBuffers = 2;
|
||||
if( Config_DSound51.NumBuffers > MAX_BUFFER_COUNT ) Config_DSound51.NumBuffers = MAX_BUFFER_COUNT;
|
||||
}
|
||||
}
|
||||
EndDialog(hWnd,0);
|
||||
|
@ -515,6 +524,30 @@ private:
|
|||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_HSCROLL:
|
||||
wmId = LOWORD(wParam);
|
||||
wmEvent = HIWORD(wParam);
|
||||
switch(wmId) {
|
||||
//case TB_ENDTRACK:
|
||||
//case TB_THUMBPOSITION:
|
||||
case TB_LINEUP:
|
||||
case TB_LINEDOWN:
|
||||
case TB_PAGEUP:
|
||||
case TB_PAGEDOWN:
|
||||
wmEvent=(int)SendMessage((HWND)lParam,TBM_GETPOS,0,0);
|
||||
case TB_THUMBTRACK:
|
||||
if( wmEvent < 2 ) wmEvent = 2;
|
||||
if( wmEvent > MAX_BUFFER_COUNT ) wmEvent = MAX_BUFFER_COUNT;
|
||||
SendMessage((HWND)lParam,TBM_SETPOS,TRUE,wmEvent);
|
||||
sprintf_s(temp,128,"%d (%d ms latency)",wmEvent, 1000 / (96000 / (wmEvent * BufferSize)));
|
||||
SetWindowText(GetDlgItem(hWnd,IDC_LATENCY_LABEL),temp);
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_VSCROLL:
|
||||
HANDLE_SCROLL_MESSAGE(IDC_SLIDER1,0,512,IDC_EDIT1);
|
||||
HANDLE_SCROLL_MESSAGE(IDC_SLIDER2,0,512,IDC_EDIT2);
|
||||
|
@ -542,13 +575,27 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
s32 Test()
|
||||
s32 Test() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Is51Out() { return true; }
|
||||
bool Is51Out() const { return true; }
|
||||
|
||||
int GetEmptySampleCount() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* GetIdent() const
|
||||
{
|
||||
return "dsound51";
|
||||
}
|
||||
|
||||
const char* GetLongName() const
|
||||
{
|
||||
return "DSound 5.1 (Experimental)";
|
||||
}
|
||||
} DS51;
|
||||
|
||||
SndOutModule *DSound51Out=&DS51;
|
||||
SndOutModule *DSound51Out=&DS51;
|
||||
|
|
|
@ -68,12 +68,11 @@ HRESULT GUIDFromString(const char *str, LPGUID guid)
|
|||
class DSound: public SndOutModule
|
||||
{
|
||||
private:
|
||||
# define PI 3.14159265f
|
||||
# define MAX_BUFFER_COUNT 8
|
||||
|
||||
# define BufferSize (CurBufferSize<<1)
|
||||
# define BufferSizeBytes (BufferSize<<1)
|
||||
|
||||
# define TBufferSize (BufferSize*CurBufferCount)
|
||||
static const int PacketsPerBuffer = (1024 / SndOutPacketSize);
|
||||
static const int BufferSize = SndOutPacketSize * PacketsPerBuffer;
|
||||
static const int BufferSizeBytes = BufferSize << 1;
|
||||
|
||||
FILE *voicelog;
|
||||
|
||||
|
@ -83,8 +82,6 @@ private:
|
|||
HANDLE thread;
|
||||
DWORD tid;
|
||||
|
||||
# define MAX_BUFFER_COUNT 5
|
||||
|
||||
IDirectSound8* dsound;
|
||||
IDirectSoundBuffer8* buffer;
|
||||
IDirectSoundNotify8* buffer_notify;
|
||||
|
@ -96,10 +93,7 @@ private:
|
|||
|
||||
SndBuffer *buff;
|
||||
|
||||
s32 *tbuffer;
|
||||
|
||||
# define STRFY(x) #x
|
||||
|
||||
# define verifyc(x) if(Verifyc(x,STRFY(x))) return -1;
|
||||
|
||||
int __forceinline Verifyc(HRESULT hr,const char* fn)
|
||||
|
@ -122,36 +116,21 @@ private:
|
|||
|
||||
while( dsound_running )
|
||||
{
|
||||
u32 rv = WaitForMultipleObjects(MAX_BUFFER_COUNT,buffer_events,FALSE,400);
|
||||
u32 rv = WaitForMultipleObjects(Config_DSoundOut.NumBuffers,buffer_events,FALSE,200);
|
||||
|
||||
LPVOID p1,p2;
|
||||
s16* p1, *oldp1;
|
||||
LPVOID p2;
|
||||
DWORD s1,s2;
|
||||
|
||||
u32 poffset=BufferSizeBytes * rv;
|
||||
|
||||
//DWORD play, write;
|
||||
//buffer->GetCurrentPosition( &play, &write );
|
||||
//ConLog( " * SPU2 > Play: %d Write: %d poffset: %d\n", play, write, poffset );
|
||||
verifyc(buffer->Lock(poffset,BufferSizeBytes,(LPVOID*)&p1,&s1,&p2,&s2,0));
|
||||
oldp1 = p1;
|
||||
|
||||
buff->ReadSamples(tbuffer,BufferSize);
|
||||
|
||||
verifyc(buffer->Lock(poffset,BufferSizeBytes,&p1,&s1,&p2,&s2,0));
|
||||
for(int p=0; p<PacketsPerBuffer; p++, p1+=SndOutPacketSize )
|
||||
buff->ReadSamples( p1 );
|
||||
|
||||
{
|
||||
s16 *t = (s16*)p1;
|
||||
s32 *s = (s32*)tbuffer;
|
||||
for(int j=0;j<BufferSize;j++)
|
||||
{
|
||||
*(t++) = (s16)((*(s++))>>8);
|
||||
}
|
||||
}
|
||||
|
||||
/*if( p2 != NULL )
|
||||
{
|
||||
ConLog( " * SPU2 > DSound Driver Loop-Around Occured. Length: %d", s2 );
|
||||
}*/
|
||||
|
||||
verifyc(buffer->Unlock(p1,s1,p2,s2));
|
||||
verifyc(buffer->Unlock(oldp1,s1,p2,s2));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -166,7 +145,7 @@ public:
|
|||
//
|
||||
GUID cGuid;
|
||||
|
||||
if((strlen(DSoundDevice)>0)&&(!FAILED(GUIDFromString(DSoundDevice,&cGuid))))
|
||||
if((strlen(Config_DSoundOut.Device)>0)&&(!FAILED(GUIDFromString(Config_DSoundOut.Device,&cGuid))))
|
||||
{
|
||||
verifyc(DirectSoundCreate8(&cGuid,&dsound,NULL));
|
||||
}
|
||||
|
@ -187,7 +166,7 @@ public:
|
|||
wfx.nChannels=2;
|
||||
wfx.wBitsPerSample = 16;
|
||||
wfx.nBlockAlign = 2*2;
|
||||
wfx.nAvgBytesPerSec = SampleRate * 2 * 2;
|
||||
wfx.nAvgBytesPerSec = SampleRate * wfx.nBlockAlign;
|
||||
wfx.cbSize=0;
|
||||
|
||||
// Set up DSBUFFERDESC structure.
|
||||
|
@ -195,7 +174,7 @@ public:
|
|||
memset(&desc, 0, sizeof(DSBUFFERDESC));
|
||||
desc.dwSize = sizeof(DSBUFFERDESC);
|
||||
desc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY;// _CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
|
||||
desc.dwBufferBytes = BufferSizeBytes * MAX_BUFFER_COUNT;
|
||||
desc.dwBufferBytes = BufferSizeBytes * Config_DSoundOut.NumBuffers;
|
||||
desc.lpwfxFormat = &wfx;
|
||||
|
||||
desc.dwFlags |=DSBCAPS_LOCSOFTWARE;
|
||||
|
@ -209,14 +188,18 @@ public:
|
|||
|
||||
DSBPOSITIONNOTIFY not[MAX_BUFFER_COUNT];
|
||||
|
||||
for(int i=0;i<MAX_BUFFER_COUNT;i++)
|
||||
for(int i=0;i<Config_DSoundOut.NumBuffers;i++)
|
||||
{
|
||||
// [Air] note: wfx.nBlockAlign modifier was *10 -- seems excessive to me but maybe
|
||||
// it was needed for some quirky driver? Theoretically we want the notification as soon
|
||||
// as possible after the buffer has finished playing.
|
||||
|
||||
buffer_events[i]=CreateEvent(NULL,FALSE,FALSE,NULL);
|
||||
not[i].dwOffset=(wfx.nBlockAlign*10 + BufferSizeBytes*(i+1))%desc.dwBufferBytes;
|
||||
not[i].dwOffset=(wfx.nBlockAlign*2 + BufferSizeBytes*(i+1))%desc.dwBufferBytes;
|
||||
not[i].hEventNotify=buffer_events[i];
|
||||
}
|
||||
|
||||
buffer_notify->SetNotificationPositions(MAX_BUFFER_COUNT,not);
|
||||
buffer_notify->SetNotificationPositions(Config_DSoundOut.NumBuffers,not);
|
||||
|
||||
LPVOID p1=0,p2=0;
|
||||
DWORD s1=0,s2=0;
|
||||
|
@ -229,13 +212,10 @@ public:
|
|||
//Play the buffer !
|
||||
verifyc(buffer->Play(0,0,DSBPLAY_LOOPING));
|
||||
|
||||
tbuffer = new s32[BufferSize];
|
||||
|
||||
// Start Thread
|
||||
dsound_running=true;
|
||||
thread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)RThread,this,0,&tid);
|
||||
thread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)RThread,this,0,&tid);
|
||||
SetThreadPriority(thread,THREAD_PRIORITY_TIME_CRITICAL);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -257,14 +237,12 @@ public:
|
|||
//
|
||||
buffer->Stop();
|
||||
|
||||
for(int i=0;i<MAX_BUFFER_COUNT;i++)
|
||||
for(int i=0;i<Config_DSoundOut.NumBuffers;i++)
|
||||
CloseHandle(buffer_events[i]);
|
||||
|
||||
buffer_notify->Release();
|
||||
buffer->Release();
|
||||
dsound->Release();
|
||||
|
||||
delete tbuffer;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -298,7 +276,7 @@ private:
|
|||
{
|
||||
case WM_INITDIALOG:
|
||||
|
||||
haveGuid = ! FAILED(GUIDFromString(DSoundDevice,&DevGuid));
|
||||
haveGuid = ! FAILED(GUIDFromString(Config_DSoundOut.Device,&DevGuid));
|
||||
SendMessage(GetDlgItem(hWnd,IDC_DS_DEVICE),CB_RESETCONTENT,0,0);
|
||||
|
||||
ndevs=0;
|
||||
|
@ -319,6 +297,12 @@ private:
|
|||
SendMessage(GetDlgItem(hWnd,IDC_DS_DEVICE),CB_SETCURSEL,tSel,0);
|
||||
}
|
||||
|
||||
char temp[128];
|
||||
INIT_SLIDER( IDC_BUFFERS_SLIDER, 2, MAX_BUFFER_COUNT, 2, 1, 1 );
|
||||
SendMessage(GetDlgItem(hWnd,IDC_BUFFERS_SLIDER),TBM_SETPOS,TRUE,Config_DSoundOut.NumBuffers);
|
||||
sprintf_s(temp, 128, "%d (%d ms latency)",Config_DSoundOut.NumBuffers, 1000 / (96000 / (Config_DSoundOut.NumBuffers * BufferSize)));
|
||||
SetWindowText(GetDlgItem(hWnd,IDC_LATENCY_LABEL),temp);
|
||||
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
wmId = LOWORD(wParam);
|
||||
|
@ -332,11 +316,11 @@ private:
|
|||
|
||||
if(!devices[i].hasGuid)
|
||||
{
|
||||
DSoundDevice[0]=0; // clear device name to ""
|
||||
Config_DSoundOut.Device[0] = 0; // clear device name to ""
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf_s(DSoundDevice,256,"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
|
||||
sprintf_s(Config_DSoundOut.Device,256,"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
|
||||
devices[i].guid.Data1,
|
||||
devices[i].guid.Data2,
|
||||
devices[i].guid.Data3,
|
||||
|
@ -350,6 +334,11 @@ private:
|
|||
devices[i].guid.Data4[7]
|
||||
);
|
||||
}
|
||||
|
||||
Config_DSoundOut.NumBuffers = (int)SendMessage( GetDlgItem( hWnd, IDC_BUFFERS_SLIDER ), TBM_GETPOS, 0, 0 );
|
||||
|
||||
if( Config_DSoundOut.NumBuffers < 2 ) Config_DSoundOut.NumBuffers = 2;
|
||||
if( Config_DSoundOut.NumBuffers > MAX_BUFFER_COUNT ) Config_DSoundOut.NumBuffers = MAX_BUFFER_COUNT;
|
||||
}
|
||||
EndDialog(hWnd,0);
|
||||
break;
|
||||
|
@ -360,6 +349,30 @@ private:
|
|||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_HSCROLL:
|
||||
wmId = LOWORD(wParam);
|
||||
wmEvent = HIWORD(wParam);
|
||||
switch(wmId) {
|
||||
//case TB_ENDTRACK:
|
||||
//case TB_THUMBPOSITION:
|
||||
case TB_LINEUP:
|
||||
case TB_LINEDOWN:
|
||||
case TB_PAGEUP:
|
||||
case TB_PAGEDOWN:
|
||||
wmEvent=(int)SendMessage((HWND)lParam,TBM_GETPOS,0,0);
|
||||
case TB_THUMBTRACK:
|
||||
if( wmEvent < 2 ) wmEvent = 2;
|
||||
if( wmEvent > MAX_BUFFER_COUNT ) wmEvent = MAX_BUFFER_COUNT;
|
||||
SendMessage((HWND)lParam,TBM_SETPOS,TRUE,wmEvent);
|
||||
sprintf_s(temp,128,"%d (%d ms latency)",wmEvent, 1000 / (96000 / (wmEvent * BufferSize)));
|
||||
SetWindowText(GetDlgItem(hWnd,IDC_LATENCY_LABEL),temp);
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -378,12 +391,36 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
virtual bool Is51Out() { return false; }
|
||||
virtual bool Is51Out() const { return false; }
|
||||
|
||||
s32 Test()
|
||||
s32 Test() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetEmptySampleCount() const
|
||||
{
|
||||
DWORD play, write;
|
||||
buffer->GetCurrentPosition( &play, &write );
|
||||
int filled = play - write;
|
||||
if( filled < 0 )
|
||||
filled = -filled;
|
||||
else
|
||||
filled = (BufferSizeBytes * Config_DSoundOut.NumBuffers) - filled;
|
||||
|
||||
return filled;
|
||||
}
|
||||
|
||||
const char* GetIdent() const
|
||||
{
|
||||
return "dsound";
|
||||
}
|
||||
|
||||
const char* GetLongName() const
|
||||
{
|
||||
return "DirectSound";
|
||||
}
|
||||
|
||||
} DS;
|
||||
|
||||
SndOutModule *DSoundOut=&DS;
|
||||
|
|
|
@ -232,7 +232,7 @@ static void __forceinline __fastcall GetNextDataBuffered( V_Core& thiscore, V_Vo
|
|||
VoiceStop(core,voice);
|
||||
thiscore.Regs.ENDX|=1<<voice;
|
||||
#ifndef PUBLIC
|
||||
if(MsgVoiceOff) ConLog(" * SPU2: Voice Off by EndPoint: %d \n", voice);
|
||||
if(MsgVoiceOff()) ConLog(" * SPU2: Voice Off by EndPoint: %d \n", voice);
|
||||
DebugCores[core].Voices[voice].lastStopReason = 1;
|
||||
#endif
|
||||
}
|
||||
|
@ -444,7 +444,7 @@ static void __forceinline CalculateADSR( V_Voice& vc )
|
|||
|
||||
if (env.Phase==6) {
|
||||
#ifndef PUBLIC
|
||||
if(MsgVoiceOff) ConLog(" * SPU2: Voice Off by ADSR: %d \n", voice);
|
||||
if(MsgVoiceOff()) ConLog(" * SPU2: Voice Off by ADSR: %d \n", voice);
|
||||
DebugCores[core].Voices[voice].lastStopReason = 2;
|
||||
#endif
|
||||
VoiceStop(core,voice);
|
||||
|
@ -665,7 +665,7 @@ void __fastcall ReadInput(V_Core& thiscore, s32& PDataL,s32& PDataR)
|
|||
#ifndef PUBLIC
|
||||
if(thiscore.InputDataLeft>0)
|
||||
{
|
||||
if(MsgAutoDMA) ConLog("WARNING: adma buffer didn't finish with a whole block!!\n");
|
||||
if(MsgAutoDMA()) ConLog("WARNING: adma buffer didn't finish with a whole block!!\n");
|
||||
}
|
||||
#endif
|
||||
thiscore.InputDataLeft=0;
|
||||
|
@ -705,7 +705,7 @@ void __fastcall ReadInput(V_Core& thiscore, s32& PDataL,s32& PDataR)
|
|||
#ifndef PUBLIC
|
||||
if(thiscore.InputDataLeft>0)
|
||||
{
|
||||
if(MsgAutoDMA) ConLog("WARNING: adma buffer didn't finish with a whole block!!\n");
|
||||
if(MsgAutoDMA()) ConLog("WARNING: adma buffer didn't finish with a whole block!!\n");
|
||||
}
|
||||
#endif
|
||||
thiscore.InputDataLeft=0;
|
||||
|
@ -759,7 +759,7 @@ void __fastcall ReadInput(V_Core& thiscore, s32& PDataL,s32& PDataR)
|
|||
#ifndef PUBLIC
|
||||
if(thiscore.InputDataLeft>0)
|
||||
{
|
||||
if(MsgAutoDMA) ConLog("WARNING: adma buffer didn't finish with a whole block!!\n");
|
||||
if(MsgAutoDMA()) ConLog("WARNING: adma buffer didn't finish with a whole block!!\n");
|
||||
}
|
||||
#endif
|
||||
thiscore.InputDataLeft=0;
|
||||
|
@ -1062,14 +1062,11 @@ static void __forceinline MixVoice( V_Core& thiscore, V_Voice& vc, s32& VValL, s
|
|||
static void __fastcall MixCore(s32& OutL, s32& OutR, s32 ExtL, s32 ExtR)
|
||||
{
|
||||
s32 RVL,RVR;
|
||||
s32 TDL=0,TDR=0;
|
||||
s32 SDL=0,SDR=0;
|
||||
s32 SWL=0,SWR=0;
|
||||
|
||||
V_Core& thiscore( Cores[core] );
|
||||
|
||||
SDL=SDR=SWL=SWR=(s32)0;
|
||||
|
||||
for (voice=0;voice<24;voice++)
|
||||
{
|
||||
s32 VValL,VValR;
|
||||
|
@ -1089,6 +1086,8 @@ static void __fastcall MixCore(s32& OutL, s32& OutR, s32 ExtL, s32 ExtR)
|
|||
spu2M_WriteFast( 0x1400 + (core<<12) + OutPos, (s16)(SWL>>16) );
|
||||
spu2M_WriteFast( 0x1600 + (core<<12) + OutPos, (s16)(SWR>>16) );
|
||||
|
||||
s32 TDL,TDR;
|
||||
|
||||
// Mix in the Input data
|
||||
TDL = OutL * thiscore.InpDryL;
|
||||
TDR = OutR * thiscore.InpDryR;
|
||||
|
@ -1200,13 +1199,11 @@ void __fastcall Mix()
|
|||
Peak1 = max(Peak1,max(OutL,OutR));
|
||||
#endif
|
||||
|
||||
// [Air] [TODO] : Replace this with MulShr32.
|
||||
// I haven't done it yet because it would require making the
|
||||
// VolumeDivisor a constant .. which it should be anyway. The presence
|
||||
// of VolumeMultiplier more or less negates the need for a variable divisor.
|
||||
|
||||
ExtL=MulDiv(OutL,VolumeMultiplier,VolumeDivisor<<6);
|
||||
ExtR=MulDiv(OutR,VolumeMultiplier,VolumeDivisor<<6);
|
||||
// [Air] : Removed MulDiv here in favor of a more direct approach
|
||||
// within the SndOut driver (which ends up having to apply its own
|
||||
// master volume divisors anyway).
|
||||
//ExtL=MulDiv(OutL,VolumeMultiplier,1<<6);
|
||||
//ExtR=MulDiv(OutR,VolumeMultiplier,1<<6);
|
||||
|
||||
// Update spdif (called each sample)
|
||||
if(PlayMode&4)
|
||||
|
@ -1215,17 +1212,17 @@ void __fastcall Mix()
|
|||
}
|
||||
|
||||
// AddToBuffer
|
||||
SndWrite(ExtL,ExtR);
|
||||
SndWrite(OutL, OutR); //ExtL,ExtR);
|
||||
OutPos++;
|
||||
if (OutPos>=0x200) OutPos=0;
|
||||
|
||||
#ifndef PUBLIC
|
||||
// [TODO]: Create an INI option to enable/disable this particular log.
|
||||
p_cachestat_counter++;
|
||||
if(p_cachestat_counter > (48000*6) )
|
||||
if(p_cachestat_counter > (48000*10) )
|
||||
{
|
||||
p_cachestat_counter = 0;
|
||||
ConLog( " * SPU2 > CacheStatistics > 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 );
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#define IDC_SRATE 1012
|
||||
#define IDC_OUTPUT 1013
|
||||
#define IDC_BUFFER 1014
|
||||
#define IDC_BUFFERS_SLIDER 1014
|
||||
#define IDC_BSIZE 1016
|
||||
#define IDC_BCOUNT 1018
|
||||
#define IDC_TEXT 1019
|
||||
|
@ -37,16 +38,26 @@
|
|||
#define IDC_SLIDER2 1034
|
||||
#define IDC_SLIDER3 1035
|
||||
#define IDC_EDIT1 1036
|
||||
#define IDC_BUTTON1 1037
|
||||
#define IDC_SHOW_DEBUG 1037
|
||||
#define IDC_DBG_OVERRUNS 1038
|
||||
#define IDC_SLIDER4 1039
|
||||
#define IDC_DBG_CACHE 1039
|
||||
#define IDC_SLIDER5 1040
|
||||
#define IDC_DEBUG_GROUP 1040
|
||||
#define IDC_SLIDER6 1041
|
||||
#define IDC_LATENCY_SLIDER 1041
|
||||
#define IDC_SLIDER7 1042
|
||||
#define IDC_LATENCY_LABEL 1042
|
||||
#define IDC_EDIT2 1043
|
||||
#define IDC_EDIT3 1044
|
||||
#define IDC_SPEEDLIMIT_RUNTIME_TOGGLE 1044
|
||||
#define IDC_EDIT4 1045
|
||||
#define IDC_EDIT5 1046
|
||||
#define IDC_EDIT6 1047
|
||||
#define IDC_VOLBOOST 1047
|
||||
#define IDC_EDIT7 1048
|
||||
#define IDC_LATENCY_LABEL2 1049
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
|
@ -54,7 +65,7 @@
|
|||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 110
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1037
|
||||
#define _APS_NEXT_CONTROL_VALUE 1048
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -19,13 +19,30 @@
|
|||
#include "SoundTouch/SoundTouch.h"
|
||||
#include "SoundTouch/WavFile.h"
|
||||
|
||||
static int ts_stats_stretchblocks = 0;
|
||||
static int ts_stats_normalblocks = 0;
|
||||
static int ts_stats_logcounter = 0;
|
||||
|
||||
class NullOutModule: public SndOutModule
|
||||
{
|
||||
public:
|
||||
s32 Init(SndBuffer *) { return 0; }
|
||||
void Close() { }
|
||||
s32 Test() { return 0; }
|
||||
s32 Test() const { return 0; }
|
||||
void Configure(HWND parent) { }
|
||||
bool Is51Out() { return false; }
|
||||
bool Is51Out() const { return false; }
|
||||
int GetEmptySampleCount() const { return 0; }
|
||||
|
||||
const char* GetIdent() const
|
||||
{
|
||||
return "nullout";
|
||||
}
|
||||
|
||||
const char* GetLongName() const
|
||||
{
|
||||
return "No Sound (Emulate SPU2 only)";
|
||||
}
|
||||
|
||||
} NullOut;
|
||||
|
||||
SndOutModule* mods[]=
|
||||
|
@ -36,9 +53,39 @@ SndOutModule* mods[]=
|
|||
DSound51Out,
|
||||
ASIOOut,
|
||||
XAudio2Out,
|
||||
NULL // signals the end of our list
|
||||
};
|
||||
|
||||
const u32 mods_count=sizeof(mods)/sizeof(SndOutModule*);
|
||||
int FindOutputModuleById( const char* omodid )
|
||||
{
|
||||
int modcnt = 0;
|
||||
while( mods[modcnt] != NULL )
|
||||
{
|
||||
if( strcmp( mods[modcnt]->GetIdent(), omodid ) == 0 )
|
||||
break;
|
||||
++modcnt;
|
||||
}
|
||||
return modcnt;
|
||||
}
|
||||
|
||||
|
||||
// Overall master volume shift.
|
||||
// Converts the mixer's 32 bit value into a 16 bit value.
|
||||
int SndOutVolumeShift = SndOutVolumeShiftBase + 1;
|
||||
|
||||
static __forceinline s16 SndScaleVol( s32 inval )
|
||||
{
|
||||
return inval >> SndOutVolumeShift;
|
||||
}
|
||||
|
||||
|
||||
// records last buffer status (fill %, range -100 to 100, with 0 being 50% full)
|
||||
double lastPct;
|
||||
|
||||
float cTempo=1;
|
||||
|
||||
soundtouch::SoundTouch* pSoundTouch=NULL;
|
||||
|
||||
|
||||
//usefull when timestretch isn't available
|
||||
//#define DYNAMIC_BUFFER_LIMITING
|
||||
|
@ -52,45 +99,42 @@ private:
|
|||
s32 wpos;
|
||||
s32 data;
|
||||
|
||||
#ifdef DYNAMIC_BUFFER_LIMITING
|
||||
s32 buffer_limit;
|
||||
#endif
|
||||
// data prediction amount, used to "commit" data that hasn't
|
||||
// finished timestretch processing.
|
||||
s32 predictData;
|
||||
|
||||
bool pr;
|
||||
bool pw;
|
||||
|
||||
int overflows;
|
||||
int underflows;
|
||||
int writewaits;
|
||||
|
||||
|
||||
|
||||
bool isWaiting;
|
||||
bool underrun_freeze;
|
||||
HANDLE hSyncEvent;
|
||||
CRITICAL_SECTION cs;
|
||||
|
||||
u32 datawritten;
|
||||
u32 dataread;
|
||||
protected:
|
||||
int GetAlignedBufferSize( int comp )
|
||||
{
|
||||
return (comp + SndOutPacketSize-1) & ~(SndOutPacketSize-1);
|
||||
}
|
||||
|
||||
public:
|
||||
SndBufferImpl(s32 _size)
|
||||
SndBufferImpl( double latencyMS )
|
||||
{
|
||||
rpos=0;
|
||||
wpos=0;
|
||||
data=0;
|
||||
size=(_size+1)&(~1);
|
||||
size=GetAlignedBufferSize( (int)(latencyMS * SampleRate / 500.0 ) );
|
||||
buffer = new s32[size];
|
||||
pr=false;
|
||||
pw=false;
|
||||
isWaiting=false;
|
||||
underrun_freeze = false;
|
||||
predictData = 0;
|
||||
|
||||
lastPct = 0.0;
|
||||
|
||||
#ifdef DYNAMIC_BUFFER_LIMITING
|
||||
overflows=0;
|
||||
underflows=0;
|
||||
writewaits=0;
|
||||
buffer_limit=size;
|
||||
#endif
|
||||
datawritten=0;
|
||||
dataread=0;
|
||||
InitializeCriticalSection(&cs);
|
||||
hSyncEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
|
||||
}
|
||||
|
@ -98,7 +142,7 @@ public:
|
|||
virtual ~SndBufferImpl()
|
||||
{
|
||||
pw=false;
|
||||
if(isWaiting) PulseEvent(hSyncEvent);
|
||||
PulseEvent(hSyncEvent);
|
||||
Sleep(10);
|
||||
EnterCriticalSection(&cs);
|
||||
LeaveCriticalSection(&cs);
|
||||
|
@ -107,42 +151,24 @@ public:
|
|||
delete buffer;
|
||||
}
|
||||
|
||||
virtual void WriteSamples(s32 *bData, s32 nSamples)
|
||||
virtual void WriteSamples(s32 *bData, int nSamples)
|
||||
{
|
||||
EnterCriticalSection(&cs);
|
||||
datawritten+=nSamples;
|
||||
|
||||
#ifdef DYNAMIC_BUFFER_LIMITING
|
||||
int free = buffer_limit-data;
|
||||
#else
|
||||
int free = size-data;
|
||||
#endif
|
||||
predictData = 0;
|
||||
|
||||
if(pw)
|
||||
jASSUME( data <= size );
|
||||
|
||||
if( pw && ( free < nSamples ) )
|
||||
{
|
||||
#ifdef DYNAMIC_BUFFER_LIMITING
|
||||
if(free<nSamples)
|
||||
writewaits++;
|
||||
#endif
|
||||
while((free<nSamples)&&(pw))
|
||||
{
|
||||
//isWaiting=true;
|
||||
LeaveCriticalSection(&cs);
|
||||
//ConLog( " * SPU2 : Waiting for object... " );
|
||||
WaitForSingleObject(hSyncEvent,1000);
|
||||
//ConLog( " Signaled! \n" );
|
||||
EnterCriticalSection(&cs);
|
||||
#ifdef DYNAMIC_BUFFER_LIMITING
|
||||
free = buffer_limit-data;
|
||||
#else
|
||||
free = size-data;
|
||||
#endif
|
||||
//isWaiting=false;
|
||||
}
|
||||
// Wait for a ReadSamples to pull some stuff out of the buffer.
|
||||
// One SyncEvent will do the trick.
|
||||
ResetEvent( hSyncEvent );
|
||||
LeaveCriticalSection(&cs);
|
||||
WaitForSingleObject(hSyncEvent,20);
|
||||
EnterCriticalSection(&cs);
|
||||
}
|
||||
|
||||
// either pw=false or free>nSamples
|
||||
|
||||
// Problem:
|
||||
// If the SPU2 gets out of sync with the SndOut device, the writepos of the
|
||||
// circular buffer will overtake the readpos, leading to a prolonged period
|
||||
|
@ -154,64 +180,106 @@ public:
|
|||
// The older portion of the buffer is discarded rather than incoming data,
|
||||
// so that the overall audio synchronization is better.
|
||||
|
||||
#ifndef DYNAMIC_BUFFER_LIMITING
|
||||
|
||||
if((data+nSamples > size) && !timeStretchEnabled)
|
||||
if( free < nSamples )
|
||||
{
|
||||
// Buffer overrun!
|
||||
// Dump samples from the read portion of the buffer instead of dropping
|
||||
// the newly written stuff.
|
||||
|
||||
// Toss half the buffer plus whatever's being written anew:
|
||||
s32 comp = (size / 2) + nSamples;
|
||||
comp = (comp + 128) & ~127; // probably not important but it makes the log look nicer. :P
|
||||
if( comp > size ) comp = size;
|
||||
s32 comp = GetAlignedBufferSize( (size + nSamples ) / 2 );
|
||||
if( comp > (size-SndOutPacketSize) ) comp = size-SndOutPacketSize;
|
||||
|
||||
if( timeStretchEnabled )
|
||||
{
|
||||
// If we overran it means the timestretcher failed. We need to speed
|
||||
// up audio playback.
|
||||
|
||||
cTempo += cTempo * 1.5f;
|
||||
if( cTempo > 5.0f ) cTempo = 5.0f;
|
||||
pSoundTouch->setTempo( cTempo );
|
||||
}
|
||||
|
||||
data-=comp;
|
||||
rpos=(rpos+comp)%size;
|
||||
timeStretchEnabled = true;
|
||||
ConLog(" * SPU2 > Overrun Compensation (%d samples tossed)\n", size );
|
||||
ConLog(" * SPU2 Timestretch: ENABLED\n");
|
||||
if( MsgOverruns() )
|
||||
ConLog(" * SPU2 > Overrun Compensation (%d packets tossed)\n", comp / SndOutPacketSize );
|
||||
lastPct = 0.0; // normalize the timestretcher
|
||||
}
|
||||
|
||||
while(data<size && nSamples>0)
|
||||
// copy in two phases, since there's a chance the packet
|
||||
// wraps around the buffer (it'd be nice to deal in packets only, but
|
||||
// the timestretcher and DSP options require flexibility).
|
||||
|
||||
const int endPos = wpos + nSamples;
|
||||
const int secondCopyLen = endPos - size;
|
||||
s32* wposbuffer = &buffer[wpos];
|
||||
|
||||
data += nSamples;
|
||||
if( secondCopyLen > 0 )
|
||||
{
|
||||
buffer[wpos] = *(bData++);
|
||||
wpos=(wpos+1)%size;
|
||||
data++;
|
||||
nSamples--;
|
||||
nSamples -= secondCopyLen;
|
||||
memcpy( buffer, &bData[nSamples], secondCopyLen * sizeof( *bData ) );
|
||||
wpos = secondCopyLen;
|
||||
}
|
||||
else
|
||||
wpos += nSamples;
|
||||
|
||||
#elif defined( DYNAMIC_BUFFER_LIMITING )
|
||||
|
||||
while(nSamples>0)
|
||||
{
|
||||
buffer[wpos] = *(bData++);
|
||||
wpos=(wpos+1)%size;
|
||||
data++;
|
||||
nSamples--;
|
||||
}
|
||||
|
||||
if(data>size)
|
||||
{
|
||||
do {
|
||||
data-=size;
|
||||
}
|
||||
while(data>size);
|
||||
overflows++;
|
||||
}
|
||||
#endif
|
||||
|
||||
memcpy( wposbuffer, bData, nSamples * sizeof( *bData ) );
|
||||
|
||||
LeaveCriticalSection(&cs);
|
||||
}
|
||||
|
||||
virtual void ReadSamples (s32 *bData, s32 nSamples)
|
||||
protected:
|
||||
// Returns TRUE if there is data to be output, or false if no data
|
||||
// is available to be copied.
|
||||
bool CheckUnderrunStatus( int& nSamples, int& quietSampleCount )
|
||||
{
|
||||
static bool underrun_freeze = false;
|
||||
quietSampleCount = 0;
|
||||
if( data < nSamples )
|
||||
{
|
||||
nSamples = data;
|
||||
quietSampleCount = SndOutPacketSize - data;
|
||||
underrun_freeze = true;
|
||||
|
||||
if( timeStretchEnabled )
|
||||
{
|
||||
// timeStretcher failed it's job. We need to slow down the audio some.
|
||||
|
||||
cTempo -= (cTempo * 0.25f);
|
||||
if( cTempo < 0.2f ) cTempo = 0.2f;
|
||||
pSoundTouch->setTempo( cTempo );
|
||||
}
|
||||
|
||||
return nSamples != 0;
|
||||
}
|
||||
else if( underrun_freeze )
|
||||
{
|
||||
int toFill = (int)(size * ( timeStretchEnabled ? 0.45 : 0.70 ) );
|
||||
toFill = GetAlignedBufferSize( toFill );
|
||||
|
||||
// toFill is now aligned to a SndOutPacket
|
||||
|
||||
if( data < toFill )
|
||||
{
|
||||
quietSampleCount = nSamples;
|
||||
return false;
|
||||
}
|
||||
|
||||
underrun_freeze = false;
|
||||
if( MsgOverruns() )
|
||||
ConLog(" * SPU2 > Underrun compensation (%d packets buffered)\n", toFill / SndOutPacketSize );
|
||||
lastPct = 0.0; // normalize timestretcher
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
void ReadSamples( s16* bData )
|
||||
{
|
||||
int nSamples = SndOutPacketSize;
|
||||
|
||||
EnterCriticalSection(&cs);
|
||||
dataread+=nSamples;
|
||||
|
||||
// Problem:
|
||||
// If the SPU2 gets even the least bit out of sync with the SndOut device,
|
||||
|
@ -226,269 +294,219 @@ public:
|
|||
// This will cause one brief hiccup that can never exceed the user's
|
||||
// set buffer length in duration.
|
||||
|
||||
#ifndef DYNAMIC_BUFFER_LIMITING
|
||||
if( underrun_freeze && !timeStretchEnabled)
|
||||
int quietSamples;
|
||||
if( CheckUnderrunStatus( nSamples, quietSamples ) )
|
||||
{
|
||||
// Let's fill up 80% of our buffer.
|
||||
// (I just picked 80% arbitrarily.. there might be a better value)
|
||||
jASSUME( nSamples <= SndOutPacketSize );
|
||||
|
||||
int toFill = (int)(size * 0.80);
|
||||
toFill = (toFill + 128) & ~127; // probably not important but it makes the log look nicer. :P
|
||||
// [Air] [TODO]: This loop is probably a candidiate for SSE2 optimization.
|
||||
|
||||
if( data < toFill )
|
||||
const int endPos = rpos + nSamples;
|
||||
const int secondCopyLen = endPos - size;
|
||||
const s32* rposbuffer = &buffer[rpos];
|
||||
|
||||
data -= nSamples;
|
||||
|
||||
if( secondCopyLen > 0 )
|
||||
{
|
||||
while( nSamples>0 )
|
||||
{
|
||||
*(bData++) = 0;
|
||||
nSamples--;
|
||||
}
|
||||
LeaveCriticalSection(&cs);
|
||||
return;
|
||||
nSamples -= secondCopyLen;
|
||||
for( int i=0; i<secondCopyLen; i++ )
|
||||
bData[nSamples+i] = SndScaleVol( buffer[i] );
|
||||
rpos = secondCopyLen;
|
||||
}
|
||||
else
|
||||
rpos += nSamples;
|
||||
|
||||
underrun_freeze = false;
|
||||
timeStretchEnabled = true;
|
||||
ConLog(" * SPU2 > Underrun compensation (%d samples buffered)\n", toFill );
|
||||
ConLog(" * SPU2 Timestretch: ENABLED\n");
|
||||
}
|
||||
else underrun_freeze = false;
|
||||
|
||||
while(data>0 && nSamples>0)
|
||||
{
|
||||
*(bData++) = buffer[rpos];
|
||||
rpos=(rpos+1)%size;
|
||||
data--;
|
||||
nSamples--;
|
||||
for( int i=0; i<nSamples; i++ )
|
||||
bData[i] = SndScaleVol( rposbuffer[i] );
|
||||
}
|
||||
|
||||
while( nSamples>0 )
|
||||
{
|
||||
// buffer underrun code:
|
||||
// the contents of this loop only get run if data reached zero
|
||||
// before nSamples.
|
||||
// Let's just dull out some silence, because that's usually the least
|
||||
// painful way of dealing with underruns.
|
||||
|
||||
*(bData++) = 0;
|
||||
nSamples--;
|
||||
}
|
||||
|
||||
if( data == 0 && !pw )
|
||||
{
|
||||
underrun_freeze = true;
|
||||
}
|
||||
|
||||
#elif defined( DYNAMIC_BUFFER_LIMITING )
|
||||
|
||||
while(nSamples>0)
|
||||
{
|
||||
*(bData++) = buffer[rpos];
|
||||
rpos=(rpos+1)%size;
|
||||
data--;
|
||||
nSamples--;
|
||||
}
|
||||
|
||||
if(data<0)
|
||||
{
|
||||
do
|
||||
{
|
||||
data+=buffer_limit;
|
||||
}
|
||||
while(data<0);
|
||||
underflows++;
|
||||
}
|
||||
#else
|
||||
bool uflow = false;
|
||||
while(data<0)
|
||||
{
|
||||
data+=size;
|
||||
uflow = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
PulseEvent(hSyncEvent);
|
||||
|
||||
#ifdef DYNAMIC_BUFFER_LIMITING
|
||||
|
||||
// will never have BOTH overflows and write waits ;)
|
||||
while((overflows>0)&&(underflows>0))
|
||||
{ overflows--; underflows--; }
|
||||
while((writewaits>0)&&(underflows>0))
|
||||
{ writewaits--; underflows--; }
|
||||
int t=buffer_limit;
|
||||
if(underflows>0)
|
||||
{
|
||||
if(buffer_limit<size)
|
||||
{
|
||||
buffer_limit=min(size,buffer_limit*2);
|
||||
underflows=0;
|
||||
}
|
||||
if(underflows>3) underflows=3;
|
||||
}
|
||||
if(writewaits>0)
|
||||
{
|
||||
if(buffer_limit>(3*CurBufferSize))
|
||||
{
|
||||
buffer_limit=max(3*CurBufferSize,buffer_limit*3/4);
|
||||
writewaits=0;
|
||||
}
|
||||
if(writewaits>10) writewaits=10;
|
||||
}
|
||||
if(overflows>0)
|
||||
{
|
||||
if(buffer_limit>(3*CurBufferSize))
|
||||
{
|
||||
buffer_limit=max(3*CurBufferSize,buffer_limit*3/4);
|
||||
overflows=0;
|
||||
}
|
||||
if(overflows>3) overflows=3;
|
||||
}
|
||||
|
||||
//printf(" ** SPU2 Dynamic limiter update: Buffer limit set to %d\n",buffer_limit);
|
||||
#endif
|
||||
|
||||
// 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(*bData) );
|
||||
SetEvent( hSyncEvent );
|
||||
LeaveCriticalSection(&cs);
|
||||
}
|
||||
|
||||
void ReadSamples( s32* bData )
|
||||
{
|
||||
int nSamples = SndOutPacketSize;
|
||||
|
||||
EnterCriticalSection(&cs);
|
||||
|
||||
// Problem:
|
||||
// If the SPU2 gets even the least bit out of sync with the SndOut device,
|
||||
// the readpos of the circular buffer will overtake the writepos,
|
||||
// leading to a prolonged period of hopscotching read/write accesses (ie,
|
||||
// lots of staticy crap sound for several seconds).
|
||||
//
|
||||
// Fix:
|
||||
// If the read position overtakes the write position, abort the
|
||||
// transfer immediately and force the SndOut driver to wait until
|
||||
// the read buffer has filled up again before proceeding.
|
||||
// This will cause one brief hiccup that can never exceed the user's
|
||||
// set buffer length in duration.
|
||||
|
||||
int quietSamples;
|
||||
if( CheckUnderrunStatus( nSamples, quietSamples ) )
|
||||
{
|
||||
// nSamples is garaunteed non-zero if CheckUnderrunStatus
|
||||
// returned true.
|
||||
|
||||
const int endPos = rpos + nSamples;
|
||||
const int secondCopyLen = endPos - size;
|
||||
const int oldrpos = rpos;
|
||||
|
||||
data -= nSamples;
|
||||
|
||||
if( secondCopyLen > 0 )
|
||||
{
|
||||
nSamples -= secondCopyLen;
|
||||
memcpy( &bData[nSamples], buffer, secondCopyLen * sizeof( *bData ) );
|
||||
rpos = secondCopyLen;
|
||||
}
|
||||
else
|
||||
rpos += nSamples;
|
||||
|
||||
memcpy( bData, &buffer[oldrpos], nSamples * sizeof( *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(*bData) );
|
||||
PulseEvent(hSyncEvent);
|
||||
LeaveCriticalSection(&cs);
|
||||
}
|
||||
|
||||
void PredictDataWrite( int samples )
|
||||
{
|
||||
predictData += samples;
|
||||
}
|
||||
|
||||
virtual void PauseOnWrite(bool doPause) { pw = doPause; }
|
||||
|
||||
virtual s32 GetBufferUsage()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
virtual s32 GetBufferSize()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
bool GetStats(u32 &w, u32 &r, bool reset)
|
||||
// Calculate the buffer status percentage.
|
||||
// Returns range from -1.0 to 1.0
|
||||
// 1.0 = buffer overflow!
|
||||
// 0.0 = buffer nominal (50% full)
|
||||
// -1.0 = buffer underflow!
|
||||
double GetStatusPct()
|
||||
{
|
||||
EnterCriticalSection(&cs);
|
||||
w = datawritten;
|
||||
r = dataread;
|
||||
if(reset) { datawritten=dataread=0; }
|
||||
|
||||
// Get the buffer status of the output driver too, so that we can
|
||||
// obtain a more accurate overall buffer status.
|
||||
|
||||
int drvempty = mods[OutputModule]->GetEmptySampleCount() / 2;
|
||||
|
||||
double result = (data + predictData - drvempty) - (size/2);
|
||||
result /= (size/2);
|
||||
LeaveCriticalSection(&cs);
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
} *sndBuffer;
|
||||
|
||||
};
|
||||
|
||||
SndBufferImpl *sndBuffer;
|
||||
|
||||
s32* sndTempBuffer;
|
||||
s32 sndTempProgress;
|
||||
s32 sndTempSize;
|
||||
s16* sndTempBuffer16;
|
||||
float* sndTempBufferFloat;
|
||||
|
||||
s32 buffersize=0;
|
||||
|
||||
soundtouch::SoundTouch* pSoundTouch=NULL;
|
||||
|
||||
u32 inputSamples=0;
|
||||
|
||||
u32 oldWritten=0;
|
||||
u32 oldRead=0;
|
||||
u32 oldInput=0;
|
||||
|
||||
float valAccum1 = 1.0f;
|
||||
float valAccum2 = 1.0f;
|
||||
u32 numAccum = 1;
|
||||
|
||||
const u32 numUpdates = 160;
|
||||
|
||||
float lastTempo=1;
|
||||
float cTempo=1;
|
||||
//float* sndTempBufferFloat;
|
||||
|
||||
void ResetTempoChange()
|
||||
{
|
||||
u32 cWritten;
|
||||
u32 cRead;
|
||||
u32 cInput = inputSamples;
|
||||
|
||||
sndBuffer->GetStats(cWritten,cRead,false);
|
||||
|
||||
oldWritten=cWritten;
|
||||
oldRead=cRead;
|
||||
oldInput=cInput;
|
||||
|
||||
pSoundTouch->setTempo(1);
|
||||
}
|
||||
|
||||
void UpdateTempoChange()
|
||||
{
|
||||
u32 cWritten;
|
||||
u32 cRead;
|
||||
u32 cInput = inputSamples;
|
||||
static short int runs =0;
|
||||
double statusPct = sndBuffer->GetStatusPct();
|
||||
double pctChange = statusPct - lastPct;
|
||||
|
||||
s32 bufferUsage = sndBuffer->GetBufferUsage();
|
||||
s32 bufferSize = sndBuffer->GetBufferSize();
|
||||
//Emergency stretch to compensate for FPS fluctuations and keep the buffers happy
|
||||
bool a=(bufferUsage < CurBufferSize * 4);
|
||||
bool b=(bufferUsage >= (bufferSize - CurBufferSize * 4));
|
||||
double tempoChange;
|
||||
|
||||
if(a!=b)
|
||||
// We have two factors.
|
||||
// * Distance from nominal buffer status (50% full)
|
||||
// * The change from previous update to this update.
|
||||
|
||||
// The most important factor is the change from update to update.
|
||||
// But the synchronization between emulator, mixer, and audio driver
|
||||
// is rarely consistent so drifting away from nominal buffer status (50%)
|
||||
// is inevitable. So we need to use the nominal buffer status to
|
||||
// help temper things.
|
||||
|
||||
double relation = statusPct / pctChange;
|
||||
|
||||
if( relation < 0.0 )
|
||||
{
|
||||
if (bufferUsage < CurBufferSize * 2) { cTempo*=0.80f; }
|
||||
else if(bufferUsage < CurBufferSize * 3) { cTempo*=0.90f; }
|
||||
else if(bufferUsage < CurBufferSize * 4) { cTempo*=0.96f; }
|
||||
|
||||
if (bufferUsage > (bufferSize - CurBufferSize * 2)) { cTempo*=1.20f; }
|
||||
else if(bufferUsage > (bufferSize - CurBufferSize * 3)) { cTempo*=1.10f; }
|
||||
else if(bufferUsage >= (bufferSize - CurBufferSize * 4)) { cTempo*=1.04f; }
|
||||
|
||||
if (cTempo != lastTempo) {
|
||||
pSoundTouch->setTempo(cTempo);
|
||||
}
|
||||
// The buffer is already shrinking toward
|
||||
// nominal value, so let's not do "too much"
|
||||
// We only want to adjust if the shrink rate seems too fast
|
||||
// or slow compared to our distance from nominal (50%).
|
||||
|
||||
tempoChange = ( pow( statusPct, 3.0 ) * 0.33 ) + pctChange * 0.23;
|
||||
}
|
||||
else
|
||||
{
|
||||
cTempo = cTempo * 0.9f + lastTempo * 0.1f;
|
||||
tempoChange = pctChange * 0.30;
|
||||
|
||||
// Sudden spikes in framerate can cause the nominal buffer status
|
||||
// to go critical, in which case we have to enact an emergency
|
||||
// stretch. The following cubic formula does that.
|
||||
|
||||
// Constants:
|
||||
// Weight - weights the statusPct's "emergency" consideration.
|
||||
// higher values here will make the buffer perform more drastic
|
||||
// compensations.
|
||||
|
||||
// Range - scales the adjustment to the given range (more or less).
|
||||
// The actual range is dependent on the weight used, so if you increase
|
||||
// Weight you'll usually want to decrease Range somewhat to compensate.
|
||||
|
||||
const double weight = 1.55;
|
||||
const double range = 0.12;
|
||||
|
||||
double nominalAdjust = (statusPct * 0.10) + ( pow( statusPct*weight, 3.0 ) * range);
|
||||
|
||||
tempoChange = tempoChange + nominalAdjust;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
sndBuffer->GetStats(cWritten,cRead,false);
|
||||
|
||||
valAccum1 += (cRead-oldRead);
|
||||
valAccum2 += (cInput-oldInput);
|
||||
numAccum++;
|
||||
|
||||
oldRead = cRead;
|
||||
oldInput = cInput;
|
||||
// Threshold - Ignore small values between -.005 and +.005.
|
||||
// We don't need to "pollute" our timestretcher with pointless
|
||||
// tempo change overhead.
|
||||
if( abs( tempoChange ) < 0.005 ) return;
|
||||
|
||||
//normal stretch, scales sound to game speed
|
||||
if(numAccum >= numUpdates)
|
||||
lastPct = statusPct;
|
||||
|
||||
// Apply tempoChange as a scale of cTempo. That way the effect is proportional
|
||||
// to the current tempo. (otherwise tempos would change too slowly/quickly at the extremes)
|
||||
cTempo += (float)( tempoChange * cTempo );
|
||||
|
||||
if( statusPct < -0.20 || statusPct > 0.20 || cTempo < 0.980 || cTempo > 1.020 )
|
||||
{
|
||||
float valAccum = 1.0f;
|
||||
|
||||
valAccum = valAccum2 / valAccum1;
|
||||
if( cTempo < 0.20f ) cTempo = 0.20f;
|
||||
else if( cTempo > 5.0f ) cTempo = 5.0f;
|
||||
pSoundTouch->setTempo( cTempo );
|
||||
ts_stats_stretchblocks++;
|
||||
|
||||
if((valAccum < 1.04f) && (valAccum > 0.96f) /*&& (valAccum != 1)*/)
|
||||
{
|
||||
valAccum = 1.0f;
|
||||
}
|
||||
|
||||
if (valAccum != lastTempo) //only update soundtouch object when needed
|
||||
pSoundTouch->setTempo(valAccum);
|
||||
|
||||
lastTempo = valAccum;
|
||||
cTempo = valAccum;
|
||||
|
||||
if (lastTempo == 1) {
|
||||
runs++;
|
||||
if (runs == 5) {
|
||||
timeStretchEnabled = false;
|
||||
ConLog( " * SPU2 Timestretch: DISABLED > tempo = %f\n",lastTempo);
|
||||
runs = 0;
|
||||
}
|
||||
}
|
||||
else runs = 0;
|
||||
|
||||
valAccum1 = 1.0f;
|
||||
valAccum2 = 1.0f;
|
||||
numAccum = 0;
|
||||
ConLog(" %s * SPU2: TempoChange by %d%% (tempo: %d%%) (buffer: %d%%)\n",
|
||||
(relation < 0.0) ? "Normalize" : "",
|
||||
(int)(tempoChange * 100.0), (int)(cTempo * 100.0),
|
||||
(int)(statusPct * 100.0)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Nominal operation -- turn off stretching.
|
||||
pSoundTouch->setTempo( 1.0f );
|
||||
ts_stats_normalblocks++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void soundtouchInit() {
|
||||
pSoundTouch = new soundtouch::SoundTouch();
|
||||
pSoundTouch->setSampleRate(SampleRate);
|
||||
|
@ -500,18 +518,22 @@ void soundtouchInit() {
|
|||
|
||||
s32 SndInit()
|
||||
{
|
||||
if(OutputModule>=mods_count)
|
||||
return -1;
|
||||
if( mods[OutputModule] == NULL )
|
||||
{
|
||||
// force us to the NullOut module if nothing assigned.
|
||||
OutputModule = FindOutputModuleById( NullOut.GetIdent() );
|
||||
}
|
||||
|
||||
// initialize sound buffer
|
||||
sndBuffer = new SndBufferImpl(CurBufferSize * MaxBufferCount * 2);
|
||||
sndTempSize = 512;
|
||||
// Buffer actually attempts to run ~50%, so allocate near double what
|
||||
// the requested latency is:
|
||||
sndBuffer = new SndBufferImpl( SndOutLatencyMS * 1.75 );
|
||||
sndTempProgress = 0;
|
||||
sndTempBuffer = new s32[sndTempSize];
|
||||
sndTempBuffer16 = new s16[sndTempSize];
|
||||
sndTempBufferFloat = new float[sndTempSize];
|
||||
buffersize=sndBuffer->GetBufferSize();
|
||||
sndTempBuffer = new s32[SndOutPacketSize];
|
||||
sndTempBuffer16 = new s16[SndOutPacketSize];
|
||||
//sndTempBufferFloat = new float[sndTempSize];
|
||||
|
||||
cTempo = 1.0;
|
||||
soundtouchInit();
|
||||
|
||||
ResetTempoChange();
|
||||
|
@ -530,15 +552,11 @@ s32 SndInit()
|
|||
|
||||
void SndClose()
|
||||
{
|
||||
if(OutputModule>=mods_count)
|
||||
return;
|
||||
|
||||
mods[OutputModule]->Close();
|
||||
|
||||
delete sndBuffer;
|
||||
delete sndTempBuffer;
|
||||
delete sndTempBuffer16;
|
||||
delete sndTempBufferFloat;
|
||||
|
||||
delete pSoundTouch;
|
||||
}
|
||||
|
@ -560,88 +578,108 @@ void SndUpdateLimitMode()
|
|||
|
||||
}
|
||||
|
||||
bool SndGetStats(u32 *written, u32 *played)
|
||||
{
|
||||
return sndBuffer->GetStats(*written,*played,false);
|
||||
}
|
||||
|
||||
s32 SndWrite(s32 ValL, s32 ValR)
|
||||
{
|
||||
if(WaveLog && wavedump_ok)
|
||||
#ifndef PUBLIC
|
||||
if(WaveLog() && wavedump_ok)
|
||||
{
|
||||
wavedump_write(ValL>>8,ValR>>8);
|
||||
wavedump_write(SndScaleVol(ValL),SndScaleVol(ValR));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if(recording!=0)
|
||||
RecordWrite(ValL>>8,ValR>>8);
|
||||
|
||||
if(OutputModule>=mods_count)
|
||||
return -1;
|
||||
RecordWrite(SndScaleVol(ValL),SndScaleVol(ValR));
|
||||
|
||||
if(mods[OutputModule] == &NullOut) // null output doesn't need buffering or stretching! :p
|
||||
return 0;
|
||||
|
||||
inputSamples+=2;
|
||||
//inputSamples+=2;
|
||||
|
||||
sndTempBuffer[sndTempProgress++] = ValL;
|
||||
sndTempBuffer[sndTempProgress++] = ValR;
|
||||
|
||||
if(sndTempProgress>=sndTempSize)
|
||||
// If we haven't accumulated a full packet yet, do nothing more:
|
||||
if(sndTempProgress < SndOutPacketSize) return 1;
|
||||
|
||||
if(dspPluginEnabled)
|
||||
{
|
||||
if(dspPluginEnabled)
|
||||
for(int i=0;i<SndOutPacketSize;i++) { sndTempBuffer16[i] = SndScaleVol( sndTempBuffer[i] ); }
|
||||
|
||||
// send to winamp DSP
|
||||
sndTempProgress = DspProcess(sndTempBuffer16,sndTempProgress>>1)<<1;
|
||||
|
||||
for(int i=0;i<sndTempProgress;i++) { sndTempBuffer[i] = sndTempBuffer16[i]<<SndOutVolumeShift; }
|
||||
}
|
||||
|
||||
static int equalized = 0;
|
||||
if(timeStretchEnabled)
|
||||
{
|
||||
bool progress = false;
|
||||
|
||||
// data prediction helps keep the tempo adjustments more accurate.
|
||||
sndBuffer->PredictDataWrite( (int)( sndTempProgress / cTempo ) );
|
||||
for(int i=0;i<sndTempProgress;i++) { ((float*)sndTempBuffer)[i] = sndTempBuffer[i]/2147483648.0f; }
|
||||
|
||||
pSoundTouch->putSamples((float*)sndTempBuffer, sndTempProgress>>1);
|
||||
|
||||
while( ( sndTempProgress = pSoundTouch->receiveSamples((float*)sndTempBuffer, sndTempProgress>>1)<<1 ) != 0 )
|
||||
{
|
||||
for(int i=0;i<sndTempProgress;i++) { sndTempBuffer16[i] = sndTempBuffer[i]>>8; }
|
||||
|
||||
// send to winamp DSP
|
||||
sndTempProgress = DspProcess(sndTempBuffer16,sndTempProgress>>1)<<1;
|
||||
|
||||
for(int i=0;i<sndTempProgress;i++) { sndTempBuffer[i] = sndTempBuffer16[i]<<8; }
|
||||
}
|
||||
|
||||
if(timeStretchEnabled)
|
||||
{
|
||||
for(int i=0;i<sndTempProgress;i++) { sndTempBufferFloat[i] = sndTempBuffer[i]/2147483648.0f; }
|
||||
|
||||
// send to timestretcher
|
||||
pSoundTouch->putSamples(sndTempBufferFloat, sndTempProgress>>1);
|
||||
UpdateTempoChange();
|
||||
do
|
||||
// The timestretcher returns packets in belated "clump" form.
|
||||
// Meaning that most of the time we'll get nothing back, and then
|
||||
// suddenly we'll get several chunks back at once. That's
|
||||
// why we only update the tempo below after a set of blocks has been
|
||||
// released (otherwise the tempo rates will be skewed by backlogged data)
|
||||
|
||||
// [Air] [TODO] : Implement an SSE downsampler to int.
|
||||
for(int i=0;i<sndTempProgress;i++)
|
||||
{
|
||||
sndTempProgress = pSoundTouch->receiveSamples(sndTempBufferFloat, sndTempSize>>1)<<1;
|
||||
|
||||
if(sndTempProgress>0)
|
||||
{
|
||||
|
||||
for(int i=0;i<sndTempProgress;i++) { sndTempBuffer[i] = (s32)(sndTempBufferFloat[i]*2147483648.0f); }
|
||||
sndBuffer->WriteSamples(sndTempBuffer,sndTempProgress);
|
||||
}
|
||||
|
||||
} while (sndTempProgress != 0 );
|
||||
sndTempBuffer[i] = (s32)(((float*)sndTempBuffer)[i]*2147483648.0f);
|
||||
}
|
||||
sndBuffer->WriteSamples(sndTempBuffer, sndTempProgress);
|
||||
progress = true;
|
||||
}
|
||||
else
|
||||
|
||||
if( progress )
|
||||
{
|
||||
sndBuffer->WriteSamples(sndTempBuffer,sndTempProgress);
|
||||
sndTempProgress=0;
|
||||
UpdateTempoChange();
|
||||
|
||||
if( MsgOverruns() )
|
||||
{
|
||||
if( ++ts_stats_logcounter > 300 )
|
||||
{
|
||||
ts_stats_logcounter = 0;
|
||||
ConLog( " * SPU2 > Timestretch Stats > %d%% of packets stretched.\n",
|
||||
( ts_stats_stretchblocks * 100 ) / ( ts_stats_normalblocks + ts_stats_stretchblocks ) );
|
||||
ts_stats_normalblocks = 0;
|
||||
ts_stats_stretchblocks = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
sndBuffer->WriteSamples(sndTempBuffer, sndTempProgress);
|
||||
sndTempProgress=0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
s32 SndTest()
|
||||
{
|
||||
if(OutputModule>=mods_count)
|
||||
if( mods[OutputModule] == NULL )
|
||||
return -1;
|
||||
|
||||
return mods[OutputModule]->Test();
|
||||
}
|
||||
|
||||
void SndConfigure(HWND parent)
|
||||
void SndConfigure(HWND parent, u32 module )
|
||||
{
|
||||
if(OutputModule>=mods_count)
|
||||
if( mods[module] == NULL )
|
||||
return;
|
||||
|
||||
mods[OutputModule]->Configure(parent);
|
||||
mods[module]->Configure(parent);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
|
|
@ -18,12 +18,13 @@
|
|||
#ifndef SNDOUT_H_INCLUDE
|
||||
#define SNDOUT_H_INCLUDE
|
||||
|
||||
#define OUTPUT_NULL 0
|
||||
#define OUTPUT_WAVEOUT 1
|
||||
#define OUTPUT_DSOUND 2
|
||||
#define OUTPUT_DSOUND51 3
|
||||
#define OUTPUT_ASIO 4
|
||||
#define OUTPUT_XAUDIO2 5
|
||||
// Number of stereo samples per SndOut block.
|
||||
// All drivers must work in units of this size when communicating with
|
||||
// SndOut.
|
||||
static const int SndOutPacketSize = 1024;
|
||||
|
||||
static const int SndOutVolumeShiftBase = 14;
|
||||
extern int SndOutVolumeShift;
|
||||
|
||||
#define pcmlog
|
||||
extern FILE *wavelog;
|
||||
|
@ -32,32 +33,46 @@ s32 SndInit();
|
|||
void SndClose();
|
||||
s32 SndWrite(s32 ValL, s32 ValR);
|
||||
s32 SndTest();
|
||||
void SndConfigure(HWND parent);
|
||||
void SndConfigure(HWND parent, u32 outmodidx );
|
||||
bool SndGetStats(u32 *written, u32 *played);
|
||||
|
||||
int FindOutputModuleById( const char* omodid );
|
||||
|
||||
class SndBuffer
|
||||
{
|
||||
public:
|
||||
virtual ~SndBuffer() {}
|
||||
|
||||
virtual void WriteSamples(s32 *buffer, s32 nSamples)=0;
|
||||
virtual void ReadSamples (s32 *buffer, s32 nSamples)=0;
|
||||
|
||||
virtual void WriteSamples(s32 *buffer, int nSamples)=0;
|
||||
virtual void PauseOnWrite(bool doPause)=0;
|
||||
|
||||
virtual s32 GetBufferUsage()=0;
|
||||
virtual s32 GetBufferSize()=0;
|
||||
virtual void ReadSamples( s16* bData )=0;
|
||||
virtual void ReadSamples( s32* bData )=0;
|
||||
|
||||
//virtual s32 GetBufferUsage()=0;
|
||||
//virtual s32 GetBufferSize()=0;
|
||||
};
|
||||
|
||||
class SndOutModule
|
||||
{
|
||||
public:
|
||||
// Returns a unique identification string for this driver.
|
||||
// (usually just matches the driver's cpp filename)
|
||||
virtual const char* GetIdent() const=0;
|
||||
|
||||
// Returns the long name / description for this driver.
|
||||
// (for use in configuration screen)
|
||||
virtual const char* GetLongName() const=0;
|
||||
|
||||
virtual s32 Init(SndBuffer *buffer)=0;
|
||||
virtual void Close()=0;
|
||||
virtual s32 Test()=0;
|
||||
virtual s32 Test() const=0;
|
||||
virtual void Configure(HWND parent)=0;
|
||||
virtual bool Is51Out() const=0;
|
||||
|
||||
virtual bool Is51Out()=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() const=0;
|
||||
};
|
||||
|
||||
//internal
|
||||
|
@ -69,6 +84,5 @@ extern SndOutModule *XAudio2Out;
|
|||
extern SndOutModule *DSound51Out;
|
||||
|
||||
extern SndOutModule* mods[];
|
||||
extern const u32 mods_count;
|
||||
|
||||
#endif // SNDOUT_H_INCLUDE
|
||||
|
|
|
@ -42,6 +42,7 @@ static char *libraryName = "GiGaHeRz's SPU2 ("
|
|||
#endif
|
||||
")";
|
||||
|
||||
|
||||
DWORD CALLBACK TimeThread(PVOID /* unused param */);
|
||||
|
||||
|
||||
|
@ -171,11 +172,12 @@ void __inline __fastcall spu2M_Write( u32 addr, s16 value )
|
|||
// Make sure the cache is invalidated:
|
||||
// (note to self : addr address WORDs, not bytes)
|
||||
|
||||
addr &= 0xfffff;
|
||||
const u32 nexta = addr >> 3; // 8 words per encoded block.
|
||||
const u32 flagbitmask = 1ul<<(nexta & 31); // 31 flags per array entry
|
||||
pcm_cache_flags[nexta>>5] &= ~flagbitmask;
|
||||
|
||||
*GetMemPtr( addr & 0xfffff ) = value;
|
||||
*GetMemPtr( addr ) = value;
|
||||
}
|
||||
|
||||
// writes an unsigned value to the SPU2 ram
|
||||
|
@ -271,7 +273,7 @@ s32 CALLBACK SPU2init()
|
|||
acumCycles=0;
|
||||
|
||||
#ifdef SPU2_LOG
|
||||
if(AccessLog)
|
||||
if(AccessLog())
|
||||
{
|
||||
spu2Log = fopen(AccessLogFileName, "w");
|
||||
setvbuf(spu2Log, NULL, _IONBF, 0);
|
||||
|
@ -325,7 +327,7 @@ s32 CALLBACK SPU2init()
|
|||
|
||||
DMALogOpen();
|
||||
|
||||
if(WaveLog)
|
||||
if(WaveLog())
|
||||
{
|
||||
if(!wavedump_open())
|
||||
{
|
||||
|
@ -459,7 +461,7 @@ void CALLBACK SPU2shutdown()
|
|||
fclose(el0);
|
||||
fclose(el1);
|
||||
#endif
|
||||
if(WaveLog && wavedump_ok) wavedump_close();
|
||||
if(WaveLog() && wavedump_ok) wavedump_close();
|
||||
|
||||
DMALogClose();
|
||||
|
||||
|
@ -477,7 +479,7 @@ void CALLBACK SPU2shutdown()
|
|||
pcm_cache_data = NULL;
|
||||
|
||||
#ifdef SPU2_LOG
|
||||
if(!AccessLog) return;
|
||||
if(!AccessLog()) return;
|
||||
FileLog("[%10d] SPU2shutdown\n",Cycles);
|
||||
if(spu2Log) fclose(spu2Log);
|
||||
#endif
|
||||
|
@ -1895,7 +1897,7 @@ void VoiceStart(int core,int vc)
|
|||
DebugCores[core].Voices[vc].FirstBlock=1;
|
||||
if(core==1)
|
||||
{
|
||||
if(MsgKeyOnOff) ConLog(" * SPU2: KeyOn: C%dV%02d: SSA: %8x; M: %s%s%s%s; H: %02x%02x; P: %04x V: %04x/%04x; ADSR: %04x%04x\n",
|
||||
if(MsgKeyOnOff()) ConLog(" * SPU2: KeyOn: C%dV%02d: SSA: %8x; M: %s%s%s%s; H: %02x%02x; P: %04x V: %04x/%04x; ADSR: %04x%04x\n",
|
||||
core,vc,Cores[core].Voices[vc].StartA,
|
||||
(Cores[core].Voices[vc].DryL)?"+":"-",(Cores[core].Voices[vc].DryR)?"+":"-",
|
||||
(Cores[core].Voices[vc].WetL)?"+":"-",(Cores[core].Voices[vc].WetR)?"+":"-",
|
||||
|
@ -1944,7 +1946,7 @@ void StopVoices(int core, u32 value)
|
|||
for (vc=0;vc<24;vc++) {
|
||||
if ((value>>vc) & 1) {
|
||||
Cores[core].Voices[vc].ADSR.Releasing=1;
|
||||
//if(MsgKeyOnOff) ConLog(" * SPU2: KeyOff: Core %d; Voice %d.\n",core,vc);
|
||||
//if(MsgKeyOnOff()) ConLog(" * SPU2: KeyOff: Core %d; Voice %d.\n",core,vc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,21 +16,23 @@
|
|||
//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
#include "spu2.h"
|
||||
#include "dialogs.h"
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
class WaveOutModule: public SndOutModule
|
||||
{
|
||||
private:
|
||||
# define MAX_BUFFER_COUNT 8
|
||||
|
||||
#define MAX_BUFFER_COUNT 5
|
||||
|
||||
#define BufferSize (CurBufferSize<<1)
|
||||
#define BufferSizeBytes (BufferSize<<1)
|
||||
static const int PacketsPerBuffer = (1024 / SndOutPacketSize);
|
||||
static const int BufferSize = SndOutPacketSize*PacketsPerBuffer;
|
||||
static const int BufferSizeBytes = BufferSize << 1;
|
||||
|
||||
HWAVEOUT hwodevice;
|
||||
WAVEFORMATEX wformat;
|
||||
WAVEHDR whbuffer[MAX_BUFFER_COUNT];
|
||||
|
||||
s32* tbuffer;
|
||||
s16* qbuffer;
|
||||
|
||||
#define QBUFFER(x) (qbuffer + BufferSize * (x))
|
||||
|
@ -63,14 +65,9 @@ private:
|
|||
|
||||
buf->dwBytesRecorded = buf->dwBufferLength;
|
||||
|
||||
buff->ReadSamples(tbuffer,BufferSize);
|
||||
s16 *t = (s16*)buf->lpData;
|
||||
s32 *s = (s32*)tbuffer;
|
||||
|
||||
for(int bleh=0;bleh<BufferSize;bleh++)
|
||||
{
|
||||
*(t++) = (s16)((*(s++))>>8);
|
||||
}
|
||||
for(int p=0; p<PacketsPerBuffer; p++, t+=SndOutPacketSize )
|
||||
buff->ReadSamples( t );
|
||||
|
||||
whbuffer[i].dwFlags&=~WHDR_DONE;
|
||||
waveOutWrite(hwodevice,buf,sizeof(WAVEHDR));
|
||||
|
@ -94,8 +91,6 @@ public:
|
|||
|
||||
if (Test()) return -1;
|
||||
|
||||
if(CurBufferSize<1024) CurBufferSize=1024;
|
||||
|
||||
wformat.wFormatTag=WAVE_FORMAT_PCM;
|
||||
wformat.nSamplesPerSec=SampleRate;
|
||||
wformat.wBitsPerSample=16;
|
||||
|
@ -105,7 +100,6 @@ public:
|
|||
wformat.cbSize=0;
|
||||
|
||||
qbuffer=new s16[BufferSize*MAX_BUFFER_COUNT];
|
||||
tbuffer=new s32[BufferSize];
|
||||
|
||||
woores = waveOutOpen(&hwodevice,WAVE_MAPPER,&wformat,0,0,0);
|
||||
if (woores != MMSYSERR_NOERROR)
|
||||
|
@ -161,23 +155,121 @@ public:
|
|||
}
|
||||
waveOutClose(hwodevice);
|
||||
|
||||
delete tbuffer;
|
||||
delete qbuffer;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
virtual void Configure(HWND parent)
|
||||
static BOOL CALLBACK ConfigProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
|
||||
{
|
||||
int wmId,wmEvent;
|
||||
int tSel=0;
|
||||
|
||||
switch(uMsg)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
|
||||
char 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);
|
||||
sprintf_s(temp, 128, "%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 );
|
||||
|
||||
if( Config_WaveOut.NumBuffers < 3 ) Config_WaveOut.NumBuffers = 3;
|
||||
if( Config_WaveOut.NumBuffers > MAX_BUFFER_COUNT ) Config_WaveOut.NumBuffers = MAX_BUFFER_COUNT;
|
||||
}
|
||||
EndDialog(hWnd,0);
|
||||
break;
|
||||
case IDCANCEL:
|
||||
EndDialog(hWnd,0);
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_HSCROLL:
|
||||
wmId = LOWORD(wParam);
|
||||
wmEvent = HIWORD(wParam);
|
||||
switch(wmId) {
|
||||
//case TB_ENDTRACK:
|
||||
//case TB_THUMBPOSITION:
|
||||
case TB_LINEUP:
|
||||
case TB_LINEDOWN:
|
||||
case TB_PAGEUP:
|
||||
case TB_PAGEDOWN:
|
||||
wmEvent=(int)SendMessage((HWND)lParam,TBM_GETPOS,0,0);
|
||||
case TB_THUMBTRACK:
|
||||
if( wmEvent < 3 ) wmEvent = 3;
|
||||
if( wmEvent > MAX_BUFFER_COUNT ) wmEvent = MAX_BUFFER_COUNT;
|
||||
SendMessage((HWND)lParam,TBM_SETPOS,TRUE,wmEvent);
|
||||
sprintf_s(temp,128,"%d (%d ms latency)",wmEvent, 1000 / (96000 / (wmEvent * BufferSize)));
|
||||
SetWindowText(GetDlgItem(hWnd,IDC_LATENCY_LABEL),temp);
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
virtual bool Is51Out() { return false; }
|
||||
public:
|
||||
virtual void Configure(HWND parent)
|
||||
{
|
||||
INT_PTR ret;
|
||||
ret=DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_WAVEOUT),GetActiveWindow(),(DLGPROC)ConfigProc,1);
|
||||
if(ret==-1)
|
||||
{
|
||||
MessageBoxEx(GetActiveWindow(),"Error Opening the config dialog.","OMG ERROR!",MB_OK,0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
s32 Test() {
|
||||
virtual bool Is51Out() const { return false; }
|
||||
|
||||
s32 Test() const
|
||||
{
|
||||
if (waveOutGetNumDevs() == 0) {
|
||||
SysMessage("No waveOut Devices Present\n"); return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetEmptySampleCount() const
|
||||
{
|
||||
int result = 0;
|
||||
for(int i=0;i<MAX_BUFFER_COUNT;i++)
|
||||
{
|
||||
result += (whbuffer[i].dwFlags & WHDR_DONE) ? BufferSize : 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const char* GetIdent() const
|
||||
{
|
||||
return "waveout";
|
||||
}
|
||||
|
||||
const char* GetLongName() const
|
||||
{
|
||||
return "waveOut (Laggy)";
|
||||
}
|
||||
|
||||
} WO;
|
||||
|
||||
SndOutModule *WaveOut=&WO;
|
||||
|
|
|
@ -27,13 +27,11 @@
|
|||
class XAudio2Mod: public SndOutModule
|
||||
{
|
||||
private:
|
||||
static const int BufferSize = SndOutPacketSize;
|
||||
static const int BufferSizeBytes = BufferSize * 2;
|
||||
//#define BufferSize (SndOutPacketSize<<1)
|
||||
//#define BufferSizeBytes (BufferSize<<1)
|
||||
|
||||
//#define PI 3.14159265f
|
||||
|
||||
#define BufferSize (CurBufferSize<<1)
|
||||
#define BufferSizeBytes (BufferSize<<1)
|
||||
|
||||
s32* tbuffer;
|
||||
s16* qbuffer;
|
||||
|
||||
s32 out_num;
|
||||
|
@ -104,16 +102,9 @@ private:
|
|||
out_num=(out_num+1)%MAX_BUFFER_COUNT;
|
||||
|
||||
XAUDIO2_BUFFER buf = {0};
|
||||
buff->ReadSamples(tbuffer,BufferSize);
|
||||
buff->ReadSamples(qb);
|
||||
|
||||
buf.AudioBytes = BufferSizeBytes;
|
||||
s16 *t = qb;
|
||||
s32 *s = (s32*)tbuffer;
|
||||
for(int i=0;i<BufferSize;i++)
|
||||
{
|
||||
*(t++) = (s16)((*(s++))>>8);
|
||||
}
|
||||
|
||||
buf.pAudioData=(const BYTE*)qb;
|
||||
|
||||
pSourceVoice->SubmitSourceBuffer( &buf );
|
||||
|
@ -161,7 +152,7 @@ public:
|
|||
wfx.nChannels=2;
|
||||
wfx.wBitsPerSample = 16;
|
||||
wfx.nBlockAlign = 2*2;
|
||||
wfx.nAvgBytesPerSec = SampleRate * 2 * 2;
|
||||
wfx.nAvgBytesPerSec = SampleRate * wfx.nBlockAlign;
|
||||
wfx.cbSize=0;
|
||||
|
||||
//
|
||||
|
@ -175,9 +166,9 @@ public:
|
|||
}
|
||||
pSourceVoice->Start( 0, 0 );
|
||||
|
||||
tbuffer = new s32[BufferSize];
|
||||
//tbuffer = new s32[BufferSize];
|
||||
qbuffer = new s16[BufferSize*MAX_BUFFER_COUNT];
|
||||
ZeroMemory(qbuffer,BufferSize*MAX_BUFFER_COUNT);
|
||||
ZeroMemory(qbuffer,BufferSize*MAX_BUFFER_COUNT*2);
|
||||
|
||||
// Start Thread
|
||||
xaudio2_running=true;
|
||||
|
@ -218,20 +209,34 @@ public:
|
|||
|
||||
SAFE_RELEASE( pXAudio2 );
|
||||
CoUninitialize();
|
||||
|
||||
delete tbuffer;
|
||||
}
|
||||
|
||||
virtual void Configure(HWND parent)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Is51Out() { return false; }
|
||||
virtual bool Is51Out() const { return false; }
|
||||
|
||||
s32 Test()
|
||||
s32 Test() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetEmptySampleCount() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* GetIdent() const
|
||||
{
|
||||
return "xaudio2";
|
||||
}
|
||||
|
||||
const char* GetLongName() const
|
||||
{
|
||||
return "XAudio 2 (Experimental)";
|
||||
}
|
||||
|
||||
} XA2;
|
||||
|
||||
SndOutModule *XAudio2Out=&XA2;
|
||||
|
|
Loading…
Reference in New Issue