748 lines
21 KiB
C++
748 lines
21 KiB
C++
/* FCE Ultra - NES/Famicom Emulator
|
|
*
|
|
* Copyright notice for this file:
|
|
* Copyright (C) 2002 Xodnizel
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
|
|
LPDIRECTSOUND ppDS=0; /* DirectSound object. */
|
|
LPDIRECTSOUNDBUFFER ppbuf=0; /* Primary buffer object. */
|
|
LPDIRECTSOUNDBUFFER ppbufsec=0; /* Secondary buffer object. */
|
|
LPDIRECTSOUNDBUFFER ppbufw; /* Buffer to actually write to. */
|
|
|
|
long DSBufferSize; /* The size of the buffer that we can write to, in bytes. */
|
|
|
|
long BufHowMuch; /* How many bytes we should try to buffer. */
|
|
DWORD ToWritePos; /* Position which the next write to the buffer
|
|
should write to.
|
|
*/
|
|
|
|
|
|
|
|
DSBUFFERDESC DSBufferDesc;
|
|
WAVEFORMATEX wfa;
|
|
WAVEFORMATEX wf;
|
|
|
|
//bittag=1 -> 8bit output
|
|
int bittage;
|
|
static int mute=0; /* TODO: add to config? add to GUI. */
|
|
|
|
void TrashSound(void)
|
|
{
|
|
FCEUI_Sound(0);
|
|
if(ppbufsec)
|
|
{
|
|
IDirectSoundBuffer_Stop(ppbufsec);
|
|
IDirectSoundBuffer_Release(ppbufsec);
|
|
ppbufsec=0;
|
|
}
|
|
if(ppbuf)
|
|
{
|
|
IDirectSoundBuffer_Stop(ppbuf);
|
|
IDirectSoundBuffer_Release(ppbuf);
|
|
ppbuf=0;
|
|
}
|
|
if(ppDS)
|
|
{
|
|
IDirectSound_Release(ppDS);
|
|
ppDS=0;
|
|
}
|
|
}
|
|
|
|
void CheckDStatus(void)
|
|
{
|
|
DWORD status;
|
|
status=0;
|
|
IDirectSoundBuffer_GetStatus(ppbufw, &status);
|
|
|
|
if(status&DSBSTATUS_BUFFERLOST)
|
|
{
|
|
IDirectSoundBuffer_Restore(ppbufw);
|
|
}
|
|
|
|
if(!(status&DSBSTATUS_PLAYING))
|
|
{
|
|
ToWritePos=0;
|
|
IDirectSoundBuffer_SetFormat(ppbufw,&wf);
|
|
IDirectSoundBuffer_Play(ppbufw,0,0,DSBPLAY_LOOPING);
|
|
}
|
|
}
|
|
|
|
static uint32 RawCanWrite(void)
|
|
{
|
|
DWORD CurWritePos,CurPlayPos=0;
|
|
|
|
CheckDStatus();
|
|
|
|
CurWritePos=0;
|
|
|
|
if(IDirectSoundBuffer_GetCurrentPosition(ppbufw,&CurPlayPos,&CurWritePos)==DS_OK)
|
|
{
|
|
// FCEU_DispMessage("%8d",(CurWritePos-CurPlayPos));
|
|
}
|
|
CurWritePos=(CurPlayPos+BufHowMuch)%DSBufferSize;
|
|
|
|
/* If the current write pos is >= half the buffer size less than the to write pos,
|
|
assume DirectSound has wrapped around.
|
|
*/
|
|
|
|
if(((int32)ToWritePos-(int32)CurWritePos) >= (DSBufferSize/2))
|
|
{
|
|
CurWritePos+=DSBufferSize;
|
|
//FCEU_printf("Fixit: %d,%d,%d\n",ToWritePos,CurWritePos,CurWritePos-DSBufferSize);
|
|
}
|
|
if(ToWritePos<CurWritePos)
|
|
{
|
|
int32 howmuch=(int32)CurWritePos-(int32)ToWritePos;
|
|
if(howmuch > BufHowMuch) /* Oopsie. Severe buffer overflow... */
|
|
{
|
|
//FCEU_printf("Ack");
|
|
ToWritePos=CurWritePos%DSBufferSize;
|
|
}
|
|
return(CurWritePos-ToWritePos);
|
|
}
|
|
else
|
|
return(0);
|
|
}
|
|
|
|
int32 GetWriteSound(void)
|
|
{
|
|
if(!soundo)
|
|
return 0;
|
|
return(RawCanWrite() >> bittage);
|
|
}
|
|
|
|
int32 GetMaxSound(void)
|
|
{
|
|
return( BufHowMuch >> bittage);
|
|
}
|
|
|
|
static int RawWrite(void *data, uint32 len)
|
|
{
|
|
//uint32 cw; //mbg merge 7/17/06 removed
|
|
|
|
//printf("Pre: %d\n",SexyALI_DSound_RawCanWrite(device));
|
|
//fflush(stdout);
|
|
|
|
if(!soundo)
|
|
return 0;
|
|
|
|
CheckDStatus();
|
|
/* In this block, we write as much data as we can, then we write
|
|
the rest of it in >=1ms chunks.
|
|
*/
|
|
while(len)
|
|
{
|
|
VOID *LockPtr[2]={0,0};
|
|
DWORD LockLen[2]={0,0};
|
|
|
|
//mbg merge 7/17/06 changed to uint
|
|
//mbg merge 7/18/06 was causing a crash when fastforwarding unless this was initialized to len
|
|
uint32 curlen=len;
|
|
|
|
|
|
// THIS LIMITS THE EMULATION SPEED
|
|
if((!NoWaiting) || (soundoptions&SO_OLDUP))
|
|
while(!(curlen=RawCanWrite()))
|
|
{
|
|
Sleep(1);
|
|
}
|
|
|
|
if(curlen>len) curlen=len;
|
|
|
|
if(DS_OK == IDirectSoundBuffer_Lock(ppbufw,ToWritePos,curlen,&LockPtr[0],&LockLen[0],&LockPtr[1],&LockLen[1],0))
|
|
{
|
|
}
|
|
|
|
if(LockPtr[1] != 0 && LockPtr[1] != LockPtr[0])
|
|
{
|
|
if(mute)
|
|
{
|
|
if(bittage)
|
|
{
|
|
memset(LockPtr[0], 0, LockLen[0]);
|
|
memset(LockPtr[1], 0, len-LockLen[0]);
|
|
}
|
|
else
|
|
{
|
|
memset(LockPtr[0], 0x80, LockLen[0]);
|
|
memset(LockPtr[1], 0x80, len-LockLen[0]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* not mute */
|
|
memcpy(LockPtr[0],data,LockLen[0]);
|
|
memcpy(LockPtr[1],(char*)data+LockLen[0],len-LockLen[0]); //mbg merge 7/17/06 added cast
|
|
}
|
|
}
|
|
else if(LockPtr[0])
|
|
{
|
|
if(mute)
|
|
{
|
|
if(bittage)
|
|
memset(LockPtr[0], 0, curlen);
|
|
else
|
|
memset(LockPtr[0], 0x80, curlen);
|
|
}
|
|
else
|
|
{
|
|
/* not mute */
|
|
memcpy(LockPtr[0],data,curlen);
|
|
}
|
|
}
|
|
IDirectSoundBuffer_Unlock(ppbufw,LockPtr[0],LockLen[0],LockPtr[1],LockLen[1]);
|
|
ToWritePos=(ToWritePos+curlen)%DSBufferSize;
|
|
|
|
len-=curlen;
|
|
data=(uint8 *)data+curlen; //mbg merge 7/17/06 reworked to be type proper
|
|
|
|
if(len && !NoWaiting && (fps_scale <= 256 || (soundoptions&SO_OLDUP)))
|
|
Sleep(1); // do some extra sleeping if we think there's time and we're not scaling up the FPS or in turbo mode
|
|
|
|
} // end while(len) loop
|
|
|
|
|
|
return(1);
|
|
}
|
|
|
|
int silencer=0;
|
|
|
|
int FCEUD_WriteSoundData(int32 *Buffer, int scale, int Count)
|
|
{
|
|
#define WSD_BUFSIZE (2 * 96000 / 50)
|
|
|
|
int P;
|
|
int iCount=0;
|
|
static int16 MBuffer[WSD_BUFSIZE*2];
|
|
|
|
if(!(soundoptions&SO_OLDUP))
|
|
{
|
|
if(FCEUI_EmulationPaused())
|
|
memset(MBuffer, 0, WSD_BUFSIZE); // slow and/or unnecessary
|
|
|
|
if(FCEUI_EmulationPaused()) scale >>= 1;
|
|
|
|
// limit frequency change to between 50% and 200%
|
|
if(scale > 512) scale = 512;
|
|
if(scale < 128) scale = 128;
|
|
}
|
|
|
|
// for(;Count>0;Count-=WSD_BUFSIZE)
|
|
{
|
|
int amt = (soundoptions&SO_OLDUP) ? Count : (Count > WSD_BUFSIZE ? WSD_BUFSIZE : Count);
|
|
|
|
if(!bittage)
|
|
{
|
|
if(silencer)
|
|
for(P=0;P<amt;P++)
|
|
*(((uint8*)MBuffer)+P)=((int8)(Buffer[0]>>8))^128;
|
|
else if(scale == 256) // exactly 100% speed
|
|
for(P=0;P<amt;P++)
|
|
*(((uint8*)MBuffer)+P)=((int8)(Buffer[P]>>8))^128;
|
|
else // change sound frequency
|
|
for(P=0;P<amt;P++)
|
|
*(((uint8*)MBuffer)+P)=((int8)(Buffer[P*scale/256]>>8))^128;
|
|
|
|
RawWrite(MBuffer,amt);
|
|
}
|
|
else // force 8-bit sound is off:
|
|
{
|
|
if(silencer)
|
|
for(P=0;P<amt;P++)
|
|
MBuffer[P]=Buffer[0];
|
|
else if(scale == 256) // exactly 100% speed
|
|
for(P=0;P<amt;P++)
|
|
MBuffer[P]=Buffer[P];
|
|
else // change sound frequency
|
|
for(P=0;P<amt;P++)
|
|
MBuffer[P]=Buffer[P*scale/256];
|
|
|
|
RawWrite(MBuffer,amt * 2);
|
|
}
|
|
|
|
iCount+=amt;
|
|
}
|
|
|
|
// FCEUI_AviSoundUpdate((void*)MBuffer, Count);
|
|
return iCount;
|
|
}
|
|
|
|
/*
|
|
//mbg merge 7/19/06 an experiment in understanding the sound update code
|
|
int FCEUD_WriteSoundData(int32 *Buffer, int scale, int Count)
|
|
{
|
|
#define WSD_BUFSIZE (2 * 96000 / 50)
|
|
|
|
int P;
|
|
int iCount=0;
|
|
static int16 MBuffer[WSD_BUFSIZE*2];
|
|
|
|
//if(!(soundoptions&SO_OLDUP))
|
|
//{
|
|
//shouldnt the sound be stopped?
|
|
//if(FCEUI_EmulationPaused())
|
|
// memset(MBuffer, 0, WSD_BUFSIZE); // slow and/or unnecessary
|
|
|
|
//why?
|
|
//if(FCEUI_EmulationPaused()) scale >>= 1;
|
|
// limit frequency change to between 50% and 200%
|
|
//if(scale > 512) scale = 512;
|
|
//if(scale < 128) scale = 128;
|
|
//}
|
|
|
|
int silence = FCEUI_EmulationPaused() | silencer;
|
|
|
|
for(;Count>0;Count-=WSD_BUFSIZE)
|
|
{
|
|
//int amt = (soundoptions&SO_OLDUP) ? Count : (Count > WSD_BUFSIZE ? WSD_BUFSIZE : Count);
|
|
int amt = (Count > WSD_BUFSIZE ? WSD_BUFSIZE : Count);
|
|
|
|
if(!bittage)
|
|
{
|
|
if(silence)
|
|
for(P=0;P<amt;P++)
|
|
*(((uint8*)MBuffer)+P)=((int8)(Buffer[0]>>8))^128;
|
|
else if(scale == 256) // exactly 100% speed
|
|
for(P=0;P<amt;P++)
|
|
*(((uint8*)MBuffer)+P)=((int8)(Buffer[P]>>8))^128;
|
|
else // change sound frequency
|
|
for(P=0;P<amt;P++)
|
|
*(((uint8*)MBuffer)+P)=((int8)(Buffer[P*scale/256]>>8))^128;
|
|
|
|
RawWrite(MBuffer,amt);
|
|
}
|
|
else // force 8-bit sound is off:
|
|
{
|
|
if(silence)
|
|
for(P=0;P<amt;P++)
|
|
MBuffer[P]=Buffer[0];
|
|
else if(scale == 256) // exactly 100% speed
|
|
for(P=0;P<amt;P++)
|
|
MBuffer[P]=Buffer[P];
|
|
else // change sound frequency
|
|
for(int chan=0;chan<2;chan++) {
|
|
int16 *dest = MBuffer+chan;
|
|
int32 *src = Buffer+chan;
|
|
int work = amt>>1;
|
|
for(P=0;P<work;P++) {
|
|
//interpolate
|
|
int loc = P*scale;
|
|
int mix = src[(loc>>8)<<1];
|
|
mix += ((src[((loc>>8)+1)<<1]-mix)*(loc&255))>>8;
|
|
dest[P<<1] = mix;
|
|
}
|
|
}
|
|
|
|
RawWrite(MBuffer,amt * 2);
|
|
}
|
|
|
|
iCount+=amt;
|
|
}
|
|
|
|
// FCEUI_AviSoundUpdate((void*)MBuffer, Count);
|
|
return iCount;
|
|
}
|
|
*/
|
|
|
|
int InitSound()
|
|
{
|
|
DSCAPS dscaps;
|
|
DSBCAPS dsbcaps;
|
|
|
|
memset(&wf,0x00,sizeof(wf));
|
|
wf.wFormatTag = WAVE_FORMAT_PCM;
|
|
wf.nChannels = 1;
|
|
wf.nSamplesPerSec = soundrate;
|
|
|
|
ddrval=DirectSoundCreate(0,&ppDS,0);
|
|
if (ddrval != DS_OK)
|
|
{
|
|
FCEUD_PrintError("DirectSound: Error creating DirectSound object.");
|
|
return 0;
|
|
}
|
|
|
|
if(soundoptions&SO_SECONDARY)
|
|
{
|
|
trysecondary:
|
|
ddrval=IDirectSound_SetCooperativeLevel(ppDS,hAppWnd,DSSCL_PRIORITY);
|
|
if (ddrval != DS_OK)
|
|
{
|
|
FCEUD_PrintError("DirectSound: Error setting cooperative level to DDSCL_PRIORITY.");
|
|
TrashSound();
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ddrval=IDirectSound_SetCooperativeLevel(ppDS,hAppWnd,DSSCL_WRITEPRIMARY);
|
|
if (ddrval != DS_OK)
|
|
{
|
|
FCEUD_PrintError("DirectSound: Error setting cooperative level to DDSCL_WRITEPRIMARY. Forcing use of secondary sound buffer and trying again...");
|
|
soundoptions|=SO_SECONDARY;
|
|
goto trysecondary;
|
|
}
|
|
}
|
|
memset(&dscaps,0x00,sizeof(dscaps));
|
|
dscaps.dwSize=sizeof(dscaps);
|
|
ddrval=IDirectSound_GetCaps(ppDS,&dscaps);
|
|
if(ddrval!=DS_OK)
|
|
{
|
|
FCEUD_PrintError("DirectSound: Error getting capabilities.");
|
|
return 0;
|
|
}
|
|
|
|
if(dscaps.dwFlags&DSCAPS_EMULDRIVER)
|
|
FCEUD_PrintError("DirectSound: Sound device is being emulated through waveform-audio functions. Sound quality will most likely be awful. Try to update your sound device's sound drivers.");
|
|
|
|
IDirectSound_Compact(ppDS);
|
|
|
|
memset(&DSBufferDesc,0x00,sizeof(DSBUFFERDESC));
|
|
DSBufferDesc.dwSize=sizeof(DSBufferDesc);
|
|
if(soundoptions&SO_SECONDARY)
|
|
DSBufferDesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
|
|
else
|
|
DSBufferDesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_GETCURRENTPOSITION2;
|
|
|
|
ddrval=IDirectSound_CreateSoundBuffer(ppDS,&DSBufferDesc,&ppbuf,0);
|
|
if (ddrval != DS_OK)
|
|
{
|
|
FCEUD_PrintError("DirectSound: Error creating primary buffer.");
|
|
TrashSound();
|
|
return 0;
|
|
}
|
|
|
|
memset(&wfa,0x00,sizeof(wfa));
|
|
|
|
if(soundoptions&SO_FORCE8BIT)
|
|
bittage=0;
|
|
else
|
|
{
|
|
bittage=1;
|
|
if( (!(dscaps.dwFlags&DSCAPS_PRIMARY16BIT) && !(soundoptions&SO_SECONDARY)) ||
|
|
(!(dscaps.dwFlags&DSCAPS_SECONDARY16BIT) && (soundoptions&SO_SECONDARY)))
|
|
{
|
|
FCEUD_PrintError("DirectSound: 16-bit sound is not supported. Forcing 8-bit sound.");
|
|
bittage=0;
|
|
soundoptions|=SO_FORCE8BIT;
|
|
}
|
|
}
|
|
|
|
wf.wBitsPerSample=8<<bittage;
|
|
wf.nBlockAlign = bittage+1;
|
|
wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign;
|
|
|
|
ddrval=IDirectSoundBuffer_SetFormat(ppbuf,&wf);
|
|
if (ddrval != DS_OK)
|
|
{
|
|
FCEUD_PrintError("DirectSound: Error setting primary buffer format.");
|
|
TrashSound();
|
|
return 0;
|
|
}
|
|
|
|
IDirectSoundBuffer_GetFormat(ppbuf,&wfa,sizeof(wfa),0);
|
|
|
|
if(soundoptions&SO_SECONDARY)
|
|
{
|
|
memset(&DSBufferDesc,0x00,sizeof(DSBUFFERDESC));
|
|
DSBufferDesc.dwSize=sizeof(DSBufferDesc);
|
|
DSBufferDesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
|
|
if(soundoptions&SO_GFOCUS)
|
|
DSBufferDesc.dwFlags|=DSBCAPS_GLOBALFOCUS;
|
|
DSBufferDesc.dwBufferBytes=65536;
|
|
DSBufferDesc.lpwfxFormat=&wfa;
|
|
ddrval=IDirectSound_CreateSoundBuffer(ppDS, &DSBufferDesc, &ppbufsec, 0);
|
|
if (ddrval != DS_OK)
|
|
{
|
|
FCEUD_PrintError("DirectSound: Error creating secondary buffer.");
|
|
TrashSound();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
//sprintf(TempArray,"%d\n",wfa.nSamplesPerSec);
|
|
//FCEUD_PrintError(TempArray);
|
|
|
|
if(soundoptions&SO_SECONDARY)
|
|
{
|
|
DSBufferSize=65536;
|
|
IDirectSoundBuffer_SetCurrentPosition(ppbufsec,0);
|
|
ppbufw=ppbufsec;
|
|
}
|
|
else
|
|
{
|
|
memset(&dsbcaps,0,sizeof(dsbcaps));
|
|
dsbcaps.dwSize=sizeof(dsbcaps);
|
|
ddrval=IDirectSoundBuffer_GetCaps(ppbuf,&dsbcaps);
|
|
if (ddrval != DS_OK)
|
|
{
|
|
FCEUD_PrintError("DirectSound: Error getting buffer capabilities.");
|
|
TrashSound();
|
|
return 0;
|
|
}
|
|
|
|
DSBufferSize=dsbcaps.dwBufferBytes;
|
|
|
|
if(DSBufferSize<8192)
|
|
{
|
|
FCEUD_PrintError("DirectSound: Primary buffer size is too small!");
|
|
TrashSound();
|
|
return 0;
|
|
}
|
|
ppbufw=ppbuf;
|
|
}
|
|
|
|
BufHowMuch=(soundbuftime*soundrate/1000)<<bittage;
|
|
FCEUI_Sound(soundrate);
|
|
return 1;
|
|
}
|
|
|
|
static HWND uug=0;
|
|
|
|
static void UpdateSD(HWND hwndDlg)
|
|
{
|
|
int t;
|
|
|
|
CheckDlgButton(hwndDlg,126,soundo?BST_CHECKED:BST_UNCHECKED);
|
|
CheckDlgButton(hwndDlg,122,(soundoptions&SO_FORCE8BIT)?BST_CHECKED:BST_UNCHECKED);
|
|
CheckDlgButton(hwndDlg,123,(soundoptions&SO_SECONDARY)?BST_CHECKED:BST_UNCHECKED);
|
|
CheckDlgButton(hwndDlg,124,(soundoptions&SO_GFOCUS)?BST_CHECKED:BST_UNCHECKED);
|
|
CheckDlgButton(hwndDlg,130,(soundoptions&SO_MUTEFA)?BST_CHECKED:BST_UNCHECKED);
|
|
CheckDlgButton(hwndDlg,131,(soundoptions&SO_OLDUP)?BST_CHECKED:BST_UNCHECKED);
|
|
SendDlgItemMessage(hwndDlg,129,CB_SETCURSEL,soundquality,(LPARAM)(LPSTR)0);
|
|
t=0;
|
|
if(soundrate==22050) t=1;
|
|
else if(soundrate==44100) t=2;
|
|
else if(soundrate==48000) t=3;
|
|
else if(soundrate==96000) t=4;
|
|
SendDlgItemMessage(hwndDlg,200,CB_SETCURSEL,t,(LPARAM)(LPSTR)0);
|
|
}
|
|
|
|
BOOL CALLBACK SoundConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
|
|
switch(uMsg) {
|
|
case WM_NCRBUTTONDOWN:
|
|
case WM_NCMBUTTONDOWN:
|
|
case WM_NCLBUTTONDOWN:StopSound();break;
|
|
|
|
case WM_INITDIALOG:
|
|
/* Volume Trackbar */
|
|
SendDlgItemMessage(hwndDlg,500,TBM_SETRANGE,1,MAKELONG(0,150));
|
|
SendDlgItemMessage(hwndDlg,500,TBM_SETTICFREQ,25,0);
|
|
SendDlgItemMessage(hwndDlg,500,TBM_SETPOS,1,150-soundvolume);
|
|
|
|
/* buffer size time trackbar */
|
|
SendDlgItemMessage(hwndDlg,128,TBM_SETRANGE,1,MAKELONG(15,200));
|
|
SendDlgItemMessage(hwndDlg,128,TBM_SETTICFREQ,1,0);
|
|
SendDlgItemMessage(hwndDlg,128,TBM_SETPOS,1,soundbuftime);
|
|
|
|
{
|
|
char tbuf[8];
|
|
sprintf(tbuf,"%d",soundbuftime);
|
|
SetDlgItemText(hwndDlg,666,(LPTSTR)tbuf);
|
|
}
|
|
|
|
SendDlgItemMessage(hwndDlg,129,CB_ADDSTRING,0,(LPARAM)(LPSTR)"Low");
|
|
SendDlgItemMessage(hwndDlg,129,CB_ADDSTRING,0,(LPARAM)(LPSTR)"High");
|
|
SendDlgItemMessage(hwndDlg,129,CB_ADDSTRING,0,(LPARAM)(LPSTR)"Highest");
|
|
|
|
SendDlgItemMessage(hwndDlg,200,CB_ADDSTRING,0,(LPARAM)(LPSTR)"11025");
|
|
SendDlgItemMessage(hwndDlg,200,CB_ADDSTRING,0,(LPARAM)(LPSTR)"22050");
|
|
SendDlgItemMessage(hwndDlg,200,CB_ADDSTRING,0,(LPARAM)(LPSTR)"44100");
|
|
SendDlgItemMessage(hwndDlg,200,CB_ADDSTRING,0,(LPARAM)(LPSTR)"48000");
|
|
SendDlgItemMessage(hwndDlg,200,CB_ADDSTRING,0,(LPARAM)(LPSTR)"96000");
|
|
|
|
UpdateSD(hwndDlg);
|
|
break;
|
|
case WM_VSCROLL:
|
|
soundvolume=150-SendDlgItemMessage(hwndDlg,500,TBM_GETPOS,0,0);
|
|
FCEUI_SetSoundVolume(soundvolume);
|
|
break;
|
|
case WM_HSCROLL:
|
|
{
|
|
char tbuf[8];
|
|
soundbuftime=SendDlgItemMessage(hwndDlg,128,TBM_GETPOS,0,0);
|
|
sprintf(tbuf,"%d",soundbuftime);
|
|
SetDlgItemText(hwndDlg,666,(LPTSTR)tbuf);
|
|
BufHowMuch=(soundbuftime*soundrate/1000)<<bittage;
|
|
//soundbufsize=(soundbuftime*soundrate/1000);
|
|
}
|
|
break;
|
|
case WM_CLOSE:
|
|
case WM_QUIT: goto gornk;
|
|
case WM_COMMAND:
|
|
switch(HIWORD(wParam))
|
|
{
|
|
case CBN_SELENDOK:
|
|
switch(LOWORD(wParam))
|
|
{
|
|
case 200:
|
|
{
|
|
int tmp;
|
|
tmp=SendDlgItemMessage(hwndDlg,200,CB_GETCURSEL,0,(LPARAM)(LPSTR)0);
|
|
if(tmp==0) tmp=11025;
|
|
else if(tmp==1) tmp=22050;
|
|
else if(tmp==2) tmp=44100;
|
|
else if(tmp==3) tmp=48000;
|
|
else tmp=96000;
|
|
if(tmp!=soundrate)
|
|
{
|
|
soundrate=tmp;
|
|
if(soundrate<44100)
|
|
{
|
|
soundquality=0;
|
|
FCEUI_SetSoundQuality(0);
|
|
UpdateSD(hwndDlg);
|
|
}
|
|
if(soundo)
|
|
{
|
|
TrashSound();
|
|
soundo=InitSound();
|
|
UpdateSD(hwndDlg);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 129:
|
|
soundquality=SendDlgItemMessage(hwndDlg,129,CB_GETCURSEL,0,(LPARAM)(LPSTR)0);
|
|
if(soundrate<44100) soundquality=0;
|
|
FCEUI_SetSoundQuality(soundquality);
|
|
UpdateSD(hwndDlg);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case BN_CLICKED:
|
|
switch(LOWORD(wParam))
|
|
{
|
|
case 122:soundoptions^=SO_FORCE8BIT;
|
|
if(soundo)
|
|
{
|
|
TrashSound();
|
|
soundo=InitSound();
|
|
UpdateSD(hwndDlg);
|
|
}
|
|
break;
|
|
case 123:soundoptions^=SO_SECONDARY;
|
|
if(soundo)
|
|
{
|
|
TrashSound();
|
|
soundo=InitSound();
|
|
UpdateSD(hwndDlg);
|
|
}
|
|
break;
|
|
case 124:soundoptions^=SO_GFOCUS;
|
|
if(soundo)
|
|
{
|
|
TrashSound();
|
|
soundo=InitSound();
|
|
UpdateSD(hwndDlg);
|
|
}
|
|
break;
|
|
case 130:soundoptions^=SO_MUTEFA;
|
|
break;
|
|
case 131:soundoptions^=SO_OLDUP;
|
|
if(soundo)
|
|
{
|
|
TrashSound();
|
|
soundo=InitSound();
|
|
UpdateSD(hwndDlg);
|
|
}
|
|
break;
|
|
case 126:soundo=!soundo;
|
|
if(!soundo) TrashSound();
|
|
else soundo=InitSound();
|
|
UpdateSD(hwndDlg);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!(wParam>>16))
|
|
switch(wParam&0xFFFF)
|
|
{
|
|
case 1:
|
|
gornk:
|
|
DestroyWindow(hwndDlg);
|
|
uug=0;
|
|
break;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
void ConfigSound(void)
|
|
{
|
|
if(!uug)
|
|
uug=CreateDialog(fceu_hInstance,"SOUNDCONFIG",0,SoundConCallB);
|
|
else
|
|
SetFocus(uug);
|
|
}
|
|
|
|
|
|
void StopSound(void)
|
|
{
|
|
if(soundo)
|
|
{
|
|
VOID *LockPtr=0;
|
|
DWORD LockLen=0;
|
|
if(DS_OK == IDirectSoundBuffer_Lock(ppbufw,0,DSBufferSize,&LockPtr,&LockLen,0,0,0))
|
|
{
|
|
//FCEUD_PrintError("K");
|
|
if(bittage)
|
|
memset(LockPtr, 0, LockLen);
|
|
else
|
|
memset(LockPtr, 0x80, LockLen);
|
|
IDirectSoundBuffer_Unlock(ppbufw,LockPtr,LockLen,0,0);
|
|
}
|
|
|
|
//IDirectSoundBuffer_Stop(ppbufw);
|
|
}
|
|
}
|
|
|
|
void FCEUD_SoundToggle(void)
|
|
{
|
|
if(mute)
|
|
{
|
|
mute=0;
|
|
FCEU_DispMessage("Sound mute off.");
|
|
}
|
|
else
|
|
{
|
|
mute=1;
|
|
StopSound();
|
|
FCEU_DispMessage("Sound mute on.");
|
|
}
|
|
}
|
|
|
|
void FCEUD_SoundVolumeAdjust(int n)
|
|
{
|
|
switch(n)
|
|
{
|
|
case -1: soundvolume-=10; if(soundvolume<0) soundvolume=0; break;
|
|
case 0: soundvolume=100; break;
|
|
case 1: soundvolume+=10; if(soundvolume>150) soundvolume=150; break;
|
|
}
|
|
mute=0;
|
|
FCEUI_SetSoundVolume(soundvolume);
|
|
FCEU_DispMessage("Sound volume %d.", soundvolume);
|
|
}
|
|
|
|
#include "wave.cpp"
|