PC Speaker: timing improvements

This commit is contained in:
tildearrow 2022-06-02 23:27:28 -05:00
parent 50bdbb784a
commit 37539157be
2 changed files with 44 additions and 18 deletions

View file

@ -28,6 +28,7 @@
#include <unistd.h> #include <unistd.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/kd.h> #include <linux/kd.h>
#include <time.h>
#endif #endif
#define PCSPKR_DIVIDER 4 #define PCSPKR_DIVIDER 4
@ -44,10 +45,7 @@ void _pcSpeakerThread(void* inst) {
void DivPlatformPCSpeaker::pcSpeakerThread() { void DivPlatformPCSpeaker::pcSpeakerThread() {
std::unique_lock<std::mutex> unique(realOutSelfLock); std::unique_lock<std::mutex> unique(realOutSelfLock);
#ifdef __linux__ RealQueueVal r(0,0,0);
int lastDelay=0;
#endif
RealQueueVal r(0,0);
printf("starting\n"); printf("starting\n");
while (!realOutQuit) { while (!realOutQuit) {
realQueueLock.lock(); realQueueLock.lock();
@ -62,15 +60,26 @@ void DivPlatformPCSpeaker::pcSpeakerThread() {
realQueueLock.unlock(); realQueueLock.unlock();
#ifdef __linux__ #ifdef __linux__
static struct input_event ie; static struct input_event ie;
int nextSleep=r.delay-lastDelay; static struct timespec ts, tSleep, rSleep;
lastDelay=r.delay; if (clock_gettime(CLOCK_MONOTONIC,&ts)<0) {
if (nextSleep>0) { printf("could not get time!\n");
int totalSleep=1000000.0*((double)nextSleep/(double)rate); tSleep.tv_sec=0;
//printf("sleeping %d\n",totalSleep); tSleep.tv_nsec=0;
usleep(totalSleep); } else {
tSleep.tv_sec=r.tv_sec-ts.tv_sec;
tSleep.tv_nsec=r.tv_nsec-ts.tv_nsec;
if (tSleep.tv_nsec<0) {
tSleep.tv_sec--;
tSleep.tv_nsec+=1000000000;
}
}
if (tSleep.tv_nsec>0 || tSleep.tv_sec>0) {
nanosleep(&tSleep,&rSleep);
} }
if (beepFD>=0) { if (beepFD>=0) {
gettimeofday(&ie.time,NULL); ie.time.tv_sec=r.tv_sec;
ie.time.tv_usec=r.tv_nsec/1000;
ie.type=EV_SND; ie.type=EV_SND;
ie.code=SND_TONE; ie.code=SND_TONE;
if (r.val>0) { if (r.val>0) {
@ -181,7 +190,23 @@ void DivPlatformPCSpeaker::acquire_piezo(short* bufL, short* bufR, size_t start,
void DivPlatformPCSpeaker::beepFreq(int freq, int delay) { void DivPlatformPCSpeaker::beepFreq(int freq, int delay) {
realQueueLock.lock(); realQueueLock.lock();
realQueue.push(RealQueueVal(delay,freq)); #ifdef __linux__
struct timespec ts;
double addition=1000000000.0*(double)delay/(double)rate;
if (clock_gettime(CLOCK_MONOTONIC,&ts)<0) {
ts.tv_sec=0;
ts.tv_nsec=0;
} else {
ts.tv_nsec+=addition;
while (ts.tv_nsec>=1000000000) {
ts.tv_sec++;
ts.tv_nsec-=1000000000;
}
}
realQueue.push(RealQueueVal(ts.tv_sec,ts.tv_nsec,freq));
#else
realQueue.push(RealQueueVal(0,0,freq));
#endif
realQueueLock.unlock(); realQueueLock.unlock();
realOutCond.notify_one(); realOutCond.notify_one();
} }
@ -495,15 +520,15 @@ void DivPlatformPCSpeaker::quit() {
if (speakerType==3) { if (speakerType==3) {
beepFreq(0); beepFreq(0);
} }
#ifdef __linux__
if (beepFD>=0) close(beepFD);
#endif
if (realOutThread!=NULL) { if (realOutThread!=NULL) {
realOutQuit=true; realOutQuit=true;
realOutCond.notify_one(); realOutCond.notify_one();
realOutThread->join(); realOutThread->join();
delete realOutThread; delete realOutThread;
} }
#ifdef __linux__
if (beepFD>=0) close(beepFD);
#endif
delete oscBuf; delete oscBuf;
} }

View file

@ -66,10 +66,11 @@ class DivPlatformPCSpeaker: public DivDispatch {
std::condition_variable realOutCond; std::condition_variable realOutCond;
bool realOutQuit; bool realOutQuit;
struct RealQueueVal { struct RealQueueVal {
int delay; int tv_sec, tv_nsec;
unsigned short val; unsigned short val;
RealQueueVal(int d, unsigned short v): RealQueueVal(int sec, int nsec, unsigned short v):
delay(d), tv_sec(sec),
tv_nsec(nsec),
val(v) {} val(v) {}
}; };
std::queue<RealQueueVal> realQueue; std::queue<RealQueueVal> realQueue;