From 5902173ae07fd5ddc942d3c2c124f350392f283c Mon Sep 17 00:00:00 2001 From: nitsuja Date: Thu, 5 Nov 2009 07:45:31 +0000 Subject: [PATCH] fix for sound sometimes looping endlessly if you pause and bring up a menu or dialog, possible fix for an occasional crash when changing synchronizer mode, fix for sound.clear not actually working, fix for screen gap settings messing up certain alternate LCD layout calculations (I thought I already checked this in) --- desmume/src/SPU.cpp | 19 ++++++---- desmume/src/SPU.h | 2 + desmume/src/lua-engine.cpp | 9 ++--- desmume/src/windows/main.cpp | 5 ++- desmume/src/windows/snddx.cpp | 70 ++++++++++++++++++++++++++--------- desmume/src/windows/video.h | 8 ++-- 6 files changed, 77 insertions(+), 36 deletions(-) diff --git a/desmume/src/SPU.cpp b/desmume/src/SPU.cpp index 6d2afd818..3ee28884f 100644 --- a/desmume/src/SPU.cpp +++ b/desmume/src/SPU.cpp @@ -225,10 +225,17 @@ void SPU_SetSynchMode(int mode, int method) synchmethod = (ESynchMethod)method; delete synchronizer; //grr does this need to be locked? spu might need a lock method + // or maybe not, maybe the platform-specific code that calls this function can deal with it. synchronizer = metaspu_construct(synchmethod); } } +void SPU_ClearOutputBuffer() +{ + if(SNDCore && SNDCore->ClearBuffer) + SNDCore->ClearBuffer(); +} + void SPU_SetVolume(int volume) { ::volume = volume; @@ -896,17 +903,13 @@ void SPU_Emulate_user(bool mix) if (audiosize > SPU_user->bufsize) audiosize = SPU_user->bufsize; + int samplesOutput; if(synchmode == ESynchMode_Synchronous) - { - int done = synchronizer->output_samples(SPU_user->outbuf, audiosize); - SNDCore->UpdateAudio(SPU_user->outbuf,done); - } + samplesOutput = synchronizer->output_samples(SPU_user->outbuf, audiosize); else - { - SPU_MixAudio(mix,SPU_user,audiosize); - SNDCore->UpdateAudio(SPU_user->outbuf, audiosize); - } + samplesOutput = (SPU_MixAudio(mix,SPU_user,audiosize), audiosize); + SNDCore->UpdateAudio(SPU_user->outbuf, samplesOutput); } } diff --git a/desmume/src/SPU.h b/desmume/src/SPU.h index 6d5803f70..252ff53fc 100644 --- a/desmume/src/SPU.h +++ b/desmume/src/SPU.h @@ -62,6 +62,7 @@ struct SoundInterface_struct void (*MuteAudio)(); void (*UnMuteAudio)(); void (*SetVolume)(int volume); + void (*ClearBuffer)(); }; extern SoundInterface_struct SNDDummy; @@ -132,6 +133,7 @@ int SPU_Init(int coreid, int buffersize); void SPU_Pause(int pause); void SPU_SetVolume(int volume); void SPU_SetSynchMode(int mode, int method); +void SPU_ClearOutputBuffer(void); void SPU_Reset(void); void SPU_DeInit(void); void SPU_KeyOn(int channel); diff --git a/desmume/src/lua-engine.cpp b/desmume/src/lua-engine.cpp index d9146d895..8a7860a0e 100644 --- a/desmume/src/lua-engine.cpp +++ b/desmume/src/lua-engine.cpp @@ -18,11 +18,8 @@ #endif -// a few functions that maybe aren't part of the Lua engine +// functions that maybe aren't part of the Lua engine // but didn't make sense to add to BaseDriver (at least not yet) -static void Clear_Sound_Buffer() { - if(SPU_user) SPU_user->ShutUp(); -} static bool IsHardwareAddressValid(u32 address) { // maybe TODO? let's say everything is valid. return true; @@ -1402,7 +1399,7 @@ void LuaRescueHook(lua_State* L, lua_Debug *dbg) bool stopworrying = true; if(!info.panic) { - Clear_Sound_Buffer(); + SPU_ClearOutputBuffer(); #if defined(ASK_USER_ON_FREEZE) && defined(_WIN32) DialogsOpen++; int answer = MessageBox(HWnd, "A Lua script has been running for quite a while. Maybe it is in an infinite loop.\n\nWould you like to stop the script?\n\n(Yes to stop it now,\n No to keep running and not ask again,\n Cancel to keep running but ask again later)", "Lua Alert", MB_YESNOCANCEL | MB_DEFBUTTON3 | MB_ICONASTERISK); @@ -3464,7 +3461,7 @@ DEFINE_LUA_FUNCTION(movie_close, "") DEFINE_LUA_FUNCTION(sound_clear, "") { - Clear_Sound_Buffer(); + SPU_ClearOutputBuffer(); return 0; } diff --git a/desmume/src/windows/main.cpp b/desmume/src/windows/main.cpp index a5112039c..3ff13e390 100644 --- a/desmume/src/windows/main.cpp +++ b/desmume/src/windows/main.cpp @@ -5422,7 +5422,10 @@ static LRESULT CALLBACK SoundSettingsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam if(IsDlgCheckboxChecked(hDlg,IDC_SYNCHMETHOD_P)) snd_synchmethod = 2; WritePrivateProfileInt("Sound", "SynchMethod", snd_synchmethod, IniName); - SPU_SetSynchMode(snd_synchmode, snd_synchmethod); + { + Lock lock; + SPU_SetSynchMode(snd_synchmode, snd_synchmethod); + } //write interpolation type CommonSettings.spuInterpolationMode = (SPUInterpolationMode)SendDlgItemMessage(hDlg, IDC_SPU_INTERPOLATION_CB, CB_GETCURSEL, 0, 0); diff --git a/desmume/src/windows/snddx.cpp b/desmume/src/windows/snddx.cpp index ac71a19d4..8bfd35771 100755 --- a/desmume/src/windows/snddx.cpp +++ b/desmume/src/windows/snddx.cpp @@ -44,6 +44,7 @@ u32 SNDDXGetAudioSpace(); void SNDDXMuteAudio(); void SNDDXUnMuteAudio(); void SNDDXSetVolume(int volume); +void SNDDXClearAudioBuffer(); SoundInterface_struct SNDDIRECTX = { SNDCORE_DIRECTX, @@ -54,7 +55,8 @@ SoundInterface_struct SNDDIRECTX = { SNDDXGetAudioSpace, SNDDXMuteAudio, SNDDXUnMuteAudio, - SNDDXSetVolume + SNDDXSetVolume, + SNDDXClearAudioBuffer, }; LPDIRECTSOUND8 lpDS8; @@ -67,6 +69,8 @@ static u32 soundoffset=0; static u32 soundbufsize; static LONG soundvolume; static int issoundmuted; +static bool insilence; +static int samplecounter_fakecontribution = 0; ////////////////////////////////////////////////////////////////////////////// static volatile bool doterminate; @@ -234,18 +238,44 @@ void SNDDXDeInit() void SNDDXUpdateAudio(s16 *buffer, u32 num_samples) { - LPVOID buffer1; - LPVOID buffer2; - DWORD buffer1_size, buffer2_size; - int samplecounter; { Lock lock; - samplecounter = win_sound_samplecounter -= num_samples; + if(num_samples) + { + samplecounter = win_sound_samplecounter -= num_samples - samplecounter_fakecontribution; + samplecounter_fakecontribution = 0; + } + else + { + samplecounter = win_sound_samplecounter -= 245; + samplecounter_fakecontribution += 245; + } } bool silence = (samplecounter<-44100*15/60); //behind by more than a quarter second -> silence + if(insilence) + { + if(silence) + return; + else + insilence = false; + } + else + { + if(silence) + { + insilence = true; + SNDDXClearAudioBuffer(); + return; + } + } + + LPVOID buffer1; + LPVOID buffer2; + DWORD buffer1_size, buffer2_size; + HRESULT hr = lpDSB2->Lock(soundoffset, num_samples * sizeof(s16) * 2, &buffer1, &buffer1_size, &buffer2, &buffer2_size, 0); if(FAILED(hr)) @@ -255,17 +285,9 @@ void SNDDXUpdateAudio(s16 *buffer, u32 num_samples) return; } - if(silence) { - memset(buffer1, 0, buffer1_size); - if(buffer2) - memset(buffer2, 0, buffer2_size); - } - else - { - memcpy(buffer1, buffer, buffer1_size); - if(buffer2) - memcpy(buffer2, ((u8 *)buffer)+buffer1_size, buffer2_size); - } + memcpy(buffer1, buffer, buffer1_size); + if(buffer2) + memcpy(buffer2, ((u8 *)buffer)+buffer1_size, buffer2_size); soundoffset += buffer1_size + buffer2_size; soundoffset %= soundbufsize; @@ -274,6 +296,20 @@ void SNDDXUpdateAudio(s16 *buffer, u32 num_samples) } + +void SNDDXClearAudioBuffer() +{ + LPVOID buffer1; + DWORD buffer1_size; + HRESULT hr = lpDSB2->Lock(0, 0, &buffer1, &buffer1_size, NULL, NULL, DSBLOCK_ENTIREBUFFER); + if(FAILED(hr)) + return; + memset(buffer1, 0, buffer1_size); + lpDSB2->Unlock(buffer1, buffer1_size, NULL, 0); +} + + + ////////////////////////////////////////////////////////////////////////////// static inline u32 circularDist(u32 from, u32 to, u32 size) diff --git a/desmume/src/windows/video.h b/desmume/src/windows/video.h index f1965e00c..e9ba283bf 100644 --- a/desmume/src/windows/video.h +++ b/desmume/src/windows/video.h @@ -158,11 +158,11 @@ public: case 0: return width; case 90: - return height + screengap; + return height + ((layout == 0) ? screengap : 0); case 180: return width; case 270: - return height + screengap; + return height + ((layout == 0) ? screengap : 0); default: return 0; } @@ -171,11 +171,11 @@ public: int rotatedheightgap() { switch(rotation) { case 0: - return height + screengap; + return height + ((layout == 0) ? screengap : 0); case 90: return width; case 180: - return height + screengap; + return height + ((layout == 0) ? screengap : 0); case 270: return width; default: