mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-10-30 20:40:28 -04:00 
			
		
		
		
	git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/map65@2548 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
		
			
				
	
	
		
			142 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			142 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "soundout.h"
 | |
| 
 | |
| #define FRAMES_PER_BUFFER 256
 | |
| 
 | |
| extern "C" {
 | |
| #include <portaudio.h>
 | |
| }
 | |
| 
 | |
| extern float gran();                  //Noise generator (for tests only)
 | |
| 
 | |
| extern short int iwave[60*11025];     //Wave file for Tx audio
 | |
| extern int nwave;
 | |
| extern bool btxok;
 | |
| extern double outputLatency;
 | |
| 
 | |
| typedef struct   //Parameters sent to or received from callback function
 | |
| {
 | |
|   int nTRperiod;
 | |
| } paUserData;
 | |
| 
 | |
| //--------------------------------------------------------------- d2aCallback
 | |
| extern "C" int d2aCallback(const void *inputBuffer, void *outputBuffer,
 | |
|                            unsigned long framesToProcess,
 | |
|                            const PaStreamCallbackTimeInfo* timeInfo,
 | |
|                            PaStreamCallbackFlags statusFlags,
 | |
|                            void *userData )
 | |
| {
 | |
|   paUserData *udata=(paUserData*)userData;
 | |
|   short *wptr = (short*)outputBuffer;
 | |
|   unsigned int i,n;
 | |
|   static int ic=0;
 | |
|   static bool btxok0=false;
 | |
|   static int nStart=0;
 | |
|   double tsec,tstart;
 | |
|   int nsec;
 | |
|   int nTRperiod=udata->nTRperiod;
 | |
| 
 | |
|   // Get System time
 | |
|   qint64 ms = QDateTime::currentMSecsSinceEpoch() % 86400000;
 | |
|   tsec = 0.001*ms;
 | |
|   nsec = ms/1000;
 | |
| 
 | |
|   if(btxok and !btxok0) {       //Start (or re-start) a transmission
 | |
|     n=nsec/nTRperiod;
 | |
|     tstart=tsec - n*nTRperiod - 1.0;
 | |
| 
 | |
|     if(tstart<1.0) {
 | |
|       ic=0;                      //Start of Tx cycle, set starting index to 0
 | |
|       nStart=n;
 | |
|     } else {
 | |
|       if(n != nStart) { //Late start in new Tx cycle: compute starting index
 | |
|         ic=(int)(tstart*11025.0);
 | |
|         nStart=n;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   btxok0=btxok;
 | |
| 
 | |
|   if(btxok) {
 | |
|     for(i=0 ; i<framesToProcess; i++ )  {
 | |
|       short int i2=iwave[ic];
 | |
|       if(ic > nwave) i2=0;
 | |
| //      i2 = 500.0*(i2/32767.0 + 5.0*gran());      //Add noise (tests only!)
 | |
|       if(!btxok) i2=0;
 | |
|       *wptr++ = i2;                   //left
 | |
|       *wptr++ = i2;                   //right
 | |
|       ic++;
 | |
|     }
 | |
|   } else {
 | |
|     for(i=0 ; i<framesToProcess; i++ )  {
 | |
|       *wptr++ = 0;
 | |
|       *wptr++ = 0;
 | |
|       ic++;
 | |
|     }
 | |
|   }
 | |
|   if(ic > nwave) {
 | |
|     btxok=0;
 | |
|     ic=0;
 | |
|   }
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| void SoundOutThread::run()
 | |
| {
 | |
|   PaError paerr;
 | |
|   PaStreamParameters outParam;
 | |
|   PaStream *outStream;
 | |
|   paUserData udata;
 | |
|   quitExecution = false;
 | |
| 
 | |
|   outParam.device=m_nDevOut;                 //Output device number
 | |
|   outParam.channelCount=2;                   //Number of analog channels
 | |
|   outParam.sampleFormat=paInt16;             //Send short ints to PortAudio
 | |
|   outParam.suggestedLatency=0.05;
 | |
|   outParam.hostApiSpecificStreamInfo=NULL;
 | |
| 
 | |
|   udata.nTRperiod=m_TRperiod;
 | |
|   paerr=Pa_IsFormatSupported(NULL,&outParam,11025.0);
 | |
|   if(paerr<0) {
 | |
|     qDebug() << "PortAudio says requested output format not supported.";
 | |
|     qDebug() << paerr;
 | |
|     return;
 | |
|   }
 | |
|   paerr=Pa_OpenStream(&outStream,           //Output stream
 | |
|         NULL,                               //No input parameters
 | |
|         &outParam,                          //Output parameters
 | |
|         11025.0,                            //Sample rate
 | |
|         FRAMES_PER_BUFFER,                  //Frames per buffer
 | |
|         paClipOff,                          //No clipping
 | |
|         d2aCallback,                        //output callbeck routine
 | |
|         &udata);                            //userdata
 | |
| 
 | |
|   paerr=Pa_StartStream(outStream);
 | |
|   if(paerr<0) {
 | |
|     qDebug() << "Failed to start audio output stream.";
 | |
|     return;
 | |
|   }
 | |
|   const PaStreamInfo* p=Pa_GetStreamInfo(outStream);
 | |
|   outputLatency = p->outputLatency;
 | |
|   bool qe = quitExecution;
 | |
| 
 | |
| //---------------------------------------------- Soundcard output loop
 | |
|   while (!qe) {
 | |
|     qe = quitExecution;
 | |
|     if (qe) break;
 | |
|     msleep(100);
 | |
|   }
 | |
|   Pa_StopStream(outStream);
 | |
|   Pa_CloseStream(outStream);
 | |
| }
 | |
| 
 | |
| void SoundOutThread::setOutputDevice(int n)      //setOutputDevice()
 | |
| {
 | |
|   if (isRunning()) return;
 | |
|   this->m_nDevOut=n;
 | |
| }
 | |
| 
 | |
| void SoundOutThread::setPeriod(int n)
 | |
| {
 | |
|   m_TRperiod=n;
 | |
| }
 |