Rearranged sequencing of audio streams and devices.

The code  was starting streams linked  to closed devices which  may be
causing issues on  the Mac version.  I have refactored  to ensure that
devices are always opened before related audio streams are started.

Made .h C++ headers emacs friendly.

Removed some code in the MainWindow  contructor that read the log file
but failed to check if the file exists and didn't do anything with the
data anyway.

git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@3977 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
Bill Somerville 2014-04-03 19:29:13 +00:00
parent 542c85d8f6
commit 581691befb
23 changed files with 566 additions and 566 deletions

View File

@ -13,11 +13,11 @@ namespace
} static_initializer;
}
bool AudioDevice::open (OpenMode mode, Channel channel)
bool AudioDevice::initialize (OpenMode mode, Channel channel)
{
m_channel = channel;
// ensure we are unbuffered
// open and ensure we are unbuffered if possible
return QIODevice::open (mode | QIODevice::Unbuffered);
}

View File

@ -24,7 +24,7 @@ public:
return "both" == s ? Both : "right" == s ? Right : "left" == s ? Left : Mono;
}
bool open (OpenMode mode, Channel channel);
bool initialize (OpenMode mode, Channel channel);
bool isSequential () const {return true;}

View File

@ -7,7 +7,7 @@
#include "moc_Detector.cpp"
extern "C" {
void fil4_(qint16*, qint32*, qint16*, qint32*);
void fil4_(qint16*, qint32*, qint16*, qint32*);
}
Detector::Detector (unsigned frameRate, unsigned periodLengthInSeconds,
@ -21,7 +21,7 @@ Detector::Detector (unsigned frameRate, unsigned periodLengthInSeconds,
, m_monitoring (false)
, m_starting (false)
, m_buffer ((downSampleFactor > 1) ?
new short [framesPerSignal * downSampleFactor] : 0)
new short [framesPerSignal * downSampleFactor] : 0)
, m_bufferPos (0)
{
clear ();
@ -50,76 +50,76 @@ qint64 Detector::writeData (char const * data, qint64 maxSize)
if (m_monitoring) {
// no torn frames
Q_ASSERT (!(maxSize % static_cast<qint64> (bytesPerFrame ())));
// these are in terms of input frames (not down sampled)
size_t framesAcceptable ((sizeof (jt9com_.d2) /
sizeof (jt9com_.d2[0]) - jt9com_.kin) * m_downSampleFactor);
size_t framesAccepted (qMin (static_cast<size_t> (maxSize /
bytesPerFrame ()), framesAcceptable));
// these are in terms of input frames (not down sampled)
size_t framesAcceptable ((sizeof (jt9com_.d2) /
sizeof (jt9com_.d2[0]) - jt9com_.kin) * m_downSampleFactor);
size_t framesAccepted (qMin (static_cast<size_t> (maxSize /
bytesPerFrame ()), framesAcceptable));
if (framesAccepted < static_cast<size_t> (maxSize / bytesPerFrame ())) {
qDebug () << "dropped " << maxSize / bytesPerFrame () - framesAccepted
<< " frames of data on the floor!";
}
if (framesAccepted < static_cast<size_t> (maxSize / bytesPerFrame ())) {
qDebug () << "dropped " << maxSize / bytesPerFrame () - framesAccepted
<< " frames of data on the floor!";
}
for (unsigned remaining = framesAccepted; remaining; ) {
size_t numFramesProcessed (qMin (m_framesPerSignal *
m_downSampleFactor - m_bufferPos, remaining));
for (unsigned remaining = framesAccepted; remaining; ) {
size_t numFramesProcessed (qMin (m_framesPerSignal *
m_downSampleFactor - m_bufferPos, remaining));
if(m_downSampleFactor > 1) {
store (&data[(framesAccepted - remaining) * bytesPerFrame ()],
numFramesProcessed, &m_buffer[m_bufferPos]);
m_bufferPos += numFramesProcessed;
if(m_bufferPos==m_framesPerSignal*m_downSampleFactor && m_monitoring) {
qint32 framesToProcess (m_framesPerSignal * m_downSampleFactor);
qint32 framesAfterDownSample;
if(framesToProcess==13824 and jt9com_.kin>=0 and jt9com_.kin<1440000) {
fil4_(&m_buffer[0], &framesToProcess, &jt9com_.d2[jt9com_.kin],
&framesAfterDownSample);
jt9com_.kin += framesAfterDownSample;
} else {
qDebug() << "framesToProcess = " << framesToProcess;
qDebug() << "jt9com_.kin = " << jt9com_.kin;
qDebug() << "secondInPeriod = " << secondInPeriod();
if(m_downSampleFactor > 1) {
store (&data[(framesAccepted - remaining) * bytesPerFrame ()],
numFramesProcessed, &m_buffer[m_bufferPos]);
m_bufferPos += numFramesProcessed;
if(m_bufferPos==m_framesPerSignal*m_downSampleFactor && m_monitoring) {
qint32 framesToProcess (m_framesPerSignal * m_downSampleFactor);
qint32 framesAfterDownSample;
if(framesToProcess==13824 and jt9com_.kin>=0 and jt9com_.kin<1440000) {
fil4_(&m_buffer[0], &framesToProcess, &jt9com_.d2[jt9com_.kin],
&framesAfterDownSample);
jt9com_.kin += framesAfterDownSample;
} else {
qDebug() << "framesToProcess = " << framesToProcess;
qDebug() << "jt9com_.kin = " << jt9com_.kin;
qDebug() << "secondInPeriod = " << secondInPeriod();
}
Q_EMIT framesWritten (jt9com_.kin);
m_bufferPos = 0;
}
} else {
store (&data[(framesAccepted - remaining) * bytesPerFrame ()],
numFramesProcessed, &jt9com_.d2[jt9com_.kin]);
m_bufferPos += numFramesProcessed;
jt9com_.kin += numFramesProcessed;
if (m_bufferPos == static_cast<unsigned> (m_framesPerSignal) &&
m_monitoring) {
Q_EMIT framesWritten (jt9com_.kin);
m_bufferPos = 0;
}
Q_EMIT framesWritten (jt9com_.kin);
m_bufferPos = 0;
}
} else {
store (&data[(framesAccepted - remaining) * bytesPerFrame ()],
numFramesProcessed, &jt9com_.d2[jt9com_.kin]);
m_bufferPos += numFramesProcessed;
jt9com_.kin += numFramesProcessed;
if (m_bufferPos == static_cast<unsigned> (m_framesPerSignal) &&
m_monitoring) {
Q_EMIT framesWritten (jt9com_.kin);
m_bufferPos = 0;
if (!secondInPeriod ()) {
if (!m_starting) {
// next samples will be in new period so wrap around to
// start of buffer
//
// we don't bother calling reset () since we expect to fill
// the whole buffer and don't need to waste cycles zeroing
jt9com_.kin = 0;
m_bufferPos = 0;
m_starting = true;
}
} else if(m_starting) {
m_starting = false;
}
remaining -= numFramesProcessed;
}
if (!secondInPeriod ()) {
if (!m_starting) {
// next samples will be in new period so wrap around to
// start of buffer
//
// we don't bother calling reset () since we expect to fill
// the whole buffer and don't need to waste cycles zeroing
jt9com_.kin = 0;
m_bufferPos = 0;
m_starting = true;
}
} else if(m_starting) {
m_starting = false;
}
remaining -= numFramesProcessed;
} else {
jt9com_.kin = 0;
m_bufferPos = 0;
}
} else {
jt9com_.kin = 0;
m_bufferPos = 0;
}
return maxSize; // we drop any data past the end of the buffer on
// the floor until the next period starts
return maxSize; // we drop any data past the end of the buffer on
// the floor until the next period starts
}
unsigned Detector::secondInPeriod () const

View File

@ -30,6 +30,11 @@ public:
bool isMonitoring () const {return m_monitoring;}
Q_SLOT void setMonitoring (bool newState) {m_monitoring = newState; m_bufferPos = 0;}
Q_SLOT bool reset ();
Q_SIGNAL void framesWritten (qint64) const;
protected:
qint64 readData (char * /* data */, qint64 /* maxSize */)
{
@ -39,14 +44,6 @@ protected:
qint64 writeData (char const * data, qint64 maxSize);
private:
// these are private because we want thread safety, must be called via Qt queued connections
Q_SLOT void open (AudioDevice::Channel channel = Mono) {AudioDevice::open (QIODevice::WriteOnly, channel);}
Q_SLOT void setMonitoring (bool newState) {m_monitoring = newState; m_bufferPos = 0;}
Q_SLOT bool reset ();
Q_SLOT void close () {AudioDevice::close ();}
Q_SIGNAL void framesWritten (qint64) const;
void clear (); // discard buffer contents
unsigned secondInPeriod () const;
@ -57,10 +54,10 @@ private:
bool volatile m_monitoring;
bool m_starting;
QScopedArrayPointer<short> m_buffer; // de-interleaved sample buffer
// big enough for all the
// samples for one increment of
// data (a signals worth) at
// the input sample rate
// big enough for all the
// samples for one increment of
// data (a signals worth) at
// the input sample rate
unsigned m_bufferPos;
};

View File

@ -24,27 +24,31 @@ double const Modulator::m_twoPi = 2.0 * 3.141592653589793238462;
// m_nspd=3072; //18.75 WPM
unsigned const Modulator::m_nspd = 2048 + 512; // 22.5 WPM
Modulator::Modulator (unsigned frameRate, unsigned periodLengthInSeconds, \
QObject * parent)
: AudioDevice (parent)
, m_phi (0.0)
, m_framesSent (0)
, m_frameRate (frameRate)
, m_period (periodLengthInSeconds)
, m_state (Idle)
, m_tuning (false)
, m_muted (false)
Modulator::Modulator (unsigned frameRate, unsigned periodLengthInSeconds, QObject * parent)
: AudioDevice {parent}
, m_stream {nullptr}
, m_phi {0.0}
, m_framesSent {0}
, m_frameRate {frameRate}
, m_period {periodLengthInSeconds}
, m_state {Idle}
, m_tuning {false}
, m_muted {false}
{
qsrand (QDateTime::currentMSecsSinceEpoch()); // Initialize random seed
}
void Modulator::open (unsigned symbolsLength, double framesPerSymbol, \
unsigned frequency, Channel channel, bool synchronize, double dBSNR)
void Modulator::start (unsigned symbolsLength, double framesPerSymbol, unsigned frequency, QAudioOutput * stream, Channel channel, bool synchronize, double dBSNR)
{
// Time according to this computer which becomes our base time
qint64 ms0 = QDateTime::currentMSecsSinceEpoch() % 86400000;
// qDebug () << "Modulator: Using soft keying for CW is " << SOFT_KEYING;;
if (m_state != Idle)
{
stop ();
}
// qDebug () << "Modulator: Using soft keying for CW is " << SOFT_KEYING;;
m_symbolsLength = symbolsLength;
m_framesSent = 0;
@ -63,7 +67,7 @@ void Modulator::open (unsigned symbolsLength, double framesPerSymbol, \
unsigned mstr = ms0 % (1000 * m_period); // ms in period
m_ic = (mstr / 1000) * m_frameRate; // we start exactly N seconds
// into period where N is the next whole second
// into period where N is the next whole second
m_silentFrames = 0;
// calculate number of silent frames to send
@ -71,11 +75,38 @@ void Modulator::open (unsigned symbolsLength, double framesPerSymbol, \
m_silentFrames = m_ic + m_frameRate - (mstr * m_frameRate / 1000);
}
// qDebug () << "Modulator: starting at " << m_ic / m_frameRate << " sec, sending " << m_silentFrames << " silent frames";
// qDebug () << "Modulator: starting at " << m_ic / m_frameRate << " sec, sending " << m_silentFrames << " silent frames";
AudioDevice::open (QIODevice::ReadOnly, channel);
initialize (QIODevice::ReadOnly, channel);
Q_EMIT stateChanged ((m_state = (synchronize && m_silentFrames) ?
Synchronizing : Active));
Synchronizing : Active));
m_stream = stream;
if (m_stream)
{
m_stream->start (this);
}
}
void Modulator::stop ()
{
if (m_stream)
{
m_stream->reset ();
}
close ();
}
void Modulator::close ()
{
if (m_stream)
{
m_stream->stop ();
}
if (m_state != Idle)
{
Q_EMIT stateChanged ((m_state = Idle));
}
AudioDevice::close ();
}
qint64 Modulator::readData (char * data, qint64 maxSize)
@ -92,141 +123,143 @@ qint64 Modulator::readData (char * data, qint64 maxSize)
qint16 * samples (reinterpret_cast<qint16 *> (data));
qint16 * end (samples + numFrames * (bytesPerFrame () / sizeof (qint16)));
// qDebug () << "Modulator: " << numFrames << " requested, m_ic = " << m_ic << ", tune mode is " << m_tuning;
// qDebug() << "C" << maxSize << numFrames << bytesPerFrame();
// qDebug () << "Modulator: " << numFrames << " requested, m_ic = " << m_ic << ", tune mode is " << m_tuning;
// qDebug() << "C" << maxSize << numFrames << bytesPerFrame();
switch (m_state)
{
case Synchronizing:
{
if (m_silentFrames) { // send silence up to first second
numFrames = qMin (m_silentFrames, numFrames);
for ( ; samples != end; samples = load (0, samples)) { // silence
}
m_silentFrames -= numFrames;
return numFrames * bytesPerFrame ();
}
{
case Synchronizing:
{
if (m_silentFrames) { // send silence up to first second
numFrames = qMin (m_silentFrames, numFrames);
for ( ; samples != end; samples = load (0, samples)) { // silence
}
m_silentFrames -= numFrames;
return numFrames * bytesPerFrame ();
}
Q_EMIT stateChanged ((m_state = Active));
m_ramp = 0; // prepare for CW wave shaping
}
Q_EMIT stateChanged ((m_state = Active));
m_ramp = 0; // prepare for CW wave shaping
}
// fall through
case Active:
{
unsigned isym (m_tuning ? 0 : m_ic / (4.0 * m_nsps)); // Actual fsample=48000
if (isym >= m_symbolsLength && icw[0] > 0) { // start CW condition
// Output the CW ID
m_dphi = m_twoPi * m_frequency / m_frameRate;
unsigned const ic0 = m_symbolsLength * 4 * m_nsps;
unsigned j (0);
qint64 framesGenerated (0);
case Active:
{
unsigned isym (m_tuning ? 0 : m_ic / (4.0 * m_nsps)); // Actual fsample=48000
if (isym >= m_symbolsLength && icw[0] > 0) { // start CW condition
// Output the CW ID
m_dphi = m_twoPi * m_frequency / m_frameRate;
unsigned const ic0 = m_symbolsLength * 4 * m_nsps;
unsigned j (0);
qint64 framesGenerated (0);
while (samples != end) {
m_phi += m_dphi;
if (m_phi > m_twoPi) m_phi -= m_twoPi;
while (samples != end) {
m_phi += m_dphi;
if (m_phi > m_twoPi) m_phi -= m_twoPi;
qint16 sample ((SOFT_KEYING ? qAbs (m_ramp - 1) :
(m_ramp ? 32767 : 0)) * qSin (m_phi));
qint16 sample ((SOFT_KEYING ? qAbs (m_ramp - 1) :
(m_ramp ? 32767 : 0)) * qSin (m_phi));
j = (m_ic - ic0 - 1) / m_nspd + 1;
bool l0 (icw[j] && icw[j] <= 1); // first element treated specially as it's a count
j = (m_ic - ic0) / m_nspd + 1;
j = (m_ic - ic0 - 1) / m_nspd + 1;
bool l0 (icw[j] && icw[j] <= 1); // first element treated specially as it's a count
j = (m_ic - ic0) / m_nspd + 1;
if ((m_ramp != 0 && m_ramp != std::numeric_limits<qint16>::min ()) ||
!!icw[j] != l0) {
if (!!icw[j] != l0) {
Q_ASSERT (m_ramp == 0 || m_ramp == std::numeric_limits<qint16>::min ());
if ((m_ramp != 0 && m_ramp != std::numeric_limits<qint16>::min ()) ||
!!icw[j] != l0) {
if (!!icw[j] != l0) {
Q_ASSERT (m_ramp == 0 || m_ramp == std::numeric_limits<qint16>::min ());
}
m_ramp += RAMP_INCREMENT; // ramp
}
if (j < NUM_CW_SYMBOLS) { // stop condition
// if (!m_ramp && !icw[j])
// {
// sample = 0;
// }
samples = load (postProcessSample (sample), samples);
++framesGenerated;
++m_ic;
}
}
m_ramp += RAMP_INCREMENT; // ramp
if (j > static_cast<unsigned> (icw[0]))
{
close ();
}
m_framesSent += framesGenerated;
return framesGenerated * bytesPerFrame ();
}
if (j < NUM_CW_SYMBOLS) { // stop condition
// if (!m_ramp && !icw[j])
// {
// sample = 0;
// }
double const baud (12000.0 / m_nsps);
// fade out parameters (no fade out for tuning)
unsigned const i0 = m_tuning ? 999 * m_nsps :
(m_symbolsLength - 0.017) * 4.0 * m_nsps;
unsigned const i1 = m_tuning ? 999 * m_nsps :
m_symbolsLength * 4.0 * m_nsps;
samples = load (postProcessSample (sample), samples);
++framesGenerated;
for (unsigned i = 0; i < numFrames; ++i) {
isym = m_tuning ? 0 : m_ic / (4.0 * m_nsps); //Actual fsample=48000
if (isym != m_isym0) {
if(m_toneSpacing==0.0) {
toneFrequency0=m_frequency + itone[isym]*baud;
} else {
toneFrequency0=m_frequency + itone[isym]*m_toneSpacing;
}
m_dphi = m_twoPi * toneFrequency0 / m_frameRate;
m_isym0 = isym;
}
int j=m_ic/480;
if(m_fSpread>0.0 and j!=j0) {
float x1=(float)rand()/RAND_MAX;
float x2=(float)rand()/RAND_MAX;
toneFrequency = toneFrequency0 + 0.5*m_fSpread*(x1+x2-1.0);
m_dphi = m_twoPi * toneFrequency / m_frameRate;
j0=j;
}
m_phi += m_dphi;
if (m_phi > m_twoPi) m_phi -= m_twoPi;
if (m_ic > i0) m_amp = 0.98 * m_amp;
if (m_ic > i1) m_amp = 0.0;
samples = load (postProcessSample (m_amp * qSin (m_phi)), samples);
++m_ic;
}
}
if (j > static_cast<unsigned> (icw[0])) {
Q_EMIT stateChanged ((m_state = Idle));
}
if (m_amp == 0.0) { // TODO G4WJS: compare double with zero might not be wise
if (icw[0] == 0) {
// no CW ID to send
Q_EMIT stateChanged ((m_state = Idle));
m_framesSent += numFrames;
return numFrames * bytesPerFrame ();
}
m_framesSent += framesGenerated;
return framesGenerated * bytesPerFrame ();
}
double const baud (12000.0 / m_nsps);
// fade out parameters (no fade out for tuning)
unsigned const i0 = m_tuning ? 999 * m_nsps :
(m_symbolsLength - 0.017) * 4.0 * m_nsps;
unsigned const i1 = m_tuning ? 999 * m_nsps :
m_symbolsLength * 4.0 * m_nsps;
for (unsigned i = 0; i < numFrames; ++i) {
isym = m_tuning ? 0 : m_ic / (4.0 * m_nsps); //Actual fsample=48000
if (isym != m_isym0) {
if(m_toneSpacing==0.0) {
toneFrequency0=m_frequency + itone[isym]*baud;
} else {
toneFrequency0=m_frequency + itone[isym]*m_toneSpacing;
m_phi = 0.0;
}
m_dphi = m_twoPi * toneFrequency0 / m_frameRate;
m_isym0 = isym;
}
int j=m_ic/480;
if(m_fSpread>0.0 and j!=j0) {
float x1=(float)rand()/RAND_MAX;
float x2=(float)rand()/RAND_MAX;
toneFrequency = toneFrequency0 + 0.5*m_fSpread*(x1+x2-1.0);
m_dphi = m_twoPi * toneFrequency / m_frameRate;
j0=j;
}
m_phi += m_dphi;
if (m_phi > m_twoPi) m_phi -= m_twoPi;
if (m_ic > i0) m_amp = 0.98 * m_amp;
if (m_ic > i1) m_amp = 0.0;
samples = load (postProcessSample (m_amp * qSin (m_phi)), samples);
++m_ic;
}
if (m_amp == 0.0) { // TODO G4WJS: compare double with zero might not be wise
if (icw[0] == 0) {
// no CW ID to send
Q_EMIT stateChanged ((m_state = Idle));
// done for this chunk - continue on next call
m_framesSent += numFrames;
return numFrames * bytesPerFrame ();
}
// fall through
m_phi = 0.0;
case Idle:
break;
}
// done for this chunk - continue on next call
m_framesSent += numFrames;
return numFrames * bytesPerFrame ();
}
Q_EMIT stateChanged ((m_state = Idle));
// fall through
case Idle:
break;
}
Q_ASSERT (Idle == m_state);
close ();
return 0;
}
qint16 Modulator::postProcessSample (qint16 sample) const
{
if (m_muted) { // silent frame
sample = 0;
sample = 0;
} else if (m_addNoise) { // Test frame, we'll add noise
qint32 s = m_fac * (gran () + sample * m_snr / 32768.0);
if (s > std::numeric_limits<qint16>::max ()) {

View File

@ -3,11 +3,7 @@
#include "AudioDevice.hpp"
#ifdef UNIX
# define NUM_CHANNELS 2
#else
# define NUM_CHANNELS 1
#endif
class QAudioOutput;
//
// Input device that generates PCM audio frames that encode a message
@ -16,20 +12,17 @@
// Output can be muted while underway, preserving waveform timing when
// transmission is resumed.
//
class Modulator : public AudioDevice
class Modulator
: public AudioDevice
{
Q_OBJECT;
Q_PROPERTY (unsigned frequency READ frequency WRITE setFrequency);
Q_PROPERTY (bool tuning READ isTuning WRITE tune);
Q_PROPERTY (bool muted READ isMuted WRITE mute);
public:
enum ModulatorState {Synchronizing, Active, Idle};
Modulator (unsigned frameRate, unsigned periodLengthInSeconds, QObject * parent = 0);
Modulator (unsigned frameRate, unsigned periodLengthInSeconds, QObject * parent = nullptr);
Q_SLOT void open (unsigned symbolsLength, double framesPerSymbol, unsigned frequency, AudioDevice::Channel, bool synchronize = true, double dBSNR = 99.);
void close () override;
bool isTuning () const {return m_tuning;}
bool isMuted () const {return m_muted;}
@ -37,6 +30,13 @@ public:
bool isActive () const {return m_state != Idle;}
void setWide9(double d1, double d2) {m_toneSpacing=d1; m_fSpread=d2;}
Q_SLOT void start (unsigned symbolsLength, double framesPerSymbol, unsigned frequency, QAudioOutput *, Channel = Mono, bool synchronize = true, double dBSNR = 99.);
Q_SLOT void stop ();
Q_SLOT void tune (bool newState = true) {m_tuning = newState;}
Q_SLOT void mute (bool newState = true) {m_muted = newState;}
Q_SLOT void setFrequency (unsigned newFrequency) {m_frequency = newFrequency;}
Q_SIGNAL void stateChanged (ModulatorState) const;
protected:
qint64 readData (char * data, qint64 maxSize);
qint64 writeData (char const * /* data */, qint64 /* maxSize */)
@ -44,24 +44,11 @@ protected:
return -1; // we don't consume data
}
private:
/* private because we epect to run in a thread and don't want direct
C++ calls made, instead they must be invoked via the Qt
signal/slot mechanism which is thread safe */
Q_SLOT void close ()
{
Q_EMIT stateChanged ((m_state = Idle));
AudioDevice::close ();
}
Q_SLOT void tune (bool newState = true) {m_tuning = newState;}
Q_SLOT void mute (bool newState = true) {m_muted = newState;}
Q_SLOT void setFrequency (unsigned newFrequency) {m_frequency = newFrequency;}
Q_SIGNAL void stateChanged (ModulatorState) const;
private:
qint16 postProcessSample (qint16 sample) const;
QAudioOutput * m_stream;
unsigned m_symbolsLength;
static double const m_twoPi;
@ -80,8 +67,8 @@ private:
qint64 m_silentFrames;
qint64 m_framesSent;
int m_frameRate;
int m_period;
unsigned m_frameRate;
unsigned m_period;
ModulatorState volatile m_state;
bool volatile m_tuning;

View File

@ -1,3 +1,4 @@
// -*- Mode: C++ -*-
#ifndef ABOUTDLG_H
#define ABOUTDLG_H

View File

@ -1,3 +1,4 @@
// -*- Mode: C++ -*-
/*
* Class to handle the formatted string as returned from the fortran decoder
*

View File

@ -1,3 +1,4 @@
// -*- Mode: C++ -*-
#ifndef DISPLAYTEXT_H
#define DISPLAYTEXT_H

View File

@ -1,3 +1,4 @@
// -*- Mode: C++ -*-
#ifndef GETFILE_H
#define GETFILE_H
#include <QString>

View File

@ -1,3 +1,4 @@
// -*- Mode: C++ -*-
#ifndef LogQSO_H
#define LogQSO_H

View File

@ -36,7 +36,6 @@ int icw[NUM_CW_SYMBOLS]; //Dits for CW ID
int outBufSize;
int rc;
qint32 g_COMportOpen;
qint32 g_iptt;
static int nc1=1;
wchar_t buffer[256];
@ -134,37 +133,30 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
connect (m_audioThread, &QThread::finished, m_audioThread, &QThread::deleteLater); // disposal
// hook up sound output stream slots & signals
connect (this, SIGNAL (startAudioOutputStream (QAudioDeviceInfo const&, unsigned, unsigned)), &m_soundOutput, SLOT (startStream (QAudioDeviceInfo const&, unsigned, unsigned)));
connect (this, SIGNAL (stopAudioOutputStream ()), &m_soundOutput, SLOT (stopStream ()));
connect (this, &MainWindow::initializeAudioOutputStream, &m_soundOutput, &SoundOutput::setFormat);
connect (&m_soundOutput, &SoundOutput::error, this, &MainWindow::showSoundOutError);
// connect (&m_soundOutput, &SoundOutput::status, this, &MainWindow::showStatusMessage);
connect (this, SIGNAL (outAttenuationChanged (qreal)), &m_soundOutput, SLOT (setAttenuation (qreal)));
connect (this, &MainWindow::outAttenuationChanged, &m_soundOutput, &SoundOutput::setAttenuation);
// hook up Modulator slots
connect (this, SIGNAL (muteAudioOutput (bool)), &m_modulator, SLOT (mute (bool)));
connect (this, SIGNAL(transmitFrequency (unsigned)), &m_modulator, SLOT (setFrequency (unsigned)));
connect (this, SIGNAL (endTransmitMessage ()), &m_modulator, SLOT (close ()));
connect (this, SIGNAL (tune (bool)), &m_modulator, SLOT (tune (bool)));
connect (this, SIGNAL (sendMessage (unsigned, double, unsigned, AudioDevice::Channel, bool, double))
, &m_modulator, SLOT (open (unsigned, double, unsigned, AudioDevice::Channel, bool, double)));
connect (this, &MainWindow::muteAudioOutput, &m_modulator, &Modulator::mute);
connect (this, &MainWindow::transmitFrequency, &m_modulator, &Modulator::setFrequency);
connect (this, &MainWindow::endTransmitMessage, &m_modulator, &Modulator::stop);
connect (this, &MainWindow::tune, &m_modulator, &Modulator::tune);
connect (this, &MainWindow::sendMessage, &m_modulator, &Modulator::start);
// hook up the audio input stream
connect (this, SIGNAL (startAudioInputStream (QAudioDeviceInfo const&, unsigned, int, QIODevice *, unsigned))
, &m_soundInput, SLOT (start (QAudioDeviceInfo const&, unsigned, int, QIODevice *, unsigned)));
connect (this, SIGNAL (stopAudioInputStream ()), &m_soundInput, SLOT (stop ()));
connect (this, &MainWindow::startAudioInputStream, &m_soundInput, &SoundInput::start);
connect (this, &MainWindow::finished, &m_soundInput, &SoundInput::stop);
connect (this, &MainWindow::finished, this, &MainWindow::close);
connect(&m_soundInput, SIGNAL (error (QString)), this, SLOT (showSoundInError (QString)));
// connect(&m_soundInput, SIGNAL(status(QString)), this, SLOT(showStatusMessage(QString)));
connect(&m_soundInput, &SoundInput::error, this, &MainWindow::showSoundInError);
// connect(&m_soundInput, &SoundInput::status, this, &MainWindow::showStatusMessage);
// hook up the detector
connect (this, SIGNAL (startDetector (AudioDevice::Channel)), &m_detector, SLOT (open (AudioDevice::Channel)));
connect (this, SIGNAL (detectorSetMonitoring (bool)), &m_detector, SLOT (setMonitoring (bool)));
connect (this, SIGNAL (detectorClose ()), &m_detector, SLOT (close ()));
connect(&m_detector, SIGNAL (framesWritten (qint64)), this, SLOT (dataSink (qint64)));
connect (this, &MainWindow::detectorSetMonitoring, &m_detector, &Detector::setMonitoring);
connect(&m_detector, &Detector::framesWritten, this, &MainWindow::dataSink);
// setup the waterfall
connect(m_wideGraph.data (), SIGNAL(freezeDecode2(int)),this,
@ -281,7 +273,7 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
ptt0Timer = new QTimer(this);
ptt0Timer->setSingleShot(true);
connect (ptt0Timer, SIGNAL (timeout ()), &m_modulator, SLOT (close ()));
connect (ptt0Timer, &QTimer::timeout, &m_modulator, &Modulator::stop);
connect(ptt0Timer, SIGNAL(timeout()), this, SLOT(stopTx2()));
ptt1Timer = new QTimer(this);
ptt1Timer->setSingleShot(true);
@ -293,7 +285,7 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
tuneButtonTimer= new QTimer(this);
tuneButtonTimer->setSingleShot(true);
connect (tuneButtonTimer, SIGNAL (timeout ()), &m_modulator, SLOT (close ()));
connect (tuneButtonTimer, &QTimer::timeout, &m_modulator, &Modulator::stop);
connect(tuneButtonTimer, SIGNAL(timeout()), this,
SLOT(on_stopTxButton_clicked()));
@ -328,7 +320,6 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
m_inGain=0;
m_dataAvailable=false;
g_iptt=0;
g_COMportOpen=0;
m_secID=0;
m_blankLine=false;
m_decodedText2=false;
@ -423,26 +414,13 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
watcher2 = new QFutureWatcher<void>;
connect(watcher2, SIGNAL(finished()),this,SLOT(diskWriteFinished()));
Q_EMIT startDetector (m_config.audio_input_channel ());
Q_EMIT startAudioInputStream (m_config.audio_input_device (), AudioDevice::Mono == m_config.audio_input_channel () ? 1 : 2, m_framesAudioInputBuffered, &m_detector, m_downSampleFactor);
Q_EMIT startAudioInputStream (m_config.audio_input_device (), m_framesAudioInputBuffered, &m_detector, m_downSampleFactor, m_config.audio_input_channel ());
Q_EMIT initializeAudioOutputStream (m_config.audio_output_device (), AudioDevice::Mono == m_config.audio_output_channel () ? 1 : 2, m_msAudioOutputBuffered);
Q_EMIT transmitFrequency (m_txFreq - m_XIT);
Q_EMIT muteAudioOutput (false);
// Create "m_worked", a dictionary of all calls in wsjtx.log
QFile f(m_config.data_path ().absoluteFilePath ("wsjtx.log"));
f.open(QIODevice::ReadOnly | QIODevice::Text);
QTextStream in(&f);
QString line,t,callsign;
for(int i=0; i<99999; i++) {
line=in.readLine();
if(line.length()<=0) break;
t=line.mid(18,12);
callsign=t.mid(0,t.indexOf(","));
}
f.close();
t="UTC dB DT Freq Message";
auto t = "UTC dB DT Freq Message";
ui->decodedTextLabel->setText(t);
ui->decodedTextLabel2->setText(t);
@ -450,10 +428,8 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
ui->label_9->setStyleSheet("QLabel{background-color: #aabec8}");
ui->label_10->setStyleSheet("QLabel{background-color: #aabec8}");
ui->labUTC->setStyleSheet( \
"QLabel { background-color : black; color : yellow; }");
ui->labDialFreq->setStyleSheet( \
"QLabel { background-color : black; color : yellow; }");
ui->labUTC->setStyleSheet("QLabel { background-color : black; color : yellow; }");
ui->labDialFreq->setStyleSheet("QLabel { background-color : black; color : yellow; }");
m_config.transceiver_online (true);
qsy (m_lastMonitoredFrequency);
@ -665,14 +641,10 @@ void MainWindow::on_actionSettings_triggered() //Setup Dialog
if(m_mode=="JT9W-1") m_toneSpacing=pow(2,m_config.jt9w_bw_mult ())*12000.0/6912.0;
if(m_config.restart_audio_input ()) {
Q_EMIT stopAudioInputStream ();
Q_EMIT detectorClose ();
Q_EMIT startDetector (m_config.audio_input_channel ());
Q_EMIT startAudioInputStream (m_config.audio_input_device (), AudioDevice::Mono == m_config.audio_input_channel () ? 1 : 2, m_framesAudioInputBuffered, &m_detector, m_downSampleFactor);
Q_EMIT startAudioInputStream (m_config.audio_input_device (), m_framesAudioInputBuffered, &m_detector, m_downSampleFactor, m_config.audio_input_channel ());
}
if(m_config.restart_audio_output ()) {
Q_EMIT stopAudioOutputStream ();
Q_EMIT startAudioOutputStream (m_config.audio_output_device (), AudioDevice::Mono == m_config.audio_output_channel () ? 1 : 2, m_msAudioOutputBuffered);
Q_EMIT initializeAudioOutputStream (m_config.audio_output_device (), AudioDevice::Mono == m_config.audio_output_channel () ? 1 : 2, m_msAudioOutputBuffered);
}
auto_tx_label->setText (m_config.quick_call () ? "Tx-Enable Armed" : "Tx-Enable Disarmed");
@ -709,7 +681,6 @@ void MainWindow::on_monitorButton_clicked (bool checked)
}
Q_EMIT detectorSetMonitoring (checked);
// Q_EMIT startAudioInputStream (m_params.audio_input_device, AudioDevice::Mono == m_params.audio_input_channel ? 1 : 2, m_framesAudioInputBuffered, &m_detector, m_downSampleFactor);
}
else
{
@ -1431,7 +1402,6 @@ void MainWindow::guiUpdate()
static char msgsent[29];
static int nsendingsh=0;
static int giptt00=-1;
static int gcomport00=-1;
static double onAirFreq0=0.0;
QString rt;
@ -1670,9 +1640,8 @@ void MainWindow::guiUpdate()
m_sec0=nsec;
}
if(g_iptt!=giptt00 or g_COMportOpen!=gcomport00) {
if(g_iptt!=giptt00) {
giptt00=g_iptt;
gcomport00=g_COMportOpen;
}
iptt0=g_iptt;
@ -1706,7 +1675,6 @@ void MainWindow::startTx2()
void MainWindow::stopTx()
{
Q_EMIT endTransmitMessage ();
Q_EMIT stopAudioOutputStream ();
m_transmitting=false;
if ("JT9+JT65" == m_mode) ui->pbTxMode->setEnabled(true);
g_iptt=0;
@ -2859,13 +2827,12 @@ void MainWindow::transmit (double snr)
{
if (m_modeTx == "JT65")
{
Q_EMIT sendMessage (NUM_JT65_SYMBOLS, 4096.0 * 12000.0 / 11025.0, m_txFreq - m_XIT, m_config.audio_output_channel (), true, snr);
Q_EMIT sendMessage (NUM_JT65_SYMBOLS, 4096.0 * 12000.0 / 11025.0, m_txFreq - m_XIT, m_soundOutput.stream (), m_config.audio_output_channel (), true, snr);
}
else
{
Q_EMIT sendMessage (NUM_JT9_SYMBOLS, m_nsps, m_txFreq - m_XIT, m_config.audio_output_channel (), true, snr);
Q_EMIT sendMessage (NUM_JT9_SYMBOLS, m_nsps, m_txFreq - m_XIT, m_soundOutput.stream (), m_config.audio_output_channel (), true, snr);
}
Q_EMIT startAudioOutputStream (m_config.audio_output_device (), AudioDevice::Mono == m_config.audio_output_channel () ? 1 : 2, m_msAudioOutputBuffered);
}
void MainWindow::on_outAttenuation_valueChanged (int a)

View File

@ -1,3 +1,4 @@
// -*- Mode: C++ -*-
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#ifdef QT5
@ -13,6 +14,7 @@
#include <QScopedPointer>
#include "soundin.h"
#include "AudioDevice.hpp"
#include "soundout.h"
#include "commons.h"
#include "Radio.hpp"
@ -37,7 +39,7 @@ extern int icw[NUM_CW_SYMBOLS]; //Dits for CW ID
//--------------------------------------------------------------- MainWindow
namespace Ui {
class MainWindow;
class MainWindow;
}
class QSettings;
@ -46,6 +48,7 @@ class WideGraph;
class LogQSO;
class Transceiver;
class Astro;
class QAudioOutput;
class MainWindow : public QMainWindow
{
@ -175,11 +178,10 @@ private slots:
private:
void enable_DXCC_entity (bool on);
Q_SIGNAL void startAudioOutputStream (QAudioDeviceInfo, unsigned channels, unsigned msBuffered) const;
Q_SIGNAL void initializeAudioOutputStream (QAudioDeviceInfo, unsigned channels, unsigned msBuffered) const;
Q_SIGNAL void stopAudioOutputStream () const;
Q_SIGNAL void startAudioInputStream (QAudioDeviceInfo const&, unsigned channels, int framesPerBuffer, QIODevice * sink, unsigned downSampleFactor) const;
Q_SIGNAL void stopAudioInputStream () const;
Q_SIGNAL void startAudioInputStream (QAudioDeviceInfo const&, int framesPerBuffer, AudioDevice * sink, unsigned downSampleFactor, AudioDevice::Channel) const;
Q_SIGNAL void startDetector (AudioDevice::Channel) const;
Q_SIGNAL void detectorSetMonitoring (bool) const;
@ -190,7 +192,7 @@ private:
Q_SIGNAL void transmitFrequency (unsigned) const;
Q_SIGNAL void endTransmitMessage () const;
Q_SIGNAL void tune (bool = true) const;
Q_SIGNAL void sendMessage (unsigned symbolsLength, double framesPerSymbol, unsigned frequency, AudioDevice::Channel, bool synchronize = true, double dBSNR = 99.) const;
Q_SIGNAL void sendMessage (unsigned symbolsLength, double framesPerSymbol, unsigned frequency, QAudioOutput *, AudioDevice::Channel = AudioDevice::Mono, bool synchronize = true, double dBSNR = 99.) const;
Q_SIGNAL void outAttenuationChanged (qreal) const;
private:
@ -212,185 +214,185 @@ private:
Frequency m_dialFreq;
qint64 m_msErase;
qint64 m_secBandChanged;
qint64 m_msErase;
qint64 m_secBandChanged;
qint32 m_waterfallAvg;
qint32 m_ntx;
qint32 m_timeout;
qint32 m_rxFreq;
qint32 m_txFreq;
int m_XIT;
qint32 m_setftx;
qint32 m_ndepth;
qint32 m_sec0;
qint32 m_RxLog;
qint32 m_nutc0;
qint32 m_nrx;
qint32 m_hsym;
qint32 m_waterfallAvg;
qint32 m_ntx;
qint32 m_timeout;
qint32 m_rxFreq;
qint32 m_txFreq;
int m_XIT;
qint32 m_setftx;
qint32 m_ndepth;
qint32 m_sec0;
qint32 m_RxLog;
qint32 m_nutc0;
qint32 m_nrx;
qint32 m_hsym;
Detector m_detector;
SoundInput m_soundInput;
Detector m_detector;
SoundInput m_soundInput;
Modulator m_modulator;
SoundOutput m_soundOutput;
QThread * m_audioThread;
Modulator m_modulator;
SoundOutput m_soundOutput;
QThread * m_audioThread;
qint32 m_TRperiod;
qint32 m_nsps;
qint32 m_hsymStop;
qint32 m_len1;
qint32 m_inGain;
qint32 m_nsave;
qint32 m_ncw;
qint32 m_secID;
QString m_band;
qint32 m_repeatMsg;
qint32 m_watchdogLimit;
qint32 m_fMax;
qint32 m_EMEbandIndex;
qint32 m_toneMultIndex;
qint32 m_astroFont;
qint32 m_TRperiod;
qint32 m_nsps;
qint32 m_hsymStop;
qint32 m_len1;
qint32 m_inGain;
qint32 m_nsave;
qint32 m_ncw;
qint32 m_secID;
QString m_band;
qint32 m_repeatMsg;
qint32 m_watchdogLimit;
qint32 m_fMax;
qint32 m_EMEbandIndex;
qint32 m_toneMultIndex;
qint32 m_astroFont;
bool m_btxok; //True if OK to transmit
bool m_btxMute; //True if transmit should be muted
bool m_diskData;
bool m_loopall;
bool m_decoderBusy;
bool m_txFirst;
bool m_auto;
bool m_restart;
bool m_startAnother;
bool m_saveDecoded;
bool m_saveAll;
bool m_widebandDecode;
bool m_call3Modified;
bool m_dataAvailable;
bool m_killAll;
bool m_bdecoded;
bool m_monitorStartOFF;
bool m_pskReporterInit;
bool m_noSuffix;
bool m_toRTTY;
bool m_dBtoComments;
bool m_promptToLog;
bool m_blankLine;
bool m_insertBlank;
bool m_displayDXCCEntity;
bool m_clearCallGrid;
bool m_bMiles;
bool m_decodedText2;
bool m_freeText;
bool m_quickCall;
bool m_73TxDisable;
bool m_sent73;
bool m_runaway;
bool m_bMultipleOK;
bool m_lockTxFreq;
bool m_tx2QSO;
bool m_CATerror;
bool m_plus2kHz;
bool m_bAstroData;
bool m_btxok; //True if OK to transmit
bool m_btxMute; //True if transmit should be muted
bool m_diskData;
bool m_loopall;
bool m_decoderBusy;
bool m_txFirst;
bool m_auto;
bool m_restart;
bool m_startAnother;
bool m_saveDecoded;
bool m_saveAll;
bool m_widebandDecode;
bool m_call3Modified;
bool m_dataAvailable;
bool m_killAll;
bool m_bdecoded;
bool m_monitorStartOFF;
bool m_pskReporterInit;
bool m_noSuffix;
bool m_toRTTY;
bool m_dBtoComments;
bool m_promptToLog;
bool m_blankLine;
bool m_insertBlank;
bool m_displayDXCCEntity;
bool m_clearCallGrid;
bool m_bMiles;
bool m_decodedText2;
bool m_freeText;
bool m_quickCall;
bool m_73TxDisable;
bool m_sent73;
bool m_runaway;
bool m_bMultipleOK;
bool m_lockTxFreq;
bool m_tx2QSO;
bool m_CATerror;
bool m_plus2kHz;
bool m_bAstroData;
float m_pctZap;
float m_pctZap;
// labels in status bar
QLabel * tx_status_label;
QLabel * mode_label;
QLabel * last_tx_label;
QLabel * auto_tx_label;
// labels in status bar
QLabel * tx_status_label;
QLabel * mode_label;
QLabel * last_tx_label;
QLabel * auto_tx_label;
QMessageBox msgBox0;
QMessageBox msgBox0;
QFuture<void>* future1;
QFuture<void>* future2;
QFuture<void>* future3;
QFutureWatcher<void>* watcher1;
QFutureWatcher<void>* watcher2;
QFutureWatcher<void>* watcher3;
QFuture<void>* future1;
QFuture<void>* future2;
QFuture<void>* future3;
QFutureWatcher<void>* watcher1;
QFutureWatcher<void>* watcher2;
QFutureWatcher<void>* watcher3;
QProcess proc_jt9;
QProcess proc_jt9;
QTimer m_guiTimer;
QTimer* ptt1Timer; //StartTx delay
QTimer* ptt0Timer; //StopTx delay
QTimer* logQSOTimer;
QTimer* killFileTimer;
QTimer* tuneButtonTimer;
QTimer m_guiTimer;
QTimer* ptt1Timer; //StartTx delay
QTimer* ptt0Timer; //StopTx delay
QTimer* logQSOTimer;
QTimer* killFileTimer;
QTimer* tuneButtonTimer;
QString m_path;
QString m_pbdecoding_style1;
QString m_pbmonitor_style;
QString m_pbAutoOn_style;
QString m_pbTune_style;
QString m_baseCall;
QString m_hisCall;
QString m_hisGrid;
QString m_appDir;
QString m_dxccPfx;
QString m_palette;
QString m_dateTime;
QString m_mode;
QString m_modeTx;
QString m_fname;
QString m_rpt;
QString m_rptSent;
QString m_rptRcvd;
QString m_qsoStart;
QString m_qsoStop;
QString m_cmnd;
QString m_msgSent0;
QString m_fileToSave;
QString m_path;
QString m_pbdecoding_style1;
QString m_pbmonitor_style;
QString m_pbAutoOn_style;
QString m_pbTune_style;
QString m_baseCall;
QString m_hisCall;
QString m_hisGrid;
QString m_appDir;
QString m_dxccPfx;
QString m_palette;
QString m_dateTime;
QString m_mode;
QString m_modeTx;
QString m_fname;
QString m_rpt;
QString m_rptSent;
QString m_rptRcvd;
QString m_qsoStart;
QString m_qsoStop;
QString m_cmnd;
QString m_msgSent0;
QString m_fileToSave;
QStringList m_prefix;
QStringList m_suffix;
QStringList m_prefix;
QStringList m_suffix;
QHash<QString,bool> m_pfx;
QHash<QString,bool> m_sfx;
QHash<QString,bool> m_pfx;
QHash<QString,bool> m_sfx;
QDateTime m_dateTimeQSO;
QRect m_astroGeom;
QDateTime m_dateTimeQSO;
QRect m_astroGeom;
QSharedMemory *mem_jt9;
// Multiple instances:
QString mykey_jt9;
PSK_Reporter *psk_Reporter;
SignalMeter *signalMeter;
LogBook m_logBook;
DecodedText m_QSOText;
unsigned m_msAudioOutputBuffered;
unsigned m_framesAudioInputBuffered;
unsigned m_downSampleFactor;
QThread::Priority m_audioThreadPriority;
bool m_bandEdited;
bool m_splitMode;
bool m_monitoring;
bool m_transmitting;
bool m_tune;
Frequency m_lastMonitoredFrequency;
double m_toneSpacing;
QSharedMemory *mem_jt9;
// Multiple instances:
QString mykey_jt9;
PSK_Reporter *psk_Reporter;
SignalMeter *signalMeter;
LogBook m_logBook;
DecodedText m_QSOText;
unsigned m_msAudioOutputBuffered;
unsigned m_framesAudioInputBuffered;
unsigned m_downSampleFactor;
QThread::Priority m_audioThreadPriority;
bool m_bandEdited;
bool m_splitMode;
bool m_monitoring;
bool m_transmitting;
bool m_tune;
Frequency m_lastMonitoredFrequency;
double m_toneSpacing;
//---------------------------------------------------- private functions
void readSettings();
void setDecodedTextFont (QFont const&);
void writeSettings();
void createStatusBar();
void updateStatusBar();
void msgBox(QString t);
void genStdMsgs(QString rpt);
void lookup();
void ba2msg(QByteArray ba, char* message);
void msgtype(QString t, QLineEdit* tx);
void stub();
void statusChanged();
void qsy(Frequency f);
bool gridOK(QString g);
bool shortList(QString callsign);
QString baseCall(QString t);
void transmit (double snr = 99.);
void rigFailure (QString const& reason, QString const& detail);
void pskSetLocal ();
void displayDialFrequency ();
//---------------------------------------------------- private functions
void readSettings();
void setDecodedTextFont (QFont const&);
void writeSettings();
void createStatusBar();
void updateStatusBar();
void msgBox(QString t);
void genStdMsgs(QString rpt);
void lookup();
void ba2msg(QByteArray ba, char* message);
void msgtype(QString t, QLineEdit* tx);
void stub();
void statusChanged();
void qsy(Frequency f);
bool gridOK(QString g);
bool shortList(QString callsign);
QString baseCall(QString t);
void transmit (double snr = 99.);
void rigFailure (QString const& reason, QString const& detail);
void pskSetLocal ();
void displayDialFrequency ();
};
extern void getfile(QString fname, int ntrperiod);
@ -402,25 +404,25 @@ extern void getDev(int* numDevices,char hostAPI_DeviceName[][50],
extern int ptt(int nport, int ntx, int* iptt, int* nopen);
extern "C" {
//----------------------------------------------------- C and Fortran routines
void symspec_(int* k, int* ntrperiod, int* nsps, int* ingain, int* nflatten,
float* px, float s[], float* df3, int* nhsym, int* npts8);
//----------------------------------------------------- C and Fortran routines
void symspec_(int* k, int* ntrperiod, int* nsps, int* ingain, int* nflatten,
float* px, float s[], float* df3, int* nhsym, int* npts8);
void genjt9_(char* msg, int* ichk, char* msgsent, int itone[],
int* itext, int len1, int len2);
void genjt9_(char* msg, int* ichk, char* msgsent, int itone[],
int* itext, int len1, int len2);
void gen65_(char* msg, int* ichk, char* msgsent, int itone[],
int* itext, int len1, int len2);
void gen65_(char* msg, int* ichk, char* msgsent, int itone[],
int* itext, int len1, int len2);
bool stdmsg_(const char* msg, int len);
bool stdmsg_(const char* msg, int len);
void azdist_(char* MyGrid, char* HisGrid, double* utch, int* nAz, int* nEl,
int* nDmiles, int* nDkm, int* nHotAz, int* nHotABetter,
int len1, int len2);
void azdist_(char* MyGrid, char* HisGrid, double* utch, int* nAz, int* nEl,
int* nDmiles, int* nDkm, int* nHotAz, int* nHotABetter,
int len1, int len2);
void morse_(char* msg, int* icw, int* ncw, int len);
void morse_(char* msg, int* icw, int* ncw, int len);
int ptt_(int nport, int ntx, int* iptt, int* nopen);
int ptt_(int nport, int ntx, int* iptt, int* nopen);
}

View File

@ -1,3 +1,4 @@
// -*- Mode: C++ -*-
#ifndef METERWIDGET_H
#define METERWIDGET_H

View File

@ -1,3 +1,4 @@
// -*- Mode: C++ -*-
///////////////////////////////////////////////////////////////////////////
// Some code in this file and accompanying files is based on work by
// Moe Wheatley, AE4Y, released under the "Simplified BSD License".

View File

@ -1,3 +1,4 @@
// -*- Mode: C++ -*-
#ifndef PSK_REPORTER_H
#define PSK_REPORTER_H

View File

@ -1,3 +1,4 @@
// -*- Mode: C++ -*-
#ifndef SIGNALMETER_H
#define SIGNALMETER_H

View File

@ -1,3 +1,4 @@
// -*- Mode: C++ -*-
#ifndef SLEEP_H
#define SLEEP_H
#include <qthread.h>

View File

@ -15,40 +15,41 @@ bool SoundInput::audioError () const
if (m_stream)
{
switch (m_stream->error ())
{
case QAudio::OpenError:
Q_EMIT error (tr ("An error opening the audio input device has occurred."));
break;
{
case QAudio::OpenError:
Q_EMIT error (tr ("An error opening the audio input device has occurred."));
break;
case QAudio::IOError:
Q_EMIT error (tr ("An error occurred during read from the audio input device."));
break;
case QAudio::IOError:
Q_EMIT error (tr ("An error occurred during read from the audio input device."));
break;
case QAudio::UnderrunError:
Q_EMIT error (tr ("Audio data not being fed to the audio input device fast enough."));
break;
case QAudio::UnderrunError:
Q_EMIT error (tr ("Audio data not being fed to the audio input device fast enough."));
break;
case QAudio::FatalError:
Q_EMIT error (tr ("Non-recoverable error, audio input device not usable at this time."));
break;
case QAudio::FatalError:
Q_EMIT error (tr ("Non-recoverable error, audio input device not usable at this time."));
break;
case QAudio::NoError:
result = false;
break;
}
case QAudio::NoError:
result = false;
break;
}
}
return result;
}
void SoundInput::start(QAudioDeviceInfo const& device, unsigned channels, int framesPerBuffer, QIODevice * sink, unsigned downSampleFactor)
void SoundInput::start(QAudioDeviceInfo const& device, int framesPerBuffer, AudioDevice * sink, unsigned downSampleFactor, AudioDevice::Channel channel)
{
Q_ASSERT (0 < channels && channels < 3);
Q_ASSERT (sink);
stop();
stop ();
m_sink = sink;
QAudioFormat format (device.preferredFormat());
format.setChannelCount (channels);
format.setChannelCount (AudioDevice::Mono == channel ? 1 : 2);
format.setCodec ("audio/pcm");
format.setSampleRate (12000 * downSampleFactor);
format.setSampleType (QAudioFormat::SignedInt);
@ -74,9 +75,17 @@ void SoundInput::start(QAudioDeviceInfo const& device, unsigned channels, int fr
}
connect (m_stream.data(), &QAudioInput::stateChanged, this, &SoundInput::handleStateChanged);
m_stream->setBufferSize (m_stream->format ().bytesForFrames (framesPerBuffer));
m_stream->start (sink);
audioError ();
if (sink->initialize (QIODevice::WriteOnly, channel))
{
m_stream->start (sink);
audioError ();
}
else
{
Q_EMIT error (tr ("Failed to initialize audio sink device"));
}
}
void SoundInput::handleStateChanged (QAudio::State newState) const
@ -97,13 +106,13 @@ void SoundInput::handleStateChanged (QAudio::State newState) const
case QAudio::StoppedState:
if (audioError ())
{
Q_EMIT status (tr ("Error"));
}
{
Q_EMIT status (tr ("Error"));
}
else
{
Q_EMIT status (tr ("Stopped"));
}
{
Q_EMIT status (tr ("Stopped"));
}
break;
}
}
@ -115,8 +124,14 @@ void SoundInput::stop()
m_stream->stop ();
}
m_stream.reset ();
if (m_sink)
{
m_sink->close ();
}
}
SoundInput::~SoundInput ()
{
stop ();
}

View File

@ -1,3 +1,4 @@
// -*- Mode: C++ -*-
#ifndef SOUNDIN_H__
#define SOUNDIN_H__
@ -6,9 +7,10 @@
#include <QScopedPointer>
#include <QAudioInput>
#include "AudioDevice.hpp"
class QAudioDeviceInfo;
class QAudioInput;
class QIODevice;
// Gets audio data from sound sample source and passes it to a sink device
class SoundInput
@ -16,28 +18,31 @@ class SoundInput
{
Q_OBJECT;
public:
SoundInput (QObject * parent = 0)
: QObject (parent)
public:
SoundInput (QObject * parent = nullptr)
: QObject {parent}
, m_sink {nullptr}
{
}
~SoundInput ();
// sink must exist from the start call to any following stop () call
Q_SLOT void start(QAudioDeviceInfo const&, unsigned channels, int framesPerBuffer, QIODevice * sink, unsigned downSampleFactor);
Q_SLOT void stop();
// sink must exist from the start call until the next start call or
// stop call
Q_SLOT void start(QAudioDeviceInfo const&, int framesPerBuffer, AudioDevice * sink, unsigned downSampleFactor, AudioDevice::Channel = AudioDevice::Mono);
Q_SLOT void stop ();
private:
Q_SIGNAL void error (QString message) const;
Q_SIGNAL void status (QString message) const;
private:
// used internally
Q_SLOT void handleStateChanged (QAudio::State) const;
bool audioError () const;
QScopedPointer<QAudioInput> m_stream;
AudioDevice * m_sink;
};
#endif

View File

@ -21,27 +21,27 @@ bool SoundOutput::audioError () const
Q_ASSERT_X (m_stream, "SoundOutput", "programming error");
if (m_stream) {
switch (m_stream->error ())
{
case QAudio::OpenError:
Q_EMIT error (tr ("An error opening the audio output device has occurred."));
break;
{
case QAudio::OpenError:
Q_EMIT error (tr ("An error opening the audio output device has occurred."));
break;
case QAudio::IOError:
Q_EMIT error (tr ("An error occurred during write to the audio output device."));
break;
case QAudio::IOError:
Q_EMIT error (tr ("An error occurred during write to the audio output device."));
break;
case QAudio::UnderrunError:
Q_EMIT error (tr ("Audio data not being fed to the audio output device fast enough."));
break;
case QAudio::UnderrunError:
Q_EMIT error (tr ("Audio data not being fed to the audio output device fast enough."));
break;
case QAudio::FatalError:
Q_EMIT error (tr ("Non-recoverable error, audio output device not usable at this time."));
break;
case QAudio::FatalError:
Q_EMIT error (tr ("Non-recoverable error, audio output device not usable at this time."));
break;
case QAudio::NoError:
result = false;
break;
}
case QAudio::NoError:
result = false;
break;
}
}
return result;
}
@ -54,8 +54,7 @@ SoundOutput::SoundOutput (QIODevice * source)
Q_ASSERT (source);
}
void SoundOutput::startStream (QAudioDeviceInfo const& device, \
unsigned channels, unsigned msBuffered)
void SoundOutput::setFormat (QAudioDeviceInfo const& device, unsigned channels, unsigned msBuffered)
{
Q_ASSERT (0 < channels && channels < 3);
@ -70,24 +69,23 @@ void SoundOutput::startStream (QAudioDeviceInfo const& device, \
format.setSampleType (QAudioFormat::SignedInt);
format.setSampleSize (16);
if (!format.isValid ())
{
Q_EMIT error (tr ("Requested output audio format is not valid."));
}
{
Q_EMIT error (tr ("Requested output audio format is not valid."));
}
if (!device.isFormatSupported (format))
{
Q_EMIT error (tr ("Requested output audio format is not supported on device."));
}
{
Q_EMIT error (tr ("Requested output audio format is not supported on device."));
}
m_stream.reset (new QAudioOutput (device, format));
audioError ();
m_stream->setVolume (m_volume);
m_stream->setNotifyInterval(100);
connect (m_stream.data(), &QAudioOutput::stateChanged, this, \
&SoundOutput::handleStateChanged);
connect (m_stream.data(), &QAudioOutput::stateChanged, this, &SoundOutput::handleStateChanged);
m_currentDevice = device;
// qDebug() << "A" << m_volume << m_stream->notifyInterval();
// qDebug() << "A" << m_volume << m_stream->notifyInterval();
}
//
@ -103,12 +101,8 @@ void SoundOutput::startStream (QAudioDeviceInfo const& device, \
// we have to set this before every start on the stream because the
// Windows implementation seems to forget the buffer size after a
// stop.
m_stream->setBufferSize (m_stream->format().bytesForDuration(
(msBuffered ? msBuffered : MS_BUFFERED) * 1000));
// qDebug() << "B" << m_stream->bufferSize() << m_stream->periodSize() << m_stream->notifyInterval();
m_stream->start (m_source);
audioError ();
m_stream->setBufferSize (m_stream->format().bytesForDuration((msBuffered ? msBuffered : MS_BUFFERED) * 1000));
// qDebug() << "B" << m_stream->bufferSize() << m_stream->periodSize() << m_stream->notifyInterval();
}
void SoundOutput::suspend ()
@ -138,7 +132,7 @@ void SoundOutput::setAttenuation (qreal a)
{
Q_ASSERT (0. <= a && a <= 99.);
m_volume = qPow (10., -a / 10.);
// qDebug () << "SoundOut: attn = " << a << ", vol = " << m_volume;
// qDebug () << "SoundOut: attn = " << a << ", vol = " << m_volume;
if (m_stream)
{
m_stream->setVolume (m_volume);
@ -154,15 +148,6 @@ void SoundOutput::resetAttenuation ()
}
}
void SoundOutput::stopStream ()
{
if (m_stream)
{
m_stream->stop ();
audioError ();
}
}
void SoundOutput::handleStateChanged (QAudio::State newState)
{
switch (newState)
@ -185,13 +170,13 @@ void SoundOutput::handleStateChanged (QAudio::State newState)
case QAudio::StoppedState:
m_active = false;
if (audioError ())
{
Q_EMIT status (tr ("Error"));
}
{
Q_EMIT status (tr ("Error"));
}
else
{
Q_EMIT status (tr ("Stopped"));
}
{
Q_EMIT status (tr ("Stopped"));
}
break;
}
}

View File

@ -1,3 +1,4 @@
// -*- Mode: C++ -*-
#ifndef SOUNDOUT_H__
#define SOUNDOUT_H__
@ -14,39 +15,36 @@ class SoundOutput
: public QObject
{
Q_OBJECT;
Q_PROPERTY(bool running READ isRunning);
Q_PROPERTY(unsigned attenuation READ attenuation WRITE setAttenuation RESET resetAttenuation);
public:
public:
SoundOutput (QIODevice * source);
~SoundOutput ();
bool isRunning() const {return m_active;}
qreal attenuation () const;
QAudioOutput * stream () {return m_stream.data ();}
private Q_SLOTS:
/* private because we expect to run in a thread and don't want direct
C++ calls made, instead they must be invoked via the Qt
signal/slot mechanism which is thread safe */
void startStream (QAudioDeviceInfo const& device, unsigned channels, unsigned msBuffered = 0u);
public Q_SLOTS:
void setFormat (QAudioDeviceInfo const& device, unsigned channels, unsigned msBuffered = 0u);
void suspend ();
void resume ();
void stopStream ();
void setAttenuation (qreal); /* unsigned */
void resetAttenuation (); /* to zero */
Q_SIGNALS:
Q_SIGNALS:
void error (QString message) const;
void status (QString message) const;
private:
bool audioError () const;
private Q_SLOTS:
private Q_SLOTS:
void handleStateChanged (QAudio::State);
private:
private:
QScopedPointer<QAudioOutput> m_stream;
QIODevice * m_source;

View File

@ -1,3 +1,4 @@
// -*- Mode: C++ -*-
#ifndef WIDEGRAPH_H
#define WIDEGRAPH_H