improved windows sound and throttling. cleaned up lots of the mess. 8bit supported, although I dont know why you'd want to do that (it doesnt significantly cut down on processing time). Im halfway tempted to take out all the 8bit code and reimplement it buried very deep into the sound output driver as an uncontrollable panic toggle for obscure cases where 16bit isnt available.

This commit is contained in:
zeromus 2006-08-24 07:19:31 +00:00
parent ee82ccc638
commit 11e0d7ebcf
6 changed files with 165 additions and 729 deletions

View File

@ -6,23 +6,6 @@
#define LATENCY_MS (100)
int voltbl[] = {
-10000,-8750,-8018,-7499,-7097,-6768,-6490,-6250,-6037,-5847,-5675,-5518,-5374,-5240,-5116,-5000,
-4890,-4787,-4690,-4597,-4509,-4425,-4345,-4268,-4195,-4124,-4056,-3990,-3927,-3866,-3807,-3749,
-3694,-3640,-3588,-3537,-3488,-3440,-3393,-3347,-3303,-3259,-3217,-3175,-3135,-3095,-3056,-3018,
-2981,-2945,-2909,-2874,-2840,-2806,-2773,-2740,-2708,-2677,-2646,-2616,-2586,-2557,-2528,-2500,
-2472,-2444,-2417,-2390,-2364,-2338,-2312,-2287,-2262,-2238,-2213,-2190,-2166,-2143,-2120,-2097,
-2075,-2053,-2031,-2009,-1988,-1967,-1946,-1925,-1905,-1885,-1865,-1845,-1826,-1806,-1787,-1768,
-1750,-1731,-1713,-1695,-1677,-1659,-1641,-1624,-1607,-1590,-1573,-1556,-1539,-1523,-1506,-1490,
-1474,-1458,-1443,-1427,-1412,-1396,-1381,-1366,-1351,-1336,-1321,-1307,-1292,-1278,-1264,-1250,
-1235,-1222,-1208,-1194,-1180,-1167,-1153,-1140,-1127,-1114,-1101,-1088,-1075,-1062,-1050,-1037,
-1025,-1012,-1000,-988,-976,-963,-951,-940,-928,-916,-904,-893,-881,-870,-858,-847,
-836,-825,-814,-803,-792,-781,-770,-759,-748,-738,-727,-717,-706,-696,-685,-675,
-665,-655,-645,-635,-625,-615,-605,-595,-585,-576,-566,-556,-547,-537,-528,-518,
-509,-500,-490,-481,-472,-463,-454,-445,-436,-427,-418,-409,-400,-391,-383,-374,
-365,-357,-348,-340,-331,-323,-314,-306,-298,-289,-281,-273,-265,-256,-248,-240,
-232,-224,-216,-208,-200,-193,-185,-177,-169,-162,-154,-146,-139,-131,-123,-116,
-108,-101,-93,-86,-79,-71,-64,-57,-49,-42,-35,-28,-21,-14,-7,0};
class DSVoice : public OAKRA_Voice {
public:
@ -35,14 +18,10 @@ public:
int vol,pan;
virtual void setPan(int pan) {
this->pan = pan;
if(pan==0) ds_buf->SetPan(0);
else if(pan>0) ds_buf->SetPan(-voltbl[255-pan]);
else ds_buf->SetPan(voltbl[255+pan]);
//removed for FCEU
}
virtual void setVol(int vol) {
this->vol = vol;
ds_buf->SetVolume(voltbl[vol]);
//removed for FCEU
}
virtual int getVol() { return vol; }
virtual int getPan() { return pan; }
@ -75,7 +54,8 @@ public:
DSBUFFERDESC dsbd;
memset(&dsbd, 0, sizeof(dsbd));
dsbd.dwSize = sizeof(dsbd);
dsbd.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_LOCSOFTWARE | DSBCAPS_CTRLVOLUME ;
//commented out for FCEU
dsbd.dwFlags = DSBCAPS_GETCURRENTPOSITION2;// | DSBCAPS_LOCSOFTWARE | DSBCAPS_CTRLVOLUME ;
if(global) dsbd.dwFlags |= DSBCAPS_GLOBALFOCUS ;
dsbd.dwBufferBytes = buflen * format.size;
dsbd.lpwfxFormat = &wfx;

View File

@ -1828,7 +1828,7 @@ void MapInput(void)
void FCEUD_TurboOn(void)
{
//NoWaiting|=1;
turbo = 1;
turbo = true;
}
void FCEUD_TurboOff(void)

View File

@ -476,7 +476,6 @@ int main(int argc,char *argv[])
if(!DriverInitialize())
goto doexito;
InitSpeedThrottle();
UpdateMenu();
if(t)
@ -781,35 +780,27 @@ void _updateWindow() {
void FCEUD_Update(uint8 *XBuf, int32 *Buffer, int Count)
{
//mbg merge 7/19/06 - leaving this untouched but untested
/*int ocount = Count;
// apply frame scaling to Count
Count = (Count<<8)/temp_fps_scale;
//Disable sound and throttling for BotMode--we want max speed!
if(FCEU_BotMode())
{
if(XBuf && (skipcount >= 64))
//its probably not optimal
if(FCEU_BotMode()) {
//this counts the number of frames we've skipped blitting
static int skipcount = 0;
if(XBuf && (skipcount++ >= 64))
{
skipcount = 0;
FCEUD_BlitScreen(XBuf);
}
else
{
skipcount++;
}
UpdateFCEUWindow();
FCEUD_UpdateInput();
return;
}*/
}
extern bool turbo; //hack
win_SoundSetScale(fps_scale);
//write all the sound we generated.
if(soundo && Buffer && Count) {
void FCEUD_WriteSoundData_new(int32 *Buffer, int scale, int Count, bool turbo);
FCEUD_WriteSoundData_new(Buffer,fps_scale,Count,turbo);
//FCEUD_WriteSoundData(Buffer,fps_scale,Count);
win_SoundWriteData(Buffer,Count);
}
//blit the framebuffer
if(XBuf)
FCEUD_BlitScreen(XBuf);
@ -817,28 +808,20 @@ void FCEUD_Update(uint8 *XBuf, int32 *Buffer, int Count)
//update debugging displays
_updateWindow();
//throttle
bool skip = false;
for(;;) {
if(!(eoptions&EO_NOTHROTTLE)) //if throttling is enabled..
if(!turbo) //and turbo is disabled..
if(!FCEUI_EmulationPaused()) //and we're not paused..
//if(SpeedThrottle()) {//...then check whether we need to throttle
// //idle..
// Sleep(0);
// continue;
//}
{}
break;
}
extern bool turbo; //needs to be declared better
if(!(eoptions&EO_NOTHROTTLE)) //if throttling is enabled..
if(!turbo) //and turbo is disabled..
if(!FCEUI_EmulationPaused())
//then throttle
win_Throttle();
//delay until we unpause. we will only stick here if we're paused by a breakpoint or debug command
while(FCEUI_EmulationPaused() && inDebugger)
{
Sleep(50);
BlockingCheck();
FCEUD_UpdateInput(); //should this update the CONTROLS??? or only the hotkeys etc?
}
//something of a hack, but straightforward:

View File

@ -20,211 +20,8 @@
#include <list>
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);
}
///enqueues the given samples for playback
static void EnqueueSamples(void *data, uint32 len) {
}
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))
//printf("RawCanWrite(): %d\n",RawCanWrite());
//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;
@ -298,6 +95,14 @@ public:
return *(short*)((char*)liveBuffers[buffer]->data+ofs);
}
template <class ST>
ST getElementAtIndex(int addr) {
addr *= sizeof(ST); //shorts are 2bytes
int buffer = (addr+offset)>>BufferSizeBits;
int ofs = (addr+offset) & BufferSizeBitmask;
return *(ST*)((char*)liveBuffers[buffer]->data+ofs);
}
//dequeues the specified number of bytes
void dequeue(int length) {
offset += length;
@ -310,6 +115,20 @@ public:
this->length -= length;
}
//not being used now:
//tries to lock the specified number of bytes for reading.
//not all the bytes you asked for will be locked (no more than one buffer-full)
//try again if you didnt get enough.
//returns the number of bytes locked.
int lock(int length, void **ptr) {
int remain = BufferSize-offset;
*ptr = (char*)liveBuffers[0]->data + offset;
if(length<remain)
return length;
else
return remain;
}
void enqueue(int length, void *data) {
int todo = length;
@ -337,20 +156,57 @@ public:
};
class Player : public OAKRA_Module {
class PlayerBase : public OAKRA_Module {
public:
BufferSet buffers;
int cursor;
bool turbo;
int scale;
PlayerBase() {
scale = 256;
}
void receive(int bytes, void *buf) {
dsout->lock();
buffers.enqueue(bytes,buf);
buffers.decay(60);
dsout->unlock();
}
virtual int getSamplesInBuffer() = 0;
void throttle() {
//wait for the buffer to be satisfactorily low before continuing
for(;;) {
dsout->lock();
int remain = getSamplesInBuffer();
dsout->unlock();
if(remain<44100/60) break;
//if(remain<44100*scale/256/60) break; ??
Sleep(1);
}
}
void setScale(int scale) {
dsout->lock();
this->scale = scale;
dsout->unlock();
}
};
template <class ST,int SHIFT,int ZERO>
class Player : public PlayerBase {
public:
int cursor;
int getSamplesInBuffer() { return buffers.length>>SHIFT; }
//not interpolating! someday it will!
int generate(int samples, void *buf) {
int incr = 256;
int bufferSamples = buffers.length>>1;
int bufferSamples = buffers.length>>SHIFT;
//if we're we're too far behind, playback faster
if(bufferSamples > 44100*3/60) {
@ -366,369 +222,120 @@ public:
int destSamplesCanGenerate = (bufferSamples<<8) / incr;
int todo = std::min(destSamplesCanGenerate,samples);
short *sbuf = (short*)buf;
ST *sbuf = (ST*)buf;
for(int i=0;i<todo;i++) {
sbuf[i] = buffers.getShortAtIndex(cursor>>8);
sbuf[i] = buffers.getElementAtIndex<ST>(cursor>>8);
cursor += incr;
}
buffers.dequeue((cursor>>8)<<1);
buffers.dequeue((cursor>>8)<<SHIFT);
cursor &= 255;
memset(sbuf+todo,0,(samples-todo)<<1);
memset(sbuf+todo,ZERO,(samples-todo)<<SHIFT);
return samples;
}
Player() {
scale = 256;
cursor = 0;
turbo = false;
}
///receives and enqueues s16 stereo samples
void receive(int samples, short *buf, bool turbo, int scale) {
dsout->lock();
buffers.enqueue(samples*2,buf);
buffers.decay(60);
this->scale = scale;
dsout->unlock();
//throttle
// //wait for the buffer to be satisfactorily low before continuing
if(!turbo) {
for(;;) {
dsout->lock();
int remain = buffers.length>>1;
dsout->unlock();
if(remain<44100/60) break;
//if(remain<44100*scale/256/60) break; ??
Sleep(1);
}
}
}
};
Player *player;
class ShortPlayer : public Player<short,1,0> {};
class BytePlayer : public Player<unsigned char,0,0x80> {};
static ShortPlayer *shortPlayer;
static BytePlayer *bytePlayer;
static PlayerBase *player;
void win_Throttle() {
player->throttle();
}
void StopSound() {
//dont think this needs to do anything anymore
}
void sound_init_new() {
void win_SoundInit(int bits) {
dsout = new OAKRA_Module_OutputDS();
dsout->start(0);
dsout->start(hAppWnd);
dsout->beginThread();
OAKRA_Format fmt;
fmt.format = OAKRA_S16;
fmt.format = bits==8?OAKRA_U8:OAKRA_S16;
fmt.channels = 1;
fmt.rate = 44100;
fmt.size = 2;
fmt.size = OAKRA_Module::calcSize(fmt);
OAKRA_Voice *voice = dsout->getVoice(fmt);
player = new Player();
if(bits == 8)
player = bytePlayer = new BytePlayer();
else player = shortPlayer = new ShortPlayer();
dsout->lock();
voice->setSource(player);
dsout->unlock();
}
void FCEUD_WriteSoundData_new(int32 *Buffer, int scale, int Count, bool turbo) {
#define WSD_BUFSIZE (2 * 96000 / 50)
static int16 MBuffer[WSD_BUFSIZE*2];
for(int i=0;i<Count;i++)
MBuffer[i] = Buffer[i];
player->receive(Count,MBuffer,turbo,scale);
void TrashSound() {
delete dsout;
if(player) delete player;
player = 0;
}
int FCEUD_WriteSoundData(int32 *Buffer, int scale, int Count)
{
#define WSD_BUFSIZE (2 * 96000 / 50)
//HACK - aviout is expecting this
WAVEFORMATEX wf;
int bittage; //1 -> 8bit
static int bits;
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);
int amt = Count;
int cando = RawCanWrite();
printf("Count/cando %d/%d\n",amt,cando);
if(!bittage)
int InitSound() {
if(soundoptions&SO_FORCE8BIT)
bits = 8;
else {
//no modern system should have this problem, and we dont use primary buffer
/*if( (!(dscaps.dwFlags&DSCAPS_PRIMARY16BIT) && !(soundoptions&SO_SECONDARY)) ||
(!(dscaps.dwFlags&DSCAPS_SECONDARY16BIT) && (soundoptions&SO_SECONDARY)))
{
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,cando);
}
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,cando * 2);
}
iCount+=amt;
FCEUD_PrintError("DirectSound: 16-bit sound is not supported. Forcing 8-bit sound.");*/
bits = 16;
}
// FCEUI_AviSoundUpdate((void*)MBuffer, Count);
return iCount;
win_SoundInit(bits);
FCEUI_Sound(soundrate);
return 1;
// 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.");
}
/*
//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];
void win_SoundSetScale(int scale) {
player->scale = scale;
}
//if(!(soundoptions&SO_OLDUP))
//{
//shouldnt the sound be stopped?
//if(FCEUI_EmulationPaused())
// memset(MBuffer, 0, WSD_BUFSIZE); // slow and/or unnecessary
void win_SoundWriteData(int32 *buffer, int count) {
//todo..
// FCEUI_AviSoundUpdate((void*)MBuffer, Count);
//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);
switch(bits) {
case 16: {
void *tempbuf = alloca(2*count);
short *sbuf = (short *)tempbuf;
for(int i=0;i<count;i++)
sbuf[i] = buffer[i];
player->receive(count*2,tempbuf);
break;
}
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);
case 8: {
void *tempbuf = alloca(count);
unsigned char *bbuf = (unsigned char *)tempbuf;
for(int i=0;i<count;i++)
bbuf[i] = (buffer[i]>>8)^128;
player->receive(count,tempbuf);
}
iCount+=amt;
}
// FCEUI_AviSoundUpdate((void*)MBuffer, Count);
return iCount;
}
*/
int InitSound()
{
DSCAPS dscaps;
DSBCAPS dsbcaps;
sound_init_new();
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;
@ -798,7 +405,6 @@ BOOL CALLBACK SoundConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPara
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;
@ -914,27 +520,6 @@ void ConfigSound(void)
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)

View File

@ -36,129 +36,16 @@ static void RefreshThrottleFPS(void)
}
static uint64 GetCurTime(void)
{
if(tmethod)
{
uint64 tmp;
/* Practically, LARGE_INTEGER and uint64 differ only by signness and name. */
QueryPerformanceCounter((LARGE_INTEGER*)&tmp);
return(tmp);
}
else
return((uint64)GetTickCount());
}
static uint64 ttime,ltime;
static void InitSpeedThrottle(void)
{
//timeBeginPeriod(1);
//SetThreadAffinityMask(GetCurrentThread(),1);
//
//tmethod=0;
//if(QueryPerformanceFrequency((LARGE_INTEGER*)&tfreq)) {
// tmethod=1;
//}
//else tfreq=1000;
//tfreq<<=16; /* Adjustment for fps returned from FCEUI_GetDesiredFPS(). */
//ltime = 0; //mbg
}
///Resets the throttle timing. use this when the player releases the turbo
void ResetSpeedThrottle() {
ltime = 0;
}
static int SpeedThrottle(void)
{
//the desired running time for this frame
uint64 desiredRunningTime = tfreq/desiredfps;
ttime = GetCurTime();
//if this is our first time, save ltime and bail out
if(ltime == 0) {
ltime = ttime;
return 0;
}
//otherwise calculate our delta
uint64 delta = ttime-ltime;
/*printf("%20I64d %20I64d\n",delta,desiredRunningTime);
fflush(stdout);*/
if( delta < desiredRunningTime ) {
//if the elapsed time is less than the desired running time
//sleepy gets the time that needs to be slept.
//it is then converted to ms<<16
uint64 sleepy = desiredRunningTime-delta;
//sleepy *= 1000;
//if we have more than 1 ms to sleep, sleep 1 ms and return
if(sleepy>=65536) {
Sleep(1);
return 1;
} else {
//otherwise, we can't throttle for less than 1ms. assume we're close enough and return
ltime += desiredRunningTime;
return 0;
}
//sleepy*=1000;
//if(tfreq>=65536)
// sleepy/=tfreq>>16;
//else
// sleepy=0;
//if(sleepy>100)
//{
// // block for a max of 100ms to
// // keep the gui responsive
// Sleep(100);
// return 1;
//}
//Sleep(sleepy);
//goto waiter;
} else {
//we're behind...
if(delta > 2*desiredRunningTime) {
//if we're behind by 2 frames, then reset the throttling
ResetSpeedThrottle();
} else {
//we're only behind by part of a frame
//just don't throttle!
ltime += desiredRunningTime;
}
return 0;
}
//}
//if( (ttime-ltime) >= (tfreq*4/desiredfps))
// ltime=ttime;
//else
//{
// ltime+=tfreq/desiredfps;
// if( (ttime-ltime) >= (tfreq/desiredfps) ) // Oops, we're behind!
// return(1);
//}
//return(0);
}
//mbg todo - these were used by the FPS calculator in video/cpp
// Quick code for internal FPS display.
uint64 FCEUD_GetTime(void)
{
return(GetCurTime());
}
uint64 FCEUD_GetTimeFreq(void)
{
return(tfreq>>16);
}
//uint64 FCEUD_GetTime(void)
//{
// return(GetCurTime()); //this was using queryperformancecounter yuck
//}
//uint64 FCEUD_GetTimeFreq(void)
//{
// return(tfreq>>16);
//}
static void IncreaseEmulationSpeed(void)
{

View File

@ -473,6 +473,7 @@ int SaveSnapshot(void)
fclose(pp);
return(0);
}
//TODO mbg - this needs to be implemented in a better way
#ifdef SHOWFPS
uint64 FCEUD_GetTime(void);
uint64 FCEUD_GetTimeFreq(void);