diff --git a/VBA.sln b/VBA.sln index 2e9c9bff..bc9d02eb 100644 --- a/VBA.sln +++ b/VBA.sln @@ -13,6 +13,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libpng", "libpng\libpng.vcp {34DC39BF-F93A-4573-85BF-789B90B63179} = {34DC39BF-F93A-4573-85BF-789B90B63179} EndProjectSection EndProject +Project("{4CAA2610-1955-4629-BDC1-8133FE0B2087}") = "profiler", "..\profiler\profiler.aqt", "{7260A190-9B72-4227-B01C-29E53BA53413}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 diff --git a/src/GBA.cpp b/src/GBA.cpp index 0b469aa0..45b03c41 100644 --- a/src/GBA.cpp +++ b/src/GBA.cpp @@ -3906,7 +3906,7 @@ void CPULoop(int ticks) // mute sound soundTicks -= clockTicks; if(soundTicks <= 0) { - soundTick(); + psoundTickfn(); soundTicks += SOUND_CLOCK_TICKS; } timerOverflow = 0; diff --git a/src/Sound.cpp b/src/Sound.cpp index 545d0a19..561f364c 100644 --- a/src/Sound.cpp +++ b/src/Sound.cpp @@ -115,7 +115,7 @@ int soundBufferLen = 1470; int soundBufferTotalLen = 14700; int soundQuality = 2; int soundInterpolation = 0; -int soundPaused = 1; +bool soundPaused = true; int soundPlay = 0; int soundTicks = soundQuality * USE_TICKS_AS; int SOUND_CLOCK_TICKS = soundQuality * USE_TICKS_AS; @@ -300,6 +300,103 @@ variable_desc soundSaveStructV2[] = { { NULL, 0 } }; + +// *** Begin snd_interp code + + +// and here is the implementation specific code, in a messier state than the stuff above + +extern bool timer0On; +extern int timer0Reload; +extern int timer0ClockReload; +extern bool timer1On; +extern int timer1Reload; +extern int timer1ClockReload; + +extern int SOUND_CLOCK_TICKS; +extern int soundInterpolation; + +inline double calc_rate(int timer) +{ + if (timer ? timer1On : timer0On) + { + return double(SOUND_CLOCK_TICKS) / + double((0x10000 - (timer ? timer1Reload : timer0Reload)) * + (timer ? timer1ClockReload : timer0ClockReload)); + } + else + { + return 1.; + } +} + +static foo_interpolate * interp[2]; + +class foo_interpolate_setup +{ +public: + foo_interpolate_setup() + { + for (int i = 0; i < 2; i++) + { + interp[i] = get_filter(0); + } + } + + ~foo_interpolate_setup() + { + for (int i = 0; i < 2; i++) + { + delete interp[i]; + } + } +}; + +static foo_interpolate_setup blah; + +static int interpolation = 0; + +void interp_switch(int which) +{ + for (int i = 0; i < 2; i++) + { + delete interp[i]; + interp[i] = get_filter(which); + } + + interpolation = which; +} + +void interp_reset(int ch) +{ + setSoundFn(); +#ifdef ENHANCED_RATE + interp[ch]->reset(); +#else + interp[ch]->reset(calc_rate(ch ? soundDSATimer : soundDSBTimer)); +#endif +} + + +inline void interp_push(int ch, int sample) +{ + interp[ch]->push(sample); +} + +#ifdef ENHANCED_RATE +inline int interp_pop(int ch, double rate) +{ + return interp[ch]->pop(rate); +#else +inline int interp_pop(int ch) +{ + return interp[ch]->pop(); +#endif +} + + +// *** End snd_interp code + static void soundEventGB(u32 address, u8 data) { if ( apu ) @@ -479,7 +576,7 @@ u8 soundRead(u32 address) case 0x9c: case 0x9e: soundEventGB(0xFF30 + (address & 14), data); - soundEventGB(0xFF31 + (address & 14), data >> 8); + soundEventGB(0xFF31 + (address & 14), 0); // data >> 8); break; } } @@ -540,7 +637,7 @@ void soundEvent(u32 address, u16 data) case 0x9a: case 0x9c: case 0x9e: - soundEventGB(0xFF30 + (address & 14), data); + soundEventGB(0xFF30 + (address & 14), data & 0xff); soundEventGB(0xFF31 + (address & 14), data >> 8); break; } @@ -562,9 +659,33 @@ void soundChannel4() { } -void soundDirectSoundA() +#include + + +inline void soundDirectSoundA() { - directBuffer[0][soundIndex] = interp_pop(0, calc_rate(soundDSATimer)); //soundDSAValue; +#ifdef ENHANCED_RATE + double cr = calc_rate(soundDSATimer); + static int cnt = 0; + static double lastcr = 0; + static FILE *fp = NULL; + + if (fp==NULL) + fp=fopen("C:\\cr.txt", "at"); + if (cr!=lastcr) + { + fprintf(fp, "%f %d\n", lastcr, cnt); + cnt=0; + lastcr=cr; + } + else + cnt++; + + directBuffer[0][soundIndex] = interp_pop(0, calc_rate(soundDSATimer)); //soundDSAValue; +#else + directBuffer[0][soundIndex] = interp_pop(0); //soundDSAValue; +#endif + } void soundDirectSoundATimer() @@ -592,9 +713,13 @@ void soundDirectSoundATimer() soundDSAValue = 0; } -void soundDirectSoundB() +inline void soundDirectSoundB() { - directBuffer[1][soundIndex] = interp_pop(1, calc_rate(soundDSBTimer)); //soundDSBValue; +#ifdef ENHANCED_RATE + directBuffer[1][soundIndex] = interp_pop(1, calc_rate(soundDSBTimer)); //soundDSBValue; +#else + directBuffer[1][soundIndex] = interp_pop(1); //soundDSBValue; +#endif } void soundDirectSoundBTimer() @@ -811,14 +936,31 @@ void soundMix() soundFinalWave[soundBufferIndex++] = res; } +// soundTick gets called a lot +// if we are operating normally +// call normalSoundTick to avoid +// all the comparison checks. + +void normalsoundTick() +{ + soundDirectSoundA(); + soundDirectSoundB(); + soundMix(); + soundIndex++; + + if(2*soundBufferIndex >= soundBufferLen) + { + systemWriteDataToSoundBuffer(); + soundIndex = 0; + soundBufferIndex = 0; + } +} + + void soundTick() { if(systemSoundOn) { if(soundMasterOn && !stopState) { - /*soundChannel1(); - soundChannel2(); - soundChannel3(); - soundChannel4();*/ soundDirectSoundA(); soundDirectSoundB(); soundMix(); @@ -833,6 +975,7 @@ void soundTick() if(systemSoundOn) { if(soundPaused) { soundResume(); + setSoundFn(); } systemWriteDataToSoundBuffer(); @@ -843,6 +986,41 @@ void soundTick() } } +void (*psoundTickfn)()=soundTick; + + +void setSoundFn() +{ + if (systemSoundOn && !soundPaused && soundMasterOn) + psoundTickfn = normalsoundTick; + else + psoundTickfn = soundTick; + + if (soundInterpolation != interpolation) + interp_switch(soundInterpolation); + +} + +void setsystemSoundOn(bool value) +{ + systemSoundOn = value; + setSoundFn(); +} + +void setsoundPaused(bool value) +{ + soundPaused = value; + setSoundFn(); +} + +void setsoundMasterOn(bool value) +{ + soundMasterOn = value; + setSoundFn(); +} + + + void soundShutdown() { systemSoundShutdown(); @@ -868,13 +1046,13 @@ void soundShutdown() void soundPause() { systemSoundPause(); - soundPaused = 1; + setsoundPaused(true); } void soundResume() { systemSoundResume(); - soundPaused = 0; + setsoundPaused(false); } void soundEnable(int channels) @@ -918,12 +1096,12 @@ void soundReset() { systemSoundReset(); - soundPaused = 1; + setsoundPaused(true); soundPlay = 0; SOUND_CLOCK_TICKS = soundQuality * USE_TICKS_AS; soundTicks = SOUND_CLOCK_TICKS; soundNextPosition = 0; - soundMasterOn = 1; + setsoundMasterOn(true); soundIndex = 0; soundBufferIndex = 0; soundLevel1 = 7; @@ -1099,7 +1277,7 @@ bool soundInit(bool gba) } } - soundPaused = true; + setsoundPaused(true); return true; } return false; diff --git a/src/Sound.h b/src/Sound.h index 4b541073..5a1ea3e2 100644 --- a/src/Sound.h +++ b/src/Sound.h @@ -47,7 +47,8 @@ #define FIFOB_L 0xa4 #define FIFOB_H 0xa6 -extern void soundTick(); +extern void setSoundFn(); +extern void (*psoundTickfn)(); extern void soundShutdown(); extern bool soundInit(bool gba=true); extern void soundPause(); @@ -62,6 +63,10 @@ extern void soundEvent(u32, u8); extern void soundEvent(u32, u16); extern void soundTimerOverflow(int); extern void soundSetQuality(int); +extern void setsystemSoundOn(bool value); +extern void setsoundPaused(bool value); +extern void setsoundMasterOn(bool value); + //extern int SOUND_TICKS; extern int SOUND_CLOCK_TICKS; @@ -69,8 +74,8 @@ extern u8 soundRead(u32); extern u16 soundRead16(u32); extern u32 soundRead32(u32); extern int soundTicks; -extern int soundPaused; extern bool soundOffFlag; +extern bool soundPaused; extern int soundQuality; extern int soundBufferLen; extern int soundBufferTotalLen; diff --git a/src/gb/gbSound.cpp b/src/gb/gbSound.cpp index 22f83150..4d018e44 100644 --- a/src/gb/gbSound.cpp +++ b/src/gb/gbSound.cpp @@ -43,7 +43,7 @@ extern u8 soundWavePattern[4][32]; extern int soundBufferLen; extern int soundBufferTotalLen; extern int soundQuality; -extern int soundPaused; +extern bool soundPaused; extern int soundPlay; extern int soundTicks; extern int SOUND_CLOCK_TICKS; diff --git a/src/snd_interp.cpp b/src/snd_interp.cpp index 17510980..193cb43c 100644 --- a/src/snd_interp.cpp +++ b/src/snd_interp.cpp @@ -202,14 +202,20 @@ public: foo_null() : sample(0) {} ~foo_null() {} +#ifdef ENHANCED_RATE void reset() {} +#endif void push(int psample) { sample = psample; } +#ifdef ENHANCED_RATE int pop(double rate) +#else + int pop() +#endif { return sample; } @@ -234,20 +240,33 @@ public: ~foo_linear() {} +#ifdef ENHANCED_RATE void reset() { +#else + void reset(double rate) + { + foo_interpolate::reset(rate); +#endif position = 0; samples.clear(); } + void push(int sample) { samples.push_back(sample); } +#ifdef ENHANCED_RATE int pop(double rate) { - int ret, lrate; + int lrate; +#else + int pop() + { +#endif + int ret; if (position > 0x7fff) { @@ -262,6 +281,7 @@ public: ret += smp(1) * position; ret >>= 15; +#ifdef ENHANCED_RATE // wahoo, takes care of drifting if (samples.size() > 2) { @@ -269,6 +289,10 @@ public: } lrate = (int)(32768. * rate); +#else + if (samples.size() > 2) + position+=1; +#endif position += lrate; return ret; @@ -308,9 +332,15 @@ public: samples.push_back(sample); } +#ifdef ENHANCED_RATE int pop(double rate) { - int ret, lrate; + int lrate; +#else + int pop() + { +#endif + int ret; if (position > 0x7fff) { @@ -338,10 +368,14 @@ public: // wahoo, takes care of drifting if (samples.size() > 8) { +#ifdef ENHANCED_RATE rate += (.5 / 32768.); } - lrate = (int)(32768. * rate); +#else + position+=1; + } +#endif position += lrate; return ret; @@ -367,8 +401,14 @@ public: ~foo_fir() {} +#ifdef ENHANCED_RATE void reset() { +#else + void reset(double rate) + { + foo_interpolate::reset(rate); +#endif position = 0; samples.clear(); } @@ -378,9 +418,15 @@ public: samples.push_back(sample); } +#ifdef ENHANCED_RATE int pop(double rate) { - int ret, lrate; + int lrate; +#else + int pop() + { +#endif + int ret; if (position > 0x7fff) { @@ -404,6 +450,7 @@ public: if (ret > 32767) ret = 32767; else if (ret < -32768) ret = -32768; +#ifdef ENHANCED_RATE // wahoo, takes care of drifting if (samples.size() > 16) { @@ -412,7 +459,12 @@ public: lrate = (int)(32768. * rate); position += lrate; +#else + if (samples.size() > 16) + position+=1; + position+=9929; +#endif return ret; } }; @@ -431,11 +483,22 @@ public: ~foo_libresample() { +#ifdef ENHANCED_RATE reset(); +#else + reset(1); +#endif + } +#ifdef ENHANCED_RATE void reset() { +#else + void reset(double rate) + { + foo_interpolate::reset(rate); +#endif samples.clear(); if (resampler) { @@ -449,10 +512,14 @@ public: samples.push_back(float(sample)); } +#ifdef ENHANCED_RATE int pop(double rate) { +#else + int pop() + { +#endif int ret; - if (!resampler) { resampler = resample_open(0, .25, 44100. / 4000.); @@ -469,8 +536,11 @@ public: in[used] = samples[used]; } +#ifdef ENHANCED_RATE returned = resample_process(resampler, 1. / rate, in, count, 0, &used, &out, 1); - +#else + returned = resample_process(resampler, lrate / 32767, in, count, 0, &used, &out, 1); +#endif if (used) { samples.erase(used); @@ -506,114 +576,3 @@ foo_interpolate * get_filter(int which) return new foo_libresample; } } - -// and here is the implementation specific code, in a messier state than the stuff above - -extern bool timer0On; -extern int timer0Reload; -extern int timer0ClockReload; -extern bool timer1On; -extern int timer1Reload; -extern int timer1ClockReload; - -extern int SOUND_CLOCK_TICKS; -extern int soundInterpolation; - -double calc_rate(int timer) -{ - if (timer ? timer1On : timer0On) - { - return double(SOUND_CLOCK_TICKS) / - double((0x10000 - (timer ? timer1Reload : timer0Reload)) * - (timer ? timer1ClockReload : timer0ClockReload)); - } - else - { - return 1.; - } -} - -static foo_interpolate * interp[2]; - -class foo_interpolate_setup -{ -public: - foo_interpolate_setup() - { - for (int i = 0; i < 2; i++) - { - interp[i] = get_filter(0); - } - } - - ~foo_interpolate_setup() - { - for (int i = 0; i < 2; i++) - { - delete interp[i]; - } - } -}; - -static foo_interpolate_setup blah; - -class critical_section -{ - CRITICAL_SECTION cs; - -public: - critical_section() { InitializeCriticalSection(&cs); } - ~critical_section() { DeleteCriticalSection(&cs); } - - void enter() { EnterCriticalSection(&cs); } - void leave() { LeaveCriticalSection(&cs); } -}; - -static critical_section interp_sync; -static int interpolation = 0; - -class scopelock -{ - critical_section * cs; - -public: - scopelock(critical_section & pcs) { cs = &pcs; cs->enter(); } - ~scopelock() { cs->leave(); } -}; - -void interp_switch(int which) -{ - scopelock sl(interp_sync); - - for (int i = 0; i < 2; i++) - { - delete interp[i]; - interp[i] = get_filter(which); - } - - interpolation = which; -} - -void interp_reset(int ch) -{ - scopelock sl(interp_sync); - if (soundInterpolation != interpolation) interp_switch(soundInterpolation); - - interp[ch]->reset(); -} - -void interp_push(int ch, int sample) -{ - scopelock sl(interp_sync); - if (soundInterpolation != interpolation) interp_switch(soundInterpolation); - - interp[ch]->push(sample); -} - -int interp_pop(int ch, double rate) -{ - scopelock sl(interp_sync); - if (soundInterpolation != interpolation) interp_switch(soundInterpolation); - - return interp[ch]->pop(rate); -} diff --git a/src/snd_interp.h b/src/snd_interp.h index 60e2a83b..96efcc75 100644 --- a/src/snd_interp.h +++ b/src/snd_interp.h @@ -2,6 +2,7 @@ #define __SND_INTERP_H__ // simple interface that could easily be recycled +#define ENHANCED_RATE class foo_interpolate { @@ -9,22 +10,36 @@ public: foo_interpolate() {} virtual ~foo_interpolate() {}; +#ifdef ENHANCED_RATE virtual void reset() = 0; +#else + long lrate; + + virtual void reset(double rate) + { + lrate = (int)(32768. * rate); + }; +#endif virtual void push(int sample) = 0; +#ifdef ENHANCED_RATE virtual int pop(double rate) = 0; +#else + virtual int pop() = 0; +#endif + }; -foo_interpolate * get_filter(int which); +extern foo_interpolate * get_filter(int which); +/* // complicated, synced interface, specific to this implementation double calc_rate(int timer); - void interp_switch(int which); void interp_reset(int ch); -void interp_push(int ch, int sample); -int interp_pop(int ch, double rate); +inline void interp_push(int ch, int sample); +inline int interp_pop(int ch, double rate); */ #endif \ No newline at end of file diff --git a/src/win32/DirectSound.cpp b/src/win32/DirectSound.cpp index b646db48..24f0fb15 100644 --- a/src/win32/DirectSound.cpp +++ b/src/win32/DirectSound.cpp @@ -242,8 +242,7 @@ bool DirectSound::init() return false; } - systemSoundOn = true; - + setsystemSoundOn(true); return true; } @@ -343,7 +342,7 @@ void DirectSound::write() } } } else { - soundPaused = 1; + setsoundPaused(true); } } // Obtain memory address of write block. This will be in two parts