diff --git a/AudioDevice.cpp b/AudioDevice.cpp index 871273d19..a557aa66e 100644 --- a/AudioDevice.cpp +++ b/AudioDevice.cpp @@ -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); } diff --git a/AudioDevice.hpp b/AudioDevice.hpp index 63f8b5999..0f78b2ba8 100644 --- a/AudioDevice.hpp +++ b/AudioDevice.hpp @@ -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;} diff --git a/Detector.cpp b/Detector.cpp index 48a251b49..5125775db 100644 --- a/Detector.cpp +++ b/Detector.cpp @@ -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 (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 (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 (maxSize / + bytesPerFrame ()), framesAcceptable)); - if (framesAccepted < static_cast (maxSize / bytesPerFrame ())) { - qDebug () << "dropped " << maxSize / bytesPerFrame () - framesAccepted - << " frames of data on the floor!"; - } + if (framesAccepted < static_cast (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 (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 (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 diff --git a/Detector.hpp b/Detector.hpp index 3004408be..cb14702d1 100644 --- a/Detector.hpp +++ b/Detector.hpp @@ -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 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; }; diff --git a/Modulator.cpp b/Modulator.cpp index 927882023..2153a65e2 100644 --- a/Modulator.cpp +++ b/Modulator.cpp @@ -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 (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::min ()) || - !!icw[j] != l0) { - if (!!icw[j] != l0) { - Q_ASSERT (m_ramp == 0 || m_ramp == std::numeric_limits::min ()); + if ((m_ramp != 0 && m_ramp != std::numeric_limits::min ()) || + !!icw[j] != l0) { + if (!!icw[j] != l0) { + Q_ASSERT (m_ramp == 0 || m_ramp == std::numeric_limits::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 (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 (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::max ()) { diff --git a/Modulator.hpp b/Modulator.hpp index d6ec3a5a9..230e3f7ec 100644 --- a/Modulator.hpp +++ b/Modulator.hpp @@ -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; diff --git a/about.h b/about.h index 02e9239e4..c2ac75d1b 100644 --- a/about.h +++ b/about.h @@ -1,3 +1,4 @@ +// -*- Mode: C++ -*- #ifndef ABOUTDLG_H #define ABOUTDLG_H diff --git a/decodedtext.h b/decodedtext.h index e60a91d40..47dcd63a2 100644 --- a/decodedtext.h +++ b/decodedtext.h @@ -1,3 +1,4 @@ +// -*- Mode: C++ -*- /* * Class to handle the formatted string as returned from the fortran decoder * diff --git a/displaytext.h b/displaytext.h index 1307b37a9..8ed3b0ac4 100644 --- a/displaytext.h +++ b/displaytext.h @@ -1,3 +1,4 @@ +// -*- Mode: C++ -*- #ifndef DISPLAYTEXT_H #define DISPLAYTEXT_H diff --git a/getfile.h b/getfile.h index 2e255d1a4..4cd104514 100644 --- a/getfile.h +++ b/getfile.h @@ -1,3 +1,4 @@ +// -*- Mode: C++ -*- #ifndef GETFILE_H #define GETFILE_H #include diff --git a/logqso.h b/logqso.h index 72121e76e..47047750a 100644 --- a/logqso.h +++ b/logqso.h @@ -1,3 +1,4 @@ +// -*- Mode: C++ -*- #ifndef LogQSO_H #define LogQSO_H diff --git a/mainwindow.cpp b/mainwindow.cpp index 5b7ce0c84..9e65c3c08 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -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; 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) diff --git a/mainwindow.h b/mainwindow.h index 1397f7317..51bb8509b 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -1,3 +1,4 @@ +// -*- Mode: C++ -*- #ifndef MAINWINDOW_H #define MAINWINDOW_H #ifdef QT5 @@ -13,6 +14,7 @@ #include #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* future1; - QFuture* future2; - QFuture* future3; - QFutureWatcher* watcher1; - QFutureWatcher* watcher2; - QFutureWatcher* watcher3; + QFuture* future1; + QFuture* future2; + QFuture* future3; + QFutureWatcher* watcher1; + QFutureWatcher* watcher2; + QFutureWatcher* 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 m_pfx; - QHash m_sfx; + QHash m_pfx; + QHash 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); } diff --git a/meterwidget.h b/meterwidget.h index 7b51efb65..fbc27b6b9 100644 --- a/meterwidget.h +++ b/meterwidget.h @@ -1,3 +1,4 @@ +// -*- Mode: C++ -*- #ifndef METERWIDGET_H #define METERWIDGET_H diff --git a/plotter.h b/plotter.h index 99aa8b31d..b824cc2c1 100644 --- a/plotter.h +++ b/plotter.h @@ -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". diff --git a/psk_reporter.h b/psk_reporter.h index 46bc72756..4baaa4c15 100644 --- a/psk_reporter.h +++ b/psk_reporter.h @@ -1,3 +1,4 @@ +// -*- Mode: C++ -*- #ifndef PSK_REPORTER_H #define PSK_REPORTER_H diff --git a/signalmeter.h b/signalmeter.h index ea1aa6295..c5e21d61d 100644 --- a/signalmeter.h +++ b/signalmeter.h @@ -1,3 +1,4 @@ +// -*- Mode: C++ -*- #ifndef SIGNALMETER_H #define SIGNALMETER_H diff --git a/sleep.h b/sleep.h index c11188c2a..c170c9c55 100644 --- a/sleep.h +++ b/sleep.h @@ -1,3 +1,4 @@ +// -*- Mode: C++ -*- #ifndef SLEEP_H #define SLEEP_H #include diff --git a/soundin.cpp b/soundin.cpp index 377242bf6..cf0d500ae 100644 --- a/soundin.cpp +++ b/soundin.cpp @@ -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 (); } diff --git a/soundin.h b/soundin.h index 652075960..51c526238 100644 --- a/soundin.h +++ b/soundin.h @@ -1,3 +1,4 @@ +// -*- Mode: C++ -*- #ifndef SOUNDIN_H__ #define SOUNDIN_H__ @@ -6,9 +7,10 @@ #include #include +#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 m_stream; + AudioDevice * m_sink; }; #endif diff --git a/soundout.cpp b/soundout.cpp index 5a74ac405..f8830d715 100644 --- a/soundout.cpp +++ b/soundout.cpp @@ -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; } } diff --git a/soundout.h b/soundout.h index 811a8893c..12ba25d97 100644 --- a/soundout.h +++ b/soundout.h @@ -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 m_stream; QIODevice * m_source; diff --git a/widegraph.h b/widegraph.h index 909d28830..3ba972336 100644 --- a/widegraph.h +++ b/widegraph.h @@ -1,3 +1,4 @@ +// -*- Mode: C++ -*- #ifndef WIDEGRAPH_H #define WIDEGRAPH_H