PC Speaker: timing improvements
This commit is contained in:
		
							parent
							
								
									50bdbb784a
								
							
						
					
					
						commit
						37539157be
					
				| 
						 | 
					@ -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;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue