mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2025-02-03 09:44:24 -05:00
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
025bfe52d6
commit
5eb5735168
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;}
|
||||
|
||||
|
13
Detector.hpp
13
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;
|
||||
|
||||
|
@ -24,26 +24,30 @@ 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;
|
||||
|
||||
if (m_state != Idle)
|
||||
{
|
||||
stop ();
|
||||
}
|
||||
|
||||
// qDebug () << "Modulator: Using soft keying for CW is " << SOFT_KEYING;;
|
||||
|
||||
m_symbolsLength = symbolsLength;
|
||||
@ -73,9 +77,36 @@ void Modulator::open (unsigned symbolsLength, double framesPerSymbol, \
|
||||
|
||||
// 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));
|
||||
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)
|
||||
@ -152,8 +183,9 @@ qint64 Modulator::readData (char * data, qint64 maxSize)
|
||||
}
|
||||
}
|
||||
|
||||
if (j > static_cast<unsigned> (icw[0])) {
|
||||
Q_EMIT stateChanged ((m_state = Idle));
|
||||
if (j > static_cast<unsigned> (icw[0]))
|
||||
{
|
||||
close ();
|
||||
}
|
||||
|
||||
m_framesSent += framesGenerated;
|
||||
@ -212,7 +244,6 @@ qint64 Modulator::readData (char * data, qint64 maxSize)
|
||||
m_framesSent += numFrames;
|
||||
return numFrames * bytesPerFrame ();
|
||||
}
|
||||
Q_EMIT stateChanged ((m_state = Idle));
|
||||
// fall through
|
||||
|
||||
case Idle:
|
||||
@ -220,6 +251,8 @@ qint64 Modulator::readData (char * data, qint64 maxSize)
|
||||
}
|
||||
|
||||
Q_ASSERT (Idle == m_state);
|
||||
close ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -1,3 +1,4 @@
|
||||
// -*- Mode: C++ -*-
|
||||
/*
|
||||
* Class to handle the formatted string as returned from the fortran decoder
|
||||
*
|
||||
|
@ -1,3 +1,4 @@
|
||||
// -*- Mode: C++ -*-
|
||||
#ifndef DISPLAYTEXT_H
|
||||
#define DISPLAYTEXT_H
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
// -*- Mode: C++ -*-
|
||||
#ifndef GETFILE_H
|
||||
#define GETFILE_H
|
||||
#include <QString>
|
||||
|
@ -36,7 +36,6 @@ int icw[NUM_CW_SYMBOLS]; //Dits for CW ID
|
||||
|
||||
int outBufSize;
|
||||
int rc;
|
||||
qint32 g_COMportOpen;
|
||||
qint32 g_iptt;
|
||||
static int nc1=1;
|
||||
wchar_t buffer[256];
|
||||
@ -134,37 +133,30 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
|
||||
connect (m_audioThread, &QThread::finished, m_audioThread, &QThread::deleteLater); // disposal
|
||||
|
||||
// hook up sound output stream slots & signals
|
||||
connect (this, SIGNAL (startAudioOutputStream (QAudioDeviceInfo const&, unsigned, unsigned)), &m_soundOutput, SLOT (startStream (QAudioDeviceInfo const&, unsigned, unsigned)));
|
||||
connect (this, SIGNAL (stopAudioOutputStream ()), &m_soundOutput, SLOT (stopStream ()));
|
||||
connect (this, &MainWindow::initializeAudioOutputStream, &m_soundOutput, &SoundOutput::setFormat);
|
||||
connect (&m_soundOutput, &SoundOutput::error, this, &MainWindow::showSoundOutError);
|
||||
// connect (&m_soundOutput, &SoundOutput::status, this, &MainWindow::showStatusMessage);
|
||||
connect (this, SIGNAL (outAttenuationChanged (qreal)), &m_soundOutput, SLOT (setAttenuation (qreal)));
|
||||
connect (this, &MainWindow::outAttenuationChanged, &m_soundOutput, &SoundOutput::setAttenuation);
|
||||
|
||||
// hook up Modulator slots
|
||||
connect (this, SIGNAL (muteAudioOutput (bool)), &m_modulator, SLOT (mute (bool)));
|
||||
connect (this, SIGNAL(transmitFrequency (unsigned)), &m_modulator, SLOT (setFrequency (unsigned)));
|
||||
connect (this, SIGNAL (endTransmitMessage ()), &m_modulator, SLOT (close ()));
|
||||
connect (this, SIGNAL (tune (bool)), &m_modulator, SLOT (tune (bool)));
|
||||
connect (this, SIGNAL (sendMessage (unsigned, double, unsigned, AudioDevice::Channel, bool, double))
|
||||
, &m_modulator, SLOT (open (unsigned, double, unsigned, AudioDevice::Channel, bool, double)));
|
||||
connect (this, &MainWindow::muteAudioOutput, &m_modulator, &Modulator::mute);
|
||||
connect (this, &MainWindow::transmitFrequency, &m_modulator, &Modulator::setFrequency);
|
||||
connect (this, &MainWindow::endTransmitMessage, &m_modulator, &Modulator::stop);
|
||||
connect (this, &MainWindow::tune, &m_modulator, &Modulator::tune);
|
||||
connect (this, &MainWindow::sendMessage, &m_modulator, &Modulator::start);
|
||||
|
||||
// hook up the audio input stream
|
||||
connect (this, SIGNAL (startAudioInputStream (QAudioDeviceInfo const&, unsigned, int, QIODevice *, unsigned))
|
||||
, &m_soundInput, SLOT (start (QAudioDeviceInfo const&, unsigned, int, QIODevice *, unsigned)));
|
||||
connect (this, SIGNAL (stopAudioInputStream ()), &m_soundInput, SLOT (stop ()));
|
||||
|
||||
connect (this, &MainWindow::startAudioInputStream, &m_soundInput, &SoundInput::start);
|
||||
connect (this, &MainWindow::finished, &m_soundInput, &SoundInput::stop);
|
||||
|
||||
connect (this, &MainWindow::finished, this, &MainWindow::close);
|
||||
|
||||
connect(&m_soundInput, SIGNAL (error (QString)), this, SLOT (showSoundInError (QString)));
|
||||
// connect(&m_soundInput, SIGNAL(status(QString)), this, SLOT(showStatusMessage(QString)));
|
||||
connect(&m_soundInput, &SoundInput::error, this, &MainWindow::showSoundInError);
|
||||
// connect(&m_soundInput, &SoundInput::status, this, &MainWindow::showStatusMessage);
|
||||
|
||||
// hook up the detector
|
||||
connect (this, SIGNAL (startDetector (AudioDevice::Channel)), &m_detector, SLOT (open (AudioDevice::Channel)));
|
||||
connect (this, SIGNAL (detectorSetMonitoring (bool)), &m_detector, SLOT (setMonitoring (bool)));
|
||||
connect (this, SIGNAL (detectorClose ()), &m_detector, SLOT (close ()));
|
||||
|
||||
connect(&m_detector, SIGNAL (framesWritten (qint64)), this, SLOT (dataSink (qint64)));
|
||||
connect (this, &MainWindow::detectorSetMonitoring, &m_detector, &Detector::setMonitoring);
|
||||
connect(&m_detector, &Detector::framesWritten, this, &MainWindow::dataSink);
|
||||
|
||||
// setup the waterfall
|
||||
connect(m_wideGraph.data (), SIGNAL(freezeDecode2(int)),this,
|
||||
@ -281,7 +273,7 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
|
||||
|
||||
ptt0Timer = new QTimer(this);
|
||||
ptt0Timer->setSingleShot(true);
|
||||
connect (ptt0Timer, SIGNAL (timeout ()), &m_modulator, SLOT (close ()));
|
||||
connect (ptt0Timer, &QTimer::timeout, &m_modulator, &Modulator::stop);
|
||||
connect(ptt0Timer, SIGNAL(timeout()), this, SLOT(stopTx2()));
|
||||
ptt1Timer = new QTimer(this);
|
||||
ptt1Timer->setSingleShot(true);
|
||||
@ -293,7 +285,7 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
|
||||
|
||||
tuneButtonTimer= new QTimer(this);
|
||||
tuneButtonTimer->setSingleShot(true);
|
||||
connect (tuneButtonTimer, SIGNAL (timeout ()), &m_modulator, SLOT (close ()));
|
||||
connect (tuneButtonTimer, &QTimer::timeout, &m_modulator, &Modulator::stop);
|
||||
connect(tuneButtonTimer, SIGNAL(timeout()), this,
|
||||
SLOT(on_stopTxButton_clicked()));
|
||||
|
||||
@ -328,7 +320,6 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
|
||||
m_inGain=0;
|
||||
m_dataAvailable=false;
|
||||
g_iptt=0;
|
||||
g_COMportOpen=0;
|
||||
m_secID=0;
|
||||
m_blankLine=false;
|
||||
m_decodedText2=false;
|
||||
@ -423,26 +414,13 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
|
||||
watcher2 = new QFutureWatcher<void>;
|
||||
connect(watcher2, SIGNAL(finished()),this,SLOT(diskWriteFinished()));
|
||||
|
||||
Q_EMIT startDetector (m_config.audio_input_channel ());
|
||||
Q_EMIT startAudioInputStream (m_config.audio_input_device (), AudioDevice::Mono == m_config.audio_input_channel () ? 1 : 2, m_framesAudioInputBuffered, &m_detector, m_downSampleFactor);
|
||||
Q_EMIT startAudioInputStream (m_config.audio_input_device (), m_framesAudioInputBuffered, &m_detector, m_downSampleFactor, m_config.audio_input_channel ());
|
||||
Q_EMIT initializeAudioOutputStream (m_config.audio_output_device (), AudioDevice::Mono == m_config.audio_output_channel () ? 1 : 2, m_msAudioOutputBuffered);
|
||||
|
||||
Q_EMIT transmitFrequency (m_txFreq - m_XIT);
|
||||
Q_EMIT muteAudioOutput (false);
|
||||
|
||||
// Create "m_worked", a dictionary of all calls in wsjtx.log
|
||||
QFile f(m_config.data_path ().absoluteFilePath ("wsjtx.log"));
|
||||
f.open(QIODevice::ReadOnly | QIODevice::Text);
|
||||
QTextStream in(&f);
|
||||
QString line,t,callsign;
|
||||
for(int i=0; i<99999; i++) {
|
||||
line=in.readLine();
|
||||
if(line.length()<=0) break;
|
||||
t=line.mid(18,12);
|
||||
callsign=t.mid(0,t.indexOf(","));
|
||||
}
|
||||
f.close();
|
||||
|
||||
t="UTC dB DT Freq Message";
|
||||
auto t = "UTC dB DT Freq Message";
|
||||
ui->decodedTextLabel->setText(t);
|
||||
ui->decodedTextLabel2->setText(t);
|
||||
|
||||
@ -450,10 +428,8 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
|
||||
|
||||
ui->label_9->setStyleSheet("QLabel{background-color: #aabec8}");
|
||||
ui->label_10->setStyleSheet("QLabel{background-color: #aabec8}");
|
||||
ui->labUTC->setStyleSheet( \
|
||||
"QLabel { background-color : black; color : yellow; }");
|
||||
ui->labDialFreq->setStyleSheet( \
|
||||
"QLabel { background-color : black; color : yellow; }");
|
||||
ui->labUTC->setStyleSheet("QLabel { background-color : black; color : yellow; }");
|
||||
ui->labDialFreq->setStyleSheet("QLabel { background-color : black; color : yellow; }");
|
||||
|
||||
m_config.transceiver_online (true);
|
||||
qsy (m_lastMonitoredFrequency);
|
||||
@ -665,14 +641,10 @@ void MainWindow::on_actionSettings_triggered() //Setup Dialog
|
||||
if(m_mode=="JT9W-1") m_toneSpacing=pow(2,m_config.jt9w_bw_mult ())*12000.0/6912.0;
|
||||
|
||||
if(m_config.restart_audio_input ()) {
|
||||
Q_EMIT stopAudioInputStream ();
|
||||
Q_EMIT detectorClose ();
|
||||
Q_EMIT startDetector (m_config.audio_input_channel ());
|
||||
Q_EMIT startAudioInputStream (m_config.audio_input_device (), AudioDevice::Mono == m_config.audio_input_channel () ? 1 : 2, m_framesAudioInputBuffered, &m_detector, m_downSampleFactor);
|
||||
Q_EMIT startAudioInputStream (m_config.audio_input_device (), m_framesAudioInputBuffered, &m_detector, m_downSampleFactor, m_config.audio_input_channel ());
|
||||
}
|
||||
if(m_config.restart_audio_output ()) {
|
||||
Q_EMIT stopAudioOutputStream ();
|
||||
Q_EMIT startAudioOutputStream (m_config.audio_output_device (), AudioDevice::Mono == m_config.audio_output_channel () ? 1 : 2, m_msAudioOutputBuffered);
|
||||
Q_EMIT initializeAudioOutputStream (m_config.audio_output_device (), AudioDevice::Mono == m_config.audio_output_channel () ? 1 : 2, m_msAudioOutputBuffered);
|
||||
}
|
||||
|
||||
auto_tx_label->setText (m_config.quick_call () ? "Tx-Enable Armed" : "Tx-Enable Disarmed");
|
||||
@ -709,7 +681,6 @@ void MainWindow::on_monitorButton_clicked (bool checked)
|
||||
}
|
||||
|
||||
Q_EMIT detectorSetMonitoring (checked);
|
||||
// Q_EMIT startAudioInputStream (m_params.audio_input_device, AudioDevice::Mono == m_params.audio_input_channel ? 1 : 2, m_framesAudioInputBuffered, &m_detector, m_downSampleFactor);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1431,7 +1402,6 @@ void MainWindow::guiUpdate()
|
||||
static char msgsent[29];
|
||||
static int nsendingsh=0;
|
||||
static int giptt00=-1;
|
||||
static int gcomport00=-1;
|
||||
static double onAirFreq0=0.0;
|
||||
QString rt;
|
||||
|
||||
@ -1670,9 +1640,8 @@ void MainWindow::guiUpdate()
|
||||
m_sec0=nsec;
|
||||
}
|
||||
|
||||
if(g_iptt!=giptt00 or g_COMportOpen!=gcomport00) {
|
||||
if(g_iptt!=giptt00) {
|
||||
giptt00=g_iptt;
|
||||
gcomport00=g_COMportOpen;
|
||||
}
|
||||
|
||||
iptt0=g_iptt;
|
||||
@ -1706,7 +1675,6 @@ void MainWindow::startTx2()
|
||||
void MainWindow::stopTx()
|
||||
{
|
||||
Q_EMIT endTransmitMessage ();
|
||||
Q_EMIT stopAudioOutputStream ();
|
||||
m_transmitting=false;
|
||||
if ("JT9+JT65" == m_mode) ui->pbTxMode->setEnabled(true);
|
||||
g_iptt=0;
|
||||
@ -2859,13 +2827,12 @@ void MainWindow::transmit (double snr)
|
||||
{
|
||||
if (m_modeTx == "JT65")
|
||||
{
|
||||
Q_EMIT sendMessage (NUM_JT65_SYMBOLS, 4096.0 * 12000.0 / 11025.0, m_txFreq - m_XIT, m_config.audio_output_channel (), true, snr);
|
||||
Q_EMIT sendMessage (NUM_JT65_SYMBOLS, 4096.0 * 12000.0 / 11025.0, m_txFreq - m_XIT, m_soundOutput.stream (), m_config.audio_output_channel (), true, snr);
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_EMIT sendMessage (NUM_JT9_SYMBOLS, m_nsps, m_txFreq - m_XIT, m_config.audio_output_channel (), true, snr);
|
||||
Q_EMIT sendMessage (NUM_JT9_SYMBOLS, m_nsps, m_txFreq - m_XIT, m_soundOutput.stream (), m_config.audio_output_channel (), true, snr);
|
||||
}
|
||||
Q_EMIT startAudioOutputStream (m_config.audio_output_device (), AudioDevice::Mono == m_config.audio_output_channel () ? 1 : 2, m_msAudioOutputBuffered);
|
||||
}
|
||||
|
||||
void MainWindow::on_outAttenuation_valueChanged (int a)
|
||||
|
10
mainwindow.h
10
mainwindow.h
@ -1,3 +1,4 @@
|
||||
// -*- Mode: C++ -*-
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
#ifdef QT5
|
||||
@ -13,6 +14,7 @@
|
||||
#include <QScopedPointer>
|
||||
|
||||
#include "soundin.h"
|
||||
#include "AudioDevice.hpp"
|
||||
#include "soundout.h"
|
||||
#include "commons.h"
|
||||
#include "Radio.hpp"
|
||||
@ -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:
|
||||
|
@ -1,3 +1,4 @@
|
||||
// -*- Mode: C++ -*-
|
||||
#ifndef METERWIDGET_H
|
||||
#define METERWIDGET_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".
|
||||
|
@ -1,3 +1,4 @@
|
||||
// -*- Mode: C++ -*-
|
||||
#ifndef PSK_REPORTER_H
|
||||
#define PSK_REPORTER_H
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
// -*- Mode: C++ -*-
|
||||
#ifndef SIGNALMETER_H
|
||||
#define SIGNALMETER_H
|
||||
|
||||
|
1
sleep.h
1
sleep.h
@ -1,3 +1,4 @@
|
||||
// -*- Mode: C++ -*-
|
||||
#ifndef SLEEP_H
|
||||
#define SLEEP_H
|
||||
#include <qthread.h>
|
||||
|
21
soundin.cpp
21
soundin.cpp
@ -40,15 +40,16 @@ bool SoundInput::audioError () const
|
||||
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 ();
|
||||
|
||||
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,10 +75,18 @@ 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));
|
||||
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
|
||||
{
|
||||
@ -115,8 +124,14 @@ void SoundInput::stop()
|
||||
m_stream->stop ();
|
||||
}
|
||||
m_stream.reset ();
|
||||
|
||||
if (m_sink)
|
||||
{
|
||||
m_sink->close ();
|
||||
}
|
||||
}
|
||||
|
||||
SoundInput::~SoundInput ()
|
||||
{
|
||||
stop ();
|
||||
}
|
||||
|
17
soundin.h
17
soundin.h
@ -1,3 +1,4 @@
|
||||
// -*- Mode: C++ -*-
|
||||
#ifndef SOUNDIN_H__
|
||||
#define SOUNDIN_H__
|
||||
|
||||
@ -6,9 +7,10 @@
|
||||
#include <QScopedPointer>
|
||||
#include <QAudioInput>
|
||||
|
||||
#include "AudioDevice.hpp"
|
||||
|
||||
class QAudioDeviceInfo;
|
||||
class QAudioInput;
|
||||
class QIODevice;
|
||||
|
||||
// Gets audio data from sound sample source and passes it to a sink device
|
||||
class SoundInput
|
||||
@ -17,27 +19,30 @@ class SoundInput
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
SoundInput (QObject * parent = 0)
|
||||
: QObject (parent)
|
||||
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);
|
||||
// sink must exist from the start call until the next start call or
|
||||
// stop call
|
||||
Q_SLOT void start(QAudioDeviceInfo const&, int framesPerBuffer, AudioDevice * sink, unsigned downSampleFactor, AudioDevice::Channel = AudioDevice::Mono);
|
||||
Q_SLOT void stop ();
|
||||
|
||||
private:
|
||||
Q_SIGNAL void error (QString message) const;
|
||||
Q_SIGNAL void status (QString message) const;
|
||||
|
||||
private:
|
||||
// used internally
|
||||
Q_SLOT void handleStateChanged (QAudio::State) const;
|
||||
|
||||
bool audioError () const;
|
||||
|
||||
QScopedPointer<QAudioInput> m_stream;
|
||||
AudioDevice * m_sink;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
21
soundout.cpp
21
soundout.cpp
@ -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);
|
||||
|
||||
@ -83,8 +82,7 @@ void SoundOutput::startStream (QAudioDeviceInfo const& device, \
|
||||
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();
|
||||
@ -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));
|
||||
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 ();
|
||||
}
|
||||
|
||||
void SoundOutput::suspend ()
|
||||
@ -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)
|
||||
|
10
soundout.h
10
soundout.h
@ -1,3 +1,4 @@
|
||||
// -*- Mode: C++ -*-
|
||||
#ifndef SOUNDOUT_H__
|
||||
#define SOUNDOUT_H__
|
||||
|
||||
@ -24,15 +25,12 @@ class 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 */
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
// -*- Mode: C++ -*-
|
||||
#ifndef WIDEGRAPH_H
|
||||
#define WIDEGRAPH_H
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user