mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-15 16:42:12 -05:00
4e8a3f54c9
the main GUI thread (thanks to G4WJS). 2.. Also, for the record, some example code for using QAudioInput instead of PortAudio. This code is not presently active, and will need to be changed to accommodate the changes in #1, above. But the basic ideas are here... git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@3509 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
211 lines
5.4 KiB
C++
211 lines
5.4 KiB
C++
#include "soundin.h"
|
|
#include <stdexcept>
|
|
|
|
#define FRAMES_PER_BUFFER 1024
|
|
//#define NSMAX 1365
|
|
#define NSMAX 6827
|
|
#define NTMAX 120
|
|
|
|
extern "C" {
|
|
#include <portaudio.h>
|
|
extern struct {
|
|
float ss[184*NSMAX]; //This is "common/jt9com/..." in fortran
|
|
float savg[NSMAX];
|
|
// float c0[2*NTMAX*1500];
|
|
short int d2[NTMAX*12000];
|
|
int nutc; //UTC as integer, HHMM
|
|
int ndiskdat; //1 ==> data read from *.wav file
|
|
int ntrperiod; //TR period (seconds)
|
|
int mousefqso; //User-selected QSO freq (kHz)
|
|
int newdat; //1 ==> new data, must do long FFT
|
|
int npts8; //npts in c0() array
|
|
int nfa; //Low decode limit (Hz)
|
|
int nfb; //High decode limit (Hz)
|
|
int ntol; //+/- decoding range around fQSO (Hz)
|
|
int kin;
|
|
int nzhsym;
|
|
int nsave;
|
|
int nagain;
|
|
int ndepth;
|
|
int ntxmode;
|
|
int nmode;
|
|
char datetime[20];
|
|
} jt9com_;
|
|
}
|
|
|
|
QString reportAudioError(QAudio::Error audioError)
|
|
{
|
|
switch (audioError) {
|
|
case QAudio::NoError: Q_ASSERT(false);
|
|
case QAudio::OpenError: return QObject::tr(
|
|
"An error opening the audio device has occurred.");
|
|
case QAudio::IOError: return QObject::tr(
|
|
"An error occurred during read/write of audio device.");
|
|
case QAudio::UnderrunError: return QObject::tr(
|
|
"Audio data not being fed to the audio device fast enough.");
|
|
case QAudio::FatalError: return QObject::tr(
|
|
"Non-recoverable error, audio device not usable at this time.");
|
|
}
|
|
Q_ASSERT(false);
|
|
return "";
|
|
}
|
|
|
|
typedef struct
|
|
{
|
|
int kin; //Parameters sent to/from the portaudio callback function
|
|
int ncall;
|
|
bool bzero;
|
|
bool monitoring;
|
|
} paUserData;
|
|
|
|
|
|
void SoundInThread::run() //SoundInThread::run()
|
|
{
|
|
quitExecution = false;
|
|
|
|
//---------------------------------------------------- Soundcard Setup
|
|
|
|
quitExecutionMutex.lock();
|
|
quitExecution = false;
|
|
quitExecutionMutex.unlock();
|
|
|
|
//### Temporary: hardwired device selection
|
|
QAudioDeviceInfo DeviceInfo;
|
|
QList<QAudioDeviceInfo> m_InDevices;
|
|
QAudioDeviceInfo m_InDeviceInfo;
|
|
m_InDevices = DeviceInfo.availableDevices(QAudio::AudioInput);
|
|
inputDevice = m_InDevices.at(0);
|
|
//###
|
|
|
|
const char* pcmCodec = "audio/pcm";
|
|
QAudioFormat audioFormat = inputDevice.preferredFormat();
|
|
audioFormat.setChannelCount(1);
|
|
audioFormat.setCodec(pcmCodec);
|
|
audioFormat.setSampleRate(12000);
|
|
audioFormat.setSampleType(QAudioFormat::SignedInt);
|
|
audioFormat.setSampleSize(16);
|
|
|
|
if (!audioFormat.isValid()) {
|
|
emit error(tr("Requested audio format is not available."));
|
|
return;
|
|
}
|
|
|
|
QAudioInput audioInput(inputDevice, audioFormat);
|
|
if (audioInput.error() != QAudio::NoError) {
|
|
emit error(reportAudioError(audioInput.error()));
|
|
return;
|
|
}
|
|
|
|
QIODevice* stream = audioInput.start();
|
|
|
|
bool qe = quitExecution;
|
|
static int ntr0=99;
|
|
int k=0;
|
|
int nsec;
|
|
int ntr;
|
|
int nBusy=0;
|
|
int nstep0=0;
|
|
int nsps0=0;
|
|
qint16 buf0[4096];
|
|
|
|
//---------------------------------------------- Soundcard input loop
|
|
while (!qe) {
|
|
quitExecutionMutex.lock();
|
|
qe = quitExecution;
|
|
quitExecutionMutex.unlock();
|
|
if (qe) break;
|
|
|
|
// Error checking...
|
|
if (audioInput.error() != QAudio::NoError) {
|
|
emit error(reportAudioError(audioInput.error()));
|
|
return;
|
|
}
|
|
|
|
// udata.monitoring=m_monitoring;
|
|
qint64 ms = QDateTime::currentMSecsSinceEpoch();
|
|
ms=ms % 86400000;
|
|
nsec = ms/1000; // Time according to this computer
|
|
ntr = nsec % m_TRperiod;
|
|
|
|
// Reset buffer pointer and symbol number at start of minute
|
|
if(ntr < ntr0 or !m_monitoring or m_nsps!=nsps0) {
|
|
nstep0=0;
|
|
nsps0=m_nsps;
|
|
// udata.bzero=true;
|
|
k=0;
|
|
}
|
|
// k=udata.kin;
|
|
|
|
// How many new samples have been acquired?
|
|
const qint32 bytesReady = audioInput.bytesReady();
|
|
Q_ASSERT(bytesReady >= 0);
|
|
Q_ASSERT(bytesReady % 2 == 0);
|
|
if (bytesReady == 0) {
|
|
msleep(50);
|
|
continue;
|
|
}
|
|
|
|
// Get the new samples
|
|
qint32 bytesRead;
|
|
bytesRead = stream->read((char*)buf0, bytesReady);
|
|
Q_ASSERT(bytesRead <= bytesReady);
|
|
if (bytesRead < 0) {
|
|
emit error(tr("audio stream QIODevice::read returned -1."));
|
|
return;
|
|
}
|
|
Q_ASSERT(bytesRead % 2 == 0);
|
|
|
|
// memcpy(jt9com_.d2[k],buf0,bytesRead);
|
|
// k+=bytesRead/2;
|
|
|
|
for(int i=0; i<bytesRead/2; i++) {
|
|
jt9com_.d2[k++]=buf0[i];
|
|
}
|
|
|
|
if(m_monitoring) {
|
|
int kstep=m_nsps/2;
|
|
m_step=(k-1)/kstep;
|
|
if(m_step != nstep0) {
|
|
if(m_dataSinkBusy) {
|
|
nBusy++;
|
|
} else {
|
|
emit readyForFFT(k-1); //Signal to compute new FFTs
|
|
}
|
|
nstep0=m_step;
|
|
}
|
|
}
|
|
msleep(100);
|
|
ntr0=ntr;
|
|
}
|
|
// Pa_StopStream(inStream);
|
|
// Pa_CloseStream(inStream);
|
|
}
|
|
|
|
void SoundInThread::setInputDevice(int n) //setInputDevice()
|
|
{
|
|
if (isRunning()) return;
|
|
this->m_nDevIn=n;
|
|
}
|
|
|
|
void SoundInThread::quit() //quit()
|
|
{
|
|
quitExecution = true;
|
|
}
|
|
|
|
void SoundInThread::setMonitoring(bool b) //setMonitoring()
|
|
{
|
|
m_monitoring = b;
|
|
}
|
|
|
|
void SoundInThread::setPeriod(int ntrperiod, int nsps)
|
|
{
|
|
m_TRperiod=ntrperiod;
|
|
m_nsps=nsps;
|
|
}
|
|
|
|
int SoundInThread::mstep()
|
|
{
|
|
return m_step;
|
|
}
|
|
|