diff --git a/src/engine/platform/pcspkr.cpp b/src/engine/platform/pcspkr.cpp index e26ef64f1..3334b70bc 100644 --- a/src/engine/platform/pcspkr.cpp +++ b/src/engine/platform/pcspkr.cpp @@ -38,6 +38,57 @@ const char* regCheatSheetPCSpeaker[]={ NULL }; +void _pcSpeakerThread(void* inst) { + ((DivPlatformPCSpeaker*)inst)->pcSpeakerThread(); +} + +void DivPlatformPCSpeaker::pcSpeakerThread() { + std::unique_lock unique(realOutSelfLock); + int lastDelay=0; + RealQueueVal r(0,0); + printf("starting\n"); + while (!realOutQuit) { + realQueueLock.lock(); + if (realQueue.empty()) { + realQueueLock.unlock(); + realOutCond.wait(unique); + continue; + } else { + r=realQueue.front(); + realQueue.pop(); + } + realQueueLock.unlock(); +#ifdef __linux__ + static struct input_event ie; + int nextSleep=r.delay-lastDelay; + lastDelay=r.delay; + if (nextSleep>0) { + int totalSleep=1000000.0*((double)nextSleep/(double)rate); + //printf("sleeping %d\n",totalSleep); + usleep(totalSleep); + } + if (beepFD>=0) { + gettimeofday(&ie.time,NULL); + ie.type=EV_SND; + ie.code=SND_TONE; + if (r.val>0) { + ie.value=chipClock/r.val; + } else { + ie.value=0; + } + if (write(beepFD,&ie,sizeof(struct input_event))<0) { + perror("error while writing frequency!"); + } else { + //printf("writing freq: %d\n",r.val); + } + } else { + printf("not writing because fd is less than 0\n"); + } +#endif + } + printf("stopping\n"); +} + const char** DivPlatformPCSpeaker::getRegisterSheet() { return regCheatSheetPCSpeaker; } @@ -126,25 +177,11 @@ void DivPlatformPCSpeaker::acquire_piezo(short* bufL, short* bufR, size_t start, } } -void DivPlatformPCSpeaker::beepFreq(int freq) { -#ifdef __linux__ - static struct input_event ie; - if (beepFD>=0) { - gettimeofday(&ie.time,NULL); - ie.type=EV_SND; - ie.code=SND_TONE; - if (freq>0) { - ie.value=chipClock/freq; - } else { - ie.value=0; - } - if (write(beepFD,&ie,sizeof(struct input_event))<0) { - perror("error while writing frequency!"); - } else { - //printf("writing freq: %d\n",freq); - } - } -#endif +void DivPlatformPCSpeaker::beepFreq(int freq, int delay) { + realQueueLock.lock(); + realQueue.push(RealQueueVal(freq,delay)); + realQueueLock.unlock(); + realOutCond.notify_one(); } void DivPlatformPCSpeaker::acquire_real(short* bufL, short* bufR, size_t start, size_t len) { @@ -152,7 +189,7 @@ void DivPlatformPCSpeaker::acquire_real(short* bufL, short* bufR, size_t start, if (lastOn!=on || lastFreq!=freq) { lastOn=on; lastFreq=freq; - beepFreq((on && !isMuted[0])?freq:0); + beepFreq((on && !isMuted[0])?freq:0,start); } for (size_t i=start; i=0) close(beepFD); #endif + if (realOutThread!=NULL) { + realOutQuit=true; + realOutCond.notify_one(); + realOutThread->join(); + delete realOutThread; + } delete oscBuf; } diff --git a/src/engine/platform/pcspkr.h b/src/engine/platform/pcspkr.h index 155416bb8..397f6e0e5 100644 --- a/src/engine/platform/pcspkr.h +++ b/src/engine/platform/pcspkr.h @@ -22,6 +22,10 @@ #include "../dispatch.h" #include "../macroInt.h" +#include +#include +#include +#include class DivPlatformPCSpeaker: public DivDispatch { struct Channel { @@ -57,6 +61,19 @@ class DivPlatformPCSpeaker: public DivDispatch { }; Channel chan[1]; DivDispatchOscBuffer* oscBuf; + std::thread* realOutThread; + std::mutex realOutSelfLock; + std::condition_variable realOutCond; + bool realOutQuit; + struct RealQueueVal { + int delay; + unsigned short val; + RealQueueVal(int d, unsigned short v): + delay(d), + val(v) {} + }; + std::queue realQueue; + std::mutex realQueueLock; bool isMuted[1]; bool on, flip, lastOn; int pos, speakerType, beepFD; @@ -68,7 +85,7 @@ class DivPlatformPCSpeaker: public DivDispatch { friend void putDispatchChan(void*,int,int); - void beepFreq(int freq); + void beepFreq(int freq, int delay=0); void acquire_unfilt(short* bufL, short* bufR, size_t start, size_t len); void acquire_cone(short* bufL, short* bufR, size_t start, size_t len); @@ -76,6 +93,7 @@ class DivPlatformPCSpeaker: public DivDispatch { void acquire_real(short* bufL, short* bufR, size_t start, size_t len); public: + void pcSpeakerThread(); void acquire(short* bufL, short* bufR, size_t start, size_t len); int dispatch(DivCommand c); void* getChanState(int chan);