mirror of https://github.com/saitohirga/WSJT-X.git
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:
parent
542c85d8f6
commit
581691befb
|
@ -13,11 +13,11 @@ namespace
|
||||||
} static_initializer;
|
} static_initializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AudioDevice::open (OpenMode mode, Channel channel)
|
bool AudioDevice::initialize (OpenMode mode, Channel channel)
|
||||||
{
|
{
|
||||||
m_channel = channel;
|
m_channel = channel;
|
||||||
|
|
||||||
// ensure we are unbuffered
|
// open and ensure we are unbuffered if possible
|
||||||
return QIODevice::open (mode | QIODevice::Unbuffered);
|
return QIODevice::open (mode | QIODevice::Unbuffered);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ public:
|
||||||
return "both" == s ? Both : "right" == s ? Right : "left" == s ? Left : Mono;
|
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;}
|
bool isSequential () const {return true;}
|
||||||
|
|
||||||
|
|
12
Detector.cpp
12
Detector.cpp
|
@ -7,7 +7,7 @@
|
||||||
#include "moc_Detector.cpp"
|
#include "moc_Detector.cpp"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void fil4_(qint16*, qint32*, qint16*, qint32*);
|
void fil4_(qint16*, qint32*, qint16*, qint32*);
|
||||||
}
|
}
|
||||||
|
|
||||||
Detector::Detector (unsigned frameRate, unsigned periodLengthInSeconds,
|
Detector::Detector (unsigned frameRate, unsigned periodLengthInSeconds,
|
||||||
|
@ -113,12 +113,12 @@ qint64 Detector::writeData (char const * data, qint64 maxSize)
|
||||||
}
|
}
|
||||||
remaining -= numFramesProcessed;
|
remaining -= numFramesProcessed;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
jt9com_.kin = 0;
|
jt9com_.kin = 0;
|
||||||
m_bufferPos = 0;
|
m_bufferPos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return maxSize; // we drop any data past the end of the buffer on
|
return maxSize; // we drop any data past the end of the buffer on
|
||||||
// the floor until the next period starts
|
// the floor until the next period starts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
13
Detector.hpp
13
Detector.hpp
|
@ -30,6 +30,11 @@ public:
|
||||||
|
|
||||||
bool isMonitoring () const {return m_monitoring;}
|
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:
|
protected:
|
||||||
qint64 readData (char * /* data */, qint64 /* maxSize */)
|
qint64 readData (char * /* data */, qint64 /* maxSize */)
|
||||||
{
|
{
|
||||||
|
@ -39,14 +44,6 @@ protected:
|
||||||
qint64 writeData (char const * data, qint64 maxSize);
|
qint64 writeData (char const * data, qint64 maxSize);
|
||||||
|
|
||||||
private:
|
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
|
void clear (); // discard buffer contents
|
||||||
unsigned secondInPeriod () const;
|
unsigned secondInPeriod () const;
|
||||||
|
|
||||||
|
|
|
@ -24,27 +24,31 @@ double const Modulator::m_twoPi = 2.0 * 3.141592653589793238462;
|
||||||
// m_nspd=3072; //18.75 WPM
|
// m_nspd=3072; //18.75 WPM
|
||||||
unsigned const Modulator::m_nspd = 2048 + 512; // 22.5 WPM
|
unsigned const Modulator::m_nspd = 2048 + 512; // 22.5 WPM
|
||||||
|
|
||||||
Modulator::Modulator (unsigned frameRate, unsigned periodLengthInSeconds, \
|
Modulator::Modulator (unsigned frameRate, unsigned periodLengthInSeconds, QObject * parent)
|
||||||
QObject * parent)
|
: AudioDevice {parent}
|
||||||
: AudioDevice (parent)
|
, m_stream {nullptr}
|
||||||
, m_phi (0.0)
|
, m_phi {0.0}
|
||||||
, m_framesSent (0)
|
, m_framesSent {0}
|
||||||
, m_frameRate (frameRate)
|
, m_frameRate {frameRate}
|
||||||
, m_period (periodLengthInSeconds)
|
, m_period {periodLengthInSeconds}
|
||||||
, m_state (Idle)
|
, m_state {Idle}
|
||||||
, m_tuning (false)
|
, m_tuning {false}
|
||||||
, m_muted (false)
|
, m_muted {false}
|
||||||
{
|
{
|
||||||
qsrand (QDateTime::currentMSecsSinceEpoch()); // Initialize random seed
|
qsrand (QDateTime::currentMSecsSinceEpoch()); // Initialize random seed
|
||||||
}
|
}
|
||||||
|
|
||||||
void Modulator::open (unsigned symbolsLength, double framesPerSymbol, \
|
void Modulator::start (unsigned symbolsLength, double framesPerSymbol, unsigned frequency, QAudioOutput * stream, Channel channel, bool synchronize, double dBSNR)
|
||||||
unsigned frequency, Channel channel, bool synchronize, double dBSNR)
|
|
||||||
{
|
{
|
||||||
// Time according to this computer which becomes our base time
|
// Time according to this computer which becomes our base time
|
||||||
qint64 ms0 = QDateTime::currentMSecsSinceEpoch() % 86400000;
|
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_symbolsLength = symbolsLength;
|
||||||
m_framesSent = 0;
|
m_framesSent = 0;
|
||||||
|
@ -71,11 +75,38 @@ void Modulator::open (unsigned symbolsLength, double framesPerSymbol, \
|
||||||
m_silentFrames = m_ic + m_frameRate - (mstr * m_frameRate / 1000);
|
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) ?
|
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)
|
qint64 Modulator::readData (char * data, qint64 maxSize)
|
||||||
|
@ -92,8 +123,8 @@ qint64 Modulator::readData (char * data, qint64 maxSize)
|
||||||
qint16 * samples (reinterpret_cast<qint16 *> (data));
|
qint16 * samples (reinterpret_cast<qint16 *> (data));
|
||||||
qint16 * end (samples + numFrames * (bytesPerFrame () / sizeof (qint16)));
|
qint16 * end (samples + numFrames * (bytesPerFrame () / sizeof (qint16)));
|
||||||
|
|
||||||
// qDebug () << "Modulator: " << numFrames << " requested, m_ic = " << m_ic << ", tune mode is " << m_tuning;
|
// qDebug () << "Modulator: " << numFrames << " requested, m_ic = " << m_ic << ", tune mode is " << m_tuning;
|
||||||
// qDebug() << "C" << maxSize << numFrames << bytesPerFrame();
|
// qDebug() << "C" << maxSize << numFrames << bytesPerFrame();
|
||||||
switch (m_state)
|
switch (m_state)
|
||||||
{
|
{
|
||||||
case Synchronizing:
|
case Synchronizing:
|
||||||
|
@ -152,8 +183,9 @@ qint64 Modulator::readData (char * data, qint64 maxSize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (j > static_cast<unsigned> (icw[0])) {
|
if (j > static_cast<unsigned> (icw[0]))
|
||||||
Q_EMIT stateChanged ((m_state = Idle));
|
{
|
||||||
|
close ();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_framesSent += framesGenerated;
|
m_framesSent += framesGenerated;
|
||||||
|
@ -212,7 +244,6 @@ qint64 Modulator::readData (char * data, qint64 maxSize)
|
||||||
m_framesSent += numFrames;
|
m_framesSent += numFrames;
|
||||||
return numFrames * bytesPerFrame ();
|
return numFrames * bytesPerFrame ();
|
||||||
}
|
}
|
||||||
Q_EMIT stateChanged ((m_state = Idle));
|
|
||||||
// fall through
|
// fall through
|
||||||
|
|
||||||
case Idle:
|
case Idle:
|
||||||
|
@ -220,6 +251,8 @@ qint64 Modulator::readData (char * data, qint64 maxSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_ASSERT (Idle == m_state);
|
Q_ASSERT (Idle == m_state);
|
||||||
|
close ();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,7 @@
|
||||||
|
|
||||||
#include "AudioDevice.hpp"
|
#include "AudioDevice.hpp"
|
||||||
|
|
||||||
#ifdef UNIX
|
class QAudioOutput;
|
||||||
# define NUM_CHANNELS 2
|
|
||||||
#else
|
|
||||||
# define NUM_CHANNELS 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Input device that generates PCM audio frames that encode a message
|
// 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
|
// Output can be muted while underway, preserving waveform timing when
|
||||||
// transmission is resumed.
|
// transmission is resumed.
|
||||||
//
|
//
|
||||||
class Modulator : public AudioDevice
|
class Modulator
|
||||||
|
: public AudioDevice
|
||||||
{
|
{
|
||||||
Q_OBJECT;
|
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:
|
public:
|
||||||
enum ModulatorState {Synchronizing, Active, Idle};
|
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 isTuning () const {return m_tuning;}
|
||||||
bool isMuted () const {return m_muted;}
|
bool isMuted () const {return m_muted;}
|
||||||
|
@ -37,6 +30,13 @@ public:
|
||||||
bool isActive () const {return m_state != Idle;}
|
bool isActive () const {return m_state != Idle;}
|
||||||
void setWide9(double d1, double d2) {m_toneSpacing=d1; m_fSpread=d2;}
|
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:
|
protected:
|
||||||
qint64 readData (char * data, qint64 maxSize);
|
qint64 readData (char * data, qint64 maxSize);
|
||||||
qint64 writeData (char const * /* data */, qint64 /* maxSize */)
|
qint64 writeData (char const * /* data */, qint64 /* maxSize */)
|
||||||
|
@ -44,24 +44,11 @@ protected:
|
||||||
return -1; // we don't consume data
|
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:
|
private:
|
||||||
qint16 postProcessSample (qint16 sample) const;
|
qint16 postProcessSample (qint16 sample) const;
|
||||||
|
|
||||||
|
QAudioOutput * m_stream;
|
||||||
|
|
||||||
unsigned m_symbolsLength;
|
unsigned m_symbolsLength;
|
||||||
|
|
||||||
static double const m_twoPi;
|
static double const m_twoPi;
|
||||||
|
@ -80,8 +67,8 @@ private:
|
||||||
qint64 m_silentFrames;
|
qint64 m_silentFrames;
|
||||||
qint64 m_framesSent;
|
qint64 m_framesSent;
|
||||||
|
|
||||||
int m_frameRate;
|
unsigned m_frameRate;
|
||||||
int m_period;
|
unsigned m_period;
|
||||||
ModulatorState volatile m_state;
|
ModulatorState volatile m_state;
|
||||||
|
|
||||||
bool volatile m_tuning;
|
bool volatile m_tuning;
|
||||||
|
|
1
about.h
1
about.h
|
@ -1,3 +1,4 @@
|
||||||
|
// -*- Mode: C++ -*-
|
||||||
#ifndef ABOUTDLG_H
|
#ifndef ABOUTDLG_H
|
||||||
#define ABOUTDLG_H
|
#define ABOUTDLG_H
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// -*- Mode: C++ -*-
|
||||||
/*
|
/*
|
||||||
* Class to handle the formatted string as returned from the fortran decoder
|
* Class to handle the formatted string as returned from the fortran decoder
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// -*- Mode: C++ -*-
|
||||||
#ifndef DISPLAYTEXT_H
|
#ifndef DISPLAYTEXT_H
|
||||||
#define DISPLAYTEXT_H
|
#define DISPLAYTEXT_H
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// -*- Mode: C++ -*-
|
||||||
#ifndef GETFILE_H
|
#ifndef GETFILE_H
|
||||||
#define GETFILE_H
|
#define GETFILE_H
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
1
logqso.h
1
logqso.h
|
@ -1,3 +1,4 @@
|
||||||
|
// -*- Mode: C++ -*-
|
||||||
#ifndef LogQSO_H
|
#ifndef LogQSO_H
|
||||||
#define LogQSO_H
|
#define LogQSO_H
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,6 @@ int icw[NUM_CW_SYMBOLS]; //Dits for CW ID
|
||||||
|
|
||||||
int outBufSize;
|
int outBufSize;
|
||||||
int rc;
|
int rc;
|
||||||
qint32 g_COMportOpen;
|
|
||||||
qint32 g_iptt;
|
qint32 g_iptt;
|
||||||
static int nc1=1;
|
static int nc1=1;
|
||||||
wchar_t buffer[256];
|
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
|
connect (m_audioThread, &QThread::finished, m_audioThread, &QThread::deleteLater); // disposal
|
||||||
|
|
||||||
// hook up sound output stream slots & signals
|
// 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, &MainWindow::initializeAudioOutputStream, &m_soundOutput, &SoundOutput::setFormat);
|
||||||
connect (this, SIGNAL (stopAudioOutputStream ()), &m_soundOutput, SLOT (stopStream ()));
|
|
||||||
connect (&m_soundOutput, &SoundOutput::error, this, &MainWindow::showSoundOutError);
|
connect (&m_soundOutput, &SoundOutput::error, this, &MainWindow::showSoundOutError);
|
||||||
// connect (&m_soundOutput, &SoundOutput::status, this, &MainWindow::showStatusMessage);
|
// 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
|
// hook up Modulator slots
|
||||||
connect (this, SIGNAL (muteAudioOutput (bool)), &m_modulator, SLOT (mute (bool)));
|
connect (this, &MainWindow::muteAudioOutput, &m_modulator, &Modulator::mute);
|
||||||
connect (this, SIGNAL(transmitFrequency (unsigned)), &m_modulator, SLOT (setFrequency (unsigned)));
|
connect (this, &MainWindow::transmitFrequency, &m_modulator, &Modulator::setFrequency);
|
||||||
connect (this, SIGNAL (endTransmitMessage ()), &m_modulator, SLOT (close ()));
|
connect (this, &MainWindow::endTransmitMessage, &m_modulator, &Modulator::stop);
|
||||||
connect (this, SIGNAL (tune (bool)), &m_modulator, SLOT (tune (bool)));
|
connect (this, &MainWindow::tune, &m_modulator, &Modulator::tune);
|
||||||
connect (this, SIGNAL (sendMessage (unsigned, double, unsigned, AudioDevice::Channel, bool, double))
|
connect (this, &MainWindow::sendMessage, &m_modulator, &Modulator::start);
|
||||||
, &m_modulator, SLOT (open (unsigned, double, unsigned, AudioDevice::Channel, bool, double)));
|
|
||||||
|
|
||||||
// hook up the audio input stream
|
// hook up the audio input stream
|
||||||
connect (this, SIGNAL (startAudioInputStream (QAudioDeviceInfo const&, unsigned, int, QIODevice *, unsigned))
|
connect (this, &MainWindow::startAudioInputStream, &m_soundInput, &SoundInput::start);
|
||||||
, &m_soundInput, SLOT (start (QAudioDeviceInfo const&, unsigned, int, QIODevice *, unsigned)));
|
|
||||||
connect (this, SIGNAL (stopAudioInputStream ()), &m_soundInput, SLOT (stop ()));
|
|
||||||
|
|
||||||
connect (this, &MainWindow::finished, &m_soundInput, &SoundInput::stop);
|
connect (this, &MainWindow::finished, &m_soundInput, &SoundInput::stop);
|
||||||
|
|
||||||
connect (this, &MainWindow::finished, this, &MainWindow::close);
|
connect (this, &MainWindow::finished, this, &MainWindow::close);
|
||||||
|
|
||||||
connect(&m_soundInput, SIGNAL (error (QString)), this, SLOT (showSoundInError (QString)));
|
connect(&m_soundInput, &SoundInput::error, this, &MainWindow::showSoundInError);
|
||||||
// connect(&m_soundInput, SIGNAL(status(QString)), this, SLOT(showStatusMessage(QString)));
|
// connect(&m_soundInput, &SoundInput::status, this, &MainWindow::showStatusMessage);
|
||||||
|
|
||||||
// hook up the detector
|
// hook up the detector
|
||||||
connect (this, SIGNAL (startDetector (AudioDevice::Channel)), &m_detector, SLOT (open (AudioDevice::Channel)));
|
connect (this, &MainWindow::detectorSetMonitoring, &m_detector, &Detector::setMonitoring);
|
||||||
connect (this, SIGNAL (detectorSetMonitoring (bool)), &m_detector, SLOT (setMonitoring (bool)));
|
connect(&m_detector, &Detector::framesWritten, this, &MainWindow::dataSink);
|
||||||
connect (this, SIGNAL (detectorClose ()), &m_detector, SLOT (close ()));
|
|
||||||
|
|
||||||
connect(&m_detector, SIGNAL (framesWritten (qint64)), this, SLOT (dataSink (qint64)));
|
|
||||||
|
|
||||||
// setup the waterfall
|
// setup the waterfall
|
||||||
connect(m_wideGraph.data (), SIGNAL(freezeDecode2(int)),this,
|
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 = new QTimer(this);
|
||||||
ptt0Timer->setSingleShot(true);
|
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()));
|
connect(ptt0Timer, SIGNAL(timeout()), this, SLOT(stopTx2()));
|
||||||
ptt1Timer = new QTimer(this);
|
ptt1Timer = new QTimer(this);
|
||||||
ptt1Timer->setSingleShot(true);
|
ptt1Timer->setSingleShot(true);
|
||||||
|
@ -293,7 +285,7 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
|
||||||
|
|
||||||
tuneButtonTimer= new QTimer(this);
|
tuneButtonTimer= new QTimer(this);
|
||||||
tuneButtonTimer->setSingleShot(true);
|
tuneButtonTimer->setSingleShot(true);
|
||||||
connect (tuneButtonTimer, SIGNAL (timeout ()), &m_modulator, SLOT (close ()));
|
connect (tuneButtonTimer, &QTimer::timeout, &m_modulator, &Modulator::stop);
|
||||||
connect(tuneButtonTimer, SIGNAL(timeout()), this,
|
connect(tuneButtonTimer, SIGNAL(timeout()), this,
|
||||||
SLOT(on_stopTxButton_clicked()));
|
SLOT(on_stopTxButton_clicked()));
|
||||||
|
|
||||||
|
@ -328,7 +320,6 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
|
||||||
m_inGain=0;
|
m_inGain=0;
|
||||||
m_dataAvailable=false;
|
m_dataAvailable=false;
|
||||||
g_iptt=0;
|
g_iptt=0;
|
||||||
g_COMportOpen=0;
|
|
||||||
m_secID=0;
|
m_secID=0;
|
||||||
m_blankLine=false;
|
m_blankLine=false;
|
||||||
m_decodedText2=false;
|
m_decodedText2=false;
|
||||||
|
@ -423,26 +414,13 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
|
||||||
watcher2 = new QFutureWatcher<void>;
|
watcher2 = new QFutureWatcher<void>;
|
||||||
connect(watcher2, SIGNAL(finished()),this,SLOT(diskWriteFinished()));
|
connect(watcher2, SIGNAL(finished()),this,SLOT(diskWriteFinished()));
|
||||||
|
|
||||||
Q_EMIT startDetector (m_config.audio_input_channel ());
|
Q_EMIT startAudioInputStream (m_config.audio_input_device (), m_framesAudioInputBuffered, &m_detector, m_downSampleFactor, 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 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 transmitFrequency (m_txFreq - m_XIT);
|
||||||
Q_EMIT muteAudioOutput (false);
|
Q_EMIT muteAudioOutput (false);
|
||||||
|
|
||||||
// Create "m_worked", a dictionary of all calls in wsjtx.log
|
auto t = "UTC dB DT Freq Message";
|
||||||
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";
|
|
||||||
ui->decodedTextLabel->setText(t);
|
ui->decodedTextLabel->setText(t);
|
||||||
ui->decodedTextLabel2->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_9->setStyleSheet("QLabel{background-color: #aabec8}");
|
||||||
ui->label_10->setStyleSheet("QLabel{background-color: #aabec8}");
|
ui->label_10->setStyleSheet("QLabel{background-color: #aabec8}");
|
||||||
ui->labUTC->setStyleSheet( \
|
ui->labUTC->setStyleSheet("QLabel { background-color : black; color : yellow; }");
|
||||||
"QLabel { background-color : black; color : yellow; }");
|
ui->labDialFreq->setStyleSheet("QLabel { background-color : black; color : yellow; }");
|
||||||
ui->labDialFreq->setStyleSheet( \
|
|
||||||
"QLabel { background-color : black; color : yellow; }");
|
|
||||||
|
|
||||||
m_config.transceiver_online (true);
|
m_config.transceiver_online (true);
|
||||||
qsy (m_lastMonitoredFrequency);
|
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_mode=="JT9W-1") m_toneSpacing=pow(2,m_config.jt9w_bw_mult ())*12000.0/6912.0;
|
||||||
|
|
||||||
if(m_config.restart_audio_input ()) {
|
if(m_config.restart_audio_input ()) {
|
||||||
Q_EMIT stopAudioInputStream ();
|
Q_EMIT startAudioInputStream (m_config.audio_input_device (), m_framesAudioInputBuffered, &m_detector, m_downSampleFactor, m_config.audio_input_channel ());
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
if(m_config.restart_audio_output ()) {
|
if(m_config.restart_audio_output ()) {
|
||||||
Q_EMIT stopAudioOutputStream ();
|
Q_EMIT initializeAudioOutputStream (m_config.audio_output_device (), AudioDevice::Mono == m_config.audio_output_channel () ? 1 : 2, m_msAudioOutputBuffered);
|
||||||
Q_EMIT startAudioOutputStream (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");
|
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 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
|
else
|
||||||
{
|
{
|
||||||
|
@ -1431,7 +1402,6 @@ void MainWindow::guiUpdate()
|
||||||
static char msgsent[29];
|
static char msgsent[29];
|
||||||
static int nsendingsh=0;
|
static int nsendingsh=0;
|
||||||
static int giptt00=-1;
|
static int giptt00=-1;
|
||||||
static int gcomport00=-1;
|
|
||||||
static double onAirFreq0=0.0;
|
static double onAirFreq0=0.0;
|
||||||
QString rt;
|
QString rt;
|
||||||
|
|
||||||
|
@ -1670,9 +1640,8 @@ void MainWindow::guiUpdate()
|
||||||
m_sec0=nsec;
|
m_sec0=nsec;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(g_iptt!=giptt00 or g_COMportOpen!=gcomport00) {
|
if(g_iptt!=giptt00) {
|
||||||
giptt00=g_iptt;
|
giptt00=g_iptt;
|
||||||
gcomport00=g_COMportOpen;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iptt0=g_iptt;
|
iptt0=g_iptt;
|
||||||
|
@ -1706,7 +1675,6 @@ void MainWindow::startTx2()
|
||||||
void MainWindow::stopTx()
|
void MainWindow::stopTx()
|
||||||
{
|
{
|
||||||
Q_EMIT endTransmitMessage ();
|
Q_EMIT endTransmitMessage ();
|
||||||
Q_EMIT stopAudioOutputStream ();
|
|
||||||
m_transmitting=false;
|
m_transmitting=false;
|
||||||
if ("JT9+JT65" == m_mode) ui->pbTxMode->setEnabled(true);
|
if ("JT9+JT65" == m_mode) ui->pbTxMode->setEnabled(true);
|
||||||
g_iptt=0;
|
g_iptt=0;
|
||||||
|
@ -2859,13 +2827,12 @@ void MainWindow::transmit (double snr)
|
||||||
{
|
{
|
||||||
if (m_modeTx == "JT65")
|
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
|
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)
|
void MainWindow::on_outAttenuation_valueChanged (int a)
|
||||||
|
|
28
mainwindow.h
28
mainwindow.h
|
@ -1,3 +1,4 @@
|
||||||
|
// -*- Mode: C++ -*-
|
||||||
#ifndef MAINWINDOW_H
|
#ifndef MAINWINDOW_H
|
||||||
#define MAINWINDOW_H
|
#define MAINWINDOW_H
|
||||||
#ifdef QT5
|
#ifdef QT5
|
||||||
|
@ -13,6 +14,7 @@
|
||||||
#include <QScopedPointer>
|
#include <QScopedPointer>
|
||||||
|
|
||||||
#include "soundin.h"
|
#include "soundin.h"
|
||||||
|
#include "AudioDevice.hpp"
|
||||||
#include "soundout.h"
|
#include "soundout.h"
|
||||||
#include "commons.h"
|
#include "commons.h"
|
||||||
#include "Radio.hpp"
|
#include "Radio.hpp"
|
||||||
|
@ -46,6 +48,7 @@ class WideGraph;
|
||||||
class LogQSO;
|
class LogQSO;
|
||||||
class Transceiver;
|
class Transceiver;
|
||||||
class Astro;
|
class Astro;
|
||||||
|
class QAudioOutput;
|
||||||
|
|
||||||
class MainWindow : public QMainWindow
|
class MainWindow : public QMainWindow
|
||||||
{
|
{
|
||||||
|
@ -175,11 +178,10 @@ private slots:
|
||||||
private:
|
private:
|
||||||
void enable_DXCC_entity (bool on);
|
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 stopAudioOutputStream () const;
|
||||||
|
|
||||||
Q_SIGNAL void startAudioInputStream (QAudioDeviceInfo const&, unsigned channels, int framesPerBuffer, QIODevice * sink, unsigned downSampleFactor) const;
|
Q_SIGNAL void startAudioInputStream (QAudioDeviceInfo const&, int framesPerBuffer, AudioDevice * sink, unsigned downSampleFactor, AudioDevice::Channel) const;
|
||||||
Q_SIGNAL void stopAudioInputStream () const;
|
|
||||||
|
|
||||||
Q_SIGNAL void startDetector (AudioDevice::Channel) const;
|
Q_SIGNAL void startDetector (AudioDevice::Channel) const;
|
||||||
Q_SIGNAL void detectorSetMonitoring (bool) const;
|
Q_SIGNAL void detectorSetMonitoring (bool) const;
|
||||||
|
@ -190,7 +192,7 @@ private:
|
||||||
Q_SIGNAL void transmitFrequency (unsigned) const;
|
Q_SIGNAL void transmitFrequency (unsigned) const;
|
||||||
Q_SIGNAL void endTransmitMessage () const;
|
Q_SIGNAL void endTransmitMessage () const;
|
||||||
Q_SIGNAL void tune (bool = true) 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;
|
Q_SIGNAL void outAttenuationChanged (qreal) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -370,7 +372,7 @@ private:
|
||||||
Frequency m_lastMonitoredFrequency;
|
Frequency m_lastMonitoredFrequency;
|
||||||
double m_toneSpacing;
|
double m_toneSpacing;
|
||||||
|
|
||||||
//---------------------------------------------------- private functions
|
//---------------------------------------------------- private functions
|
||||||
void readSettings();
|
void readSettings();
|
||||||
void setDecodedTextFont (QFont const&);
|
void setDecodedTextFont (QFont const&);
|
||||||
void writeSettings();
|
void writeSettings();
|
||||||
|
@ -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 int ptt(int nport, int ntx, int* iptt, int* nopen);
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
//----------------------------------------------------- C and Fortran routines
|
//----------------------------------------------------- C and Fortran routines
|
||||||
void symspec_(int* k, int* ntrperiod, int* nsps, int* ingain, int* nflatten,
|
void symspec_(int* k, int* ntrperiod, int* nsps, int* ingain, int* nflatten,
|
||||||
float* px, float s[], float* df3, int* nhsym, int* npts8);
|
float* px, float s[], float* df3, int* nhsym, int* npts8);
|
||||||
|
|
||||||
void genjt9_(char* msg, int* ichk, char* msgsent, int itone[],
|
void genjt9_(char* msg, int* ichk, char* msgsent, int itone[],
|
||||||
int* itext, int len1, int len2);
|
int* itext, int len1, int len2);
|
||||||
|
|
||||||
void gen65_(char* msg, int* ichk, char* msgsent, int itone[],
|
void gen65_(char* msg, int* ichk, char* msgsent, int itone[],
|
||||||
int* itext, int len1, int len2);
|
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,
|
void azdist_(char* MyGrid, char* HisGrid, double* utch, int* nAz, int* nEl,
|
||||||
int* nDmiles, int* nDkm, int* nHotAz, int* nHotABetter,
|
int* nDmiles, int* nDkm, int* nHotAz, int* nHotABetter,
|
||||||
int len1, int len2);
|
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// -*- Mode: C++ -*-
|
||||||
#ifndef METERWIDGET_H
|
#ifndef METERWIDGET_H
|
||||||
#define METERWIDGET_H
|
#define METERWIDGET_H
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// -*- Mode: C++ -*-
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Some code in this file and accompanying files is based on work by
|
// Some code in this file and accompanying files is based on work by
|
||||||
// Moe Wheatley, AE4Y, released under the "Simplified BSD License".
|
// Moe Wheatley, AE4Y, released under the "Simplified BSD License".
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// -*- Mode: C++ -*-
|
||||||
#ifndef PSK_REPORTER_H
|
#ifndef PSK_REPORTER_H
|
||||||
#define PSK_REPORTER_H
|
#define PSK_REPORTER_H
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// -*- Mode: C++ -*-
|
||||||
#ifndef SIGNALMETER_H
|
#ifndef SIGNALMETER_H
|
||||||
#define SIGNALMETER_H
|
#define SIGNALMETER_H
|
||||||
|
|
||||||
|
|
1
sleep.h
1
sleep.h
|
@ -1,3 +1,4 @@
|
||||||
|
// -*- Mode: C++ -*-
|
||||||
#ifndef SLEEP_H
|
#ifndef SLEEP_H
|
||||||
#define SLEEP_H
|
#define SLEEP_H
|
||||||
#include <qthread.h>
|
#include <qthread.h>
|
||||||
|
|
23
soundin.cpp
23
soundin.cpp
|
@ -40,15 +40,16 @@ bool SoundInput::audioError () const
|
||||||
return result;
|
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);
|
Q_ASSERT (sink);
|
||||||
|
|
||||||
stop();
|
stop ();
|
||||||
|
|
||||||
|
m_sink = sink;
|
||||||
|
|
||||||
QAudioFormat format (device.preferredFormat());
|
QAudioFormat format (device.preferredFormat());
|
||||||
format.setChannelCount (channels);
|
format.setChannelCount (AudioDevice::Mono == channel ? 1 : 2);
|
||||||
format.setCodec ("audio/pcm");
|
format.setCodec ("audio/pcm");
|
||||||
format.setSampleRate (12000 * downSampleFactor);
|
format.setSampleRate (12000 * downSampleFactor);
|
||||||
format.setSampleType (QAudioFormat::SignedInt);
|
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);
|
connect (m_stream.data(), &QAudioInput::stateChanged, this, &SoundInput::handleStateChanged);
|
||||||
|
|
||||||
m_stream->setBufferSize (m_stream->format ().bytesForFrames (framesPerBuffer));
|
m_stream->setBufferSize (m_stream->format ().bytesForFrames (framesPerBuffer));
|
||||||
|
if (sink->initialize (QIODevice::WriteOnly, channel))
|
||||||
|
{
|
||||||
m_stream->start (sink);
|
m_stream->start (sink);
|
||||||
audioError ();
|
audioError ();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Q_EMIT error (tr ("Failed to initialize audio sink device"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundInput::handleStateChanged (QAudio::State newState) const
|
void SoundInput::handleStateChanged (QAudio::State newState) const
|
||||||
|
@ -115,8 +124,14 @@ void SoundInput::stop()
|
||||||
m_stream->stop ();
|
m_stream->stop ();
|
||||||
}
|
}
|
||||||
m_stream.reset ();
|
m_stream.reset ();
|
||||||
|
|
||||||
|
if (m_sink)
|
||||||
|
{
|
||||||
|
m_sink->close ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundInput::~SoundInput ()
|
SoundInput::~SoundInput ()
|
||||||
{
|
{
|
||||||
|
stop ();
|
||||||
}
|
}
|
||||||
|
|
21
soundin.h
21
soundin.h
|
@ -1,3 +1,4 @@
|
||||||
|
// -*- Mode: C++ -*-
|
||||||
#ifndef SOUNDIN_H__
|
#ifndef SOUNDIN_H__
|
||||||
#define SOUNDIN_H__
|
#define SOUNDIN_H__
|
||||||
|
|
||||||
|
@ -6,9 +7,10 @@
|
||||||
#include <QScopedPointer>
|
#include <QScopedPointer>
|
||||||
#include <QAudioInput>
|
#include <QAudioInput>
|
||||||
|
|
||||||
|
#include "AudioDevice.hpp"
|
||||||
|
|
||||||
class QAudioDeviceInfo;
|
class QAudioDeviceInfo;
|
||||||
class QAudioInput;
|
class QAudioInput;
|
||||||
class QIODevice;
|
|
||||||
|
|
||||||
// Gets audio data from sound sample source and passes it to a sink device
|
// Gets audio data from sound sample source and passes it to a sink device
|
||||||
class SoundInput
|
class SoundInput
|
||||||
|
@ -16,28 +18,31 @@ class SoundInput
|
||||||
{
|
{
|
||||||
Q_OBJECT;
|
Q_OBJECT;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SoundInput (QObject * parent = 0)
|
SoundInput (QObject * parent = nullptr)
|
||||||
: QObject (parent)
|
: QObject {parent}
|
||||||
|
, m_sink {nullptr}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
~SoundInput ();
|
~SoundInput ();
|
||||||
|
|
||||||
// sink must exist from the start call to any following stop () call
|
// sink must exist from the start call until the next start call or
|
||||||
Q_SLOT void start(QAudioDeviceInfo const&, unsigned channels, int framesPerBuffer, QIODevice * sink, unsigned downSampleFactor);
|
// stop call
|
||||||
Q_SLOT void stop();
|
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 error (QString message) const;
|
||||||
Q_SIGNAL void status (QString message) const;
|
Q_SIGNAL void status (QString message) const;
|
||||||
|
|
||||||
|
private:
|
||||||
// used internally
|
// used internally
|
||||||
Q_SLOT void handleStateChanged (QAudio::State) const;
|
Q_SLOT void handleStateChanged (QAudio::State) const;
|
||||||
|
|
||||||
bool audioError () const;
|
bool audioError () const;
|
||||||
|
|
||||||
QScopedPointer<QAudioInput> m_stream;
|
QScopedPointer<QAudioInput> m_stream;
|
||||||
|
AudioDevice * m_sink;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
27
soundout.cpp
27
soundout.cpp
|
@ -54,8 +54,7 @@ SoundOutput::SoundOutput (QIODevice * source)
|
||||||
Q_ASSERT (source);
|
Q_ASSERT (source);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundOutput::startStream (QAudioDeviceInfo const& device, \
|
void SoundOutput::setFormat (QAudioDeviceInfo const& device, unsigned channels, unsigned msBuffered)
|
||||||
unsigned channels, unsigned msBuffered)
|
|
||||||
{
|
{
|
||||||
Q_ASSERT (0 < channels && channels < 3);
|
Q_ASSERT (0 < channels && channels < 3);
|
||||||
|
|
||||||
|
@ -83,11 +82,10 @@ void SoundOutput::startStream (QAudioDeviceInfo const& device, \
|
||||||
m_stream->setVolume (m_volume);
|
m_stream->setVolume (m_volume);
|
||||||
m_stream->setNotifyInterval(100);
|
m_stream->setNotifyInterval(100);
|
||||||
|
|
||||||
connect (m_stream.data(), &QAudioOutput::stateChanged, this, \
|
connect (m_stream.data(), &QAudioOutput::stateChanged, this, &SoundOutput::handleStateChanged);
|
||||||
&SoundOutput::handleStateChanged);
|
|
||||||
|
|
||||||
m_currentDevice = device;
|
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
|
// we have to set this before every start on the stream because the
|
||||||
// Windows implementation seems to forget the buffer size after a
|
// Windows implementation seems to forget the buffer size after a
|
||||||
// stop.
|
// stop.
|
||||||
m_stream->setBufferSize (m_stream->format().bytesForDuration(
|
m_stream->setBufferSize (m_stream->format().bytesForDuration((msBuffered ? msBuffered : MS_BUFFERED) * 1000));
|
||||||
(msBuffered ? msBuffered : MS_BUFFERED) * 1000));
|
// qDebug() << "B" << m_stream->bufferSize() << m_stream->periodSize() << m_stream->notifyInterval();
|
||||||
// qDebug() << "B" << m_stream->bufferSize() << m_stream->periodSize() << m_stream->notifyInterval();
|
|
||||||
|
|
||||||
m_stream->start (m_source);
|
|
||||||
audioError ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundOutput::suspend ()
|
void SoundOutput::suspend ()
|
||||||
|
@ -138,7 +132,7 @@ void SoundOutput::setAttenuation (qreal a)
|
||||||
{
|
{
|
||||||
Q_ASSERT (0. <= a && a <= 99.);
|
Q_ASSERT (0. <= a && a <= 99.);
|
||||||
m_volume = qPow (10., -a / 10.);
|
m_volume = qPow (10., -a / 10.);
|
||||||
// qDebug () << "SoundOut: attn = " << a << ", vol = " << m_volume;
|
// qDebug () << "SoundOut: attn = " << a << ", vol = " << m_volume;
|
||||||
if (m_stream)
|
if (m_stream)
|
||||||
{
|
{
|
||||||
m_stream->setVolume (m_volume);
|
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)
|
void SoundOutput::handleStateChanged (QAudio::State newState)
|
||||||
{
|
{
|
||||||
switch (newState)
|
switch (newState)
|
||||||
|
|
18
soundout.h
18
soundout.h
|
@ -1,3 +1,4 @@
|
||||||
|
// -*- Mode: C++ -*-
|
||||||
#ifndef SOUNDOUT_H__
|
#ifndef SOUNDOUT_H__
|
||||||
#define SOUNDOUT_H__
|
#define SOUNDOUT_H__
|
||||||
|
|
||||||
|
@ -18,35 +19,32 @@ class SoundOutput
|
||||||
Q_PROPERTY(bool running READ isRunning);
|
Q_PROPERTY(bool running READ isRunning);
|
||||||
Q_PROPERTY(unsigned attenuation READ attenuation WRITE setAttenuation RESET resetAttenuation);
|
Q_PROPERTY(unsigned attenuation READ attenuation WRITE setAttenuation RESET resetAttenuation);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SoundOutput (QIODevice * source);
|
SoundOutput (QIODevice * source);
|
||||||
~SoundOutput ();
|
~SoundOutput ();
|
||||||
|
|
||||||
bool isRunning() const {return m_active;}
|
bool isRunning() const {return m_active;}
|
||||||
qreal attenuation () const;
|
qreal attenuation () const;
|
||||||
|
QAudioOutput * stream () {return m_stream.data ();}
|
||||||
|
|
||||||
private Q_SLOTS:
|
public Q_SLOTS:
|
||||||
/* private because we expect to run in a thread and don't want direct
|
void setFormat (QAudioDeviceInfo const& device, unsigned channels, unsigned msBuffered = 0u);
|
||||||
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);
|
|
||||||
void suspend ();
|
void suspend ();
|
||||||
void resume ();
|
void resume ();
|
||||||
void stopStream ();
|
|
||||||
void setAttenuation (qreal); /* unsigned */
|
void setAttenuation (qreal); /* unsigned */
|
||||||
void resetAttenuation (); /* to zero */
|
void resetAttenuation (); /* to zero */
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void error (QString message) const;
|
void error (QString message) const;
|
||||||
void status (QString message) const;
|
void status (QString message) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool audioError () const;
|
bool audioError () const;
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void handleStateChanged (QAudio::State);
|
void handleStateChanged (QAudio::State);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QScopedPointer<QAudioOutput> m_stream;
|
QScopedPointer<QAudioOutput> m_stream;
|
||||||
|
|
||||||
QIODevice * m_source;
|
QIODevice * m_source;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// -*- Mode: C++ -*-
|
||||||
#ifndef WIDEGRAPH_H
|
#ifndef WIDEGRAPH_H
|
||||||
#define WIDEGRAPH_H
|
#define WIDEGRAPH_H
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue