mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-12-23 19:25:37 -05:00
Adaptive sample block size to match FFT sizes
This change corrects timing discrepancies on the horizontal fast spectrum plot. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@6780 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
parent
fa55dadb91
commit
2beef948d9
14
Detector.cpp
14
Detector.cpp
@ -11,22 +11,26 @@ extern "C" {
|
||||
}
|
||||
|
||||
Detector::Detector (unsigned frameRate, unsigned periodLengthInSeconds,
|
||||
unsigned samplesPerFFT, unsigned downSampleFactor,
|
||||
QObject * parent)
|
||||
unsigned downSampleFactor, QObject * parent)
|
||||
: AudioDevice (parent)
|
||||
, m_frameRate (frameRate)
|
||||
, m_period (periodLengthInSeconds)
|
||||
, m_downSampleFactor (downSampleFactor)
|
||||
, m_samplesPerFFT (samplesPerFFT)
|
||||
, m_samplesPerFFT {max_buffer_size}
|
||||
, m_ns (999)
|
||||
, m_buffer ((downSampleFactor > 1) ?
|
||||
new short [samplesPerFFT * downSampleFactor] : 0)
|
||||
new short [max_buffer_size * downSampleFactor] : nullptr)
|
||||
, m_bufferPos (0)
|
||||
{
|
||||
(void)m_frameRate; // quell compiler warning
|
||||
clear ();
|
||||
}
|
||||
|
||||
void Detector::setBlockSize (unsigned n)
|
||||
{
|
||||
m_samplesPerFFT = n;
|
||||
}
|
||||
|
||||
bool Detector::reset ()
|
||||
{
|
||||
clear ();
|
||||
@ -83,7 +87,7 @@ qint64 Detector::writeData (char const * data, qint64 maxSize)
|
||||
if(m_bufferPos==m_samplesPerFFT*m_downSampleFactor) {
|
||||
qint32 framesToProcess (m_samplesPerFFT * m_downSampleFactor);
|
||||
qint32 framesAfterDownSample (m_samplesPerFFT);
|
||||
if(framesToProcess==13824 and dec_data.params.kin>=0 and
|
||||
if(m_downSampleFactor > 1 && dec_data.params.kin>=0 &&
|
||||
dec_data.params.kin < (NTMAX*12000 - framesAfterDownSample)) {
|
||||
fil4_(&m_buffer[0], &framesToProcess, &dec_data.d2[dec_data.params.kin],
|
||||
&framesAfterDownSample);
|
||||
|
@ -22,12 +22,14 @@ public:
|
||||
//
|
||||
// the samplesPerFFT argument is the number after down sampling
|
||||
//
|
||||
Detector (unsigned frameRate, unsigned periodLengthInSeconds, unsigned samplesPerFFT, unsigned downSampleFactor = 4u, QObject * parent = 0);
|
||||
Detector (unsigned frameRate, unsigned periodLengthInSeconds, unsigned downSampleFactor = 4u, QObject * parent = 0);
|
||||
|
||||
Q_SIGNAL void framesWritten (qint64) const;
|
||||
void setPeriod(unsigned p) {m_period=p;}
|
||||
bool reset () override;
|
||||
|
||||
Q_SIGNAL void framesWritten (qint64) const;
|
||||
Q_SLOT void setBlockSize (unsigned);
|
||||
|
||||
protected:
|
||||
qint64 readData (char * /* data */, qint64 /* maxSize */) override
|
||||
{
|
||||
@ -45,6 +47,7 @@ private:
|
||||
unsigned m_downSampleFactor;
|
||||
qint32 m_samplesPerFFT; // after any down sampling
|
||||
qint32 m_ns;
|
||||
static size_t const max_buffer_size {7 * 512};
|
||||
QScopedArrayPointer<short> m_buffer; // de-interleaved sample buffer
|
||||
// big enough for all the
|
||||
// samples for one increment of
|
||||
|
@ -164,7 +164,8 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
||||
m_lastDialFreq {0},
|
||||
m_callingFrequency {0},
|
||||
m_dialFreqRxWSPR {0},
|
||||
m_detector {new Detector {RX_SAMPLE_RATE, NTMAX, 6912 / 2, downSampleFactor}},
|
||||
m_detector {new Detector {RX_SAMPLE_RATE, NTMAX, downSampleFactor}},
|
||||
m_FFTSize {6192 / 2}, // conservative value to avoid buffer overruns
|
||||
m_soundInput {new SoundInput},
|
||||
m_modulator {new Modulator {TX_SAMPLE_RATE, NTMAX}},
|
||||
m_soundOutput {new SoundOutput},
|
||||
@ -378,6 +379,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
||||
connect (this, &MainWindow::finished, this, &MainWindow::close);
|
||||
|
||||
// hook up the detector signals, slots and disposal
|
||||
connect (this, &MainWindow::FFTSize, m_detector, &Detector::setBlockSize);
|
||||
connect(m_detector, &Detector::framesWritten, this, &MainWindow::dataSink);
|
||||
connect (&m_audioThread, &QThread::finished, m_detector, &QObject::deleteLater);
|
||||
|
||||
@ -995,7 +997,7 @@ void MainWindow::dataSink(qint64 frames)
|
||||
}
|
||||
|
||||
m_bUseRef=m_wideGraph->useRef();
|
||||
refspectrum_(&dec_data.d2[k-3456],&m_bRefSpec,&m_bUseRef,c_fname,len);
|
||||
refspectrum_(&dec_data.d2[k-m_nsps/2],&m_bRefSpec,&m_bUseRef,c_fname,len);
|
||||
|
||||
// Get power, spectrum, and ihsym
|
||||
int trmin=m_TRperiod/60;
|
||||
@ -1219,7 +1221,7 @@ void MainWindow::fastSink(qint64 frames)
|
||||
|
||||
decodeNow=false;
|
||||
m_k0=k;
|
||||
if(m_diskData and m_k0 >= dec_data.params.kin-3456) decodeNow=true;
|
||||
if(m_diskData and m_k0 >= dec_data.params.kin - 7 * 512) decodeNow=true;
|
||||
if(!m_diskData and m_tRemaining<0.35 and !m_bFastDecodeCalled) decodeNow=true;
|
||||
|
||||
if(decodeNow) {
|
||||
@ -1753,39 +1755,39 @@ void MainWindow::read_wav_file (QString const& fname)
|
||||
{
|
||||
// call diskDat() when done
|
||||
m_wav_future_watcher.setFuture (QtConcurrent::run ([this, fname] {
|
||||
auto basename = fname.mid (fname.lastIndexOf ('/') + 1);
|
||||
auto pos = fname.indexOf (".wav", 0, Qt::CaseInsensitive);
|
||||
// global variables and threads do not mix well, this needs changing
|
||||
dec_data.params.nutc = 0;
|
||||
if (pos > 0)
|
||||
{
|
||||
if (pos == fname.indexOf ('_', -11) + 7)
|
||||
{
|
||||
dec_data.params.nutc = fname.mid (pos - 6, 6).toInt ();
|
||||
}
|
||||
else
|
||||
{
|
||||
dec_data.params.nutc = 100 * fname.mid (pos - 4, 4).toInt ();
|
||||
}
|
||||
}
|
||||
BWFFile file {QAudioFormat {}, fname};
|
||||
file.open (BWFFile::ReadOnly);
|
||||
auto bytes_per_frame = file.format ().bytesPerFrame ();
|
||||
qint64 max_bytes = std::min (std::size_t (m_TRperiod * RX_SAMPLE_RATE),
|
||||
sizeof (dec_data.d2) / sizeof (dec_data.d2[0]))
|
||||
auto basename = fname.mid (fname.lastIndexOf ('/') + 1);
|
||||
auto pos = fname.indexOf (".wav", 0, Qt::CaseInsensitive);
|
||||
// global variables and threads do not mix well, this needs changing
|
||||
dec_data.params.nutc = 0;
|
||||
if (pos > 0)
|
||||
{
|
||||
if (pos == fname.indexOf ('_', -11) + 7)
|
||||
{
|
||||
dec_data.params.nutc = fname.mid (pos - 6, 6).toInt ();
|
||||
}
|
||||
else
|
||||
{
|
||||
dec_data.params.nutc = 100 * fname.mid (pos - 4, 4).toInt ();
|
||||
}
|
||||
}
|
||||
BWFFile file {QAudioFormat {}, fname};
|
||||
file.open (BWFFile::ReadOnly);
|
||||
auto bytes_per_frame = file.format ().bytesPerFrame ();
|
||||
qint64 max_bytes = std::min (std::size_t (m_TRperiod * RX_SAMPLE_RATE),
|
||||
sizeof (dec_data.d2) / sizeof (dec_data.d2[0]))
|
||||
* bytes_per_frame;
|
||||
auto n = file.read (reinterpret_cast<char *> (dec_data.d2),
|
||||
std::min (max_bytes, file.size ()));
|
||||
int frames_read = n / bytes_per_frame;
|
||||
// zero unfilled remaining sample space
|
||||
std::memset (&dec_data.d2[0] + n, 0, max_bytes - n);
|
||||
if (11025 == file.format ().sampleRate ())
|
||||
{
|
||||
short sample_size = file.format ().sampleSize ();
|
||||
wav12_ (dec_data.d2, dec_data.d2, &frames_read, &sample_size);
|
||||
}
|
||||
dec_data.params.kin = frames_read;
|
||||
dec_data.params.newdat = 1;
|
||||
auto n = file.read (reinterpret_cast<char *> (dec_data.d2),
|
||||
std::min (max_bytes, file.size ()));
|
||||
int frames_read = n / bytes_per_frame;
|
||||
// zero unfilled remaining sample space
|
||||
std::memset (&dec_data.d2[0] + n, 0, max_bytes - n);
|
||||
if (11025 == file.format ().sampleRate ())
|
||||
{
|
||||
short sample_size = file.format ().sampleSize ();
|
||||
wav12_ (dec_data.d2, dec_data.d2, &frames_read, &sample_size);
|
||||
}
|
||||
dec_data.params.kin = frames_read;
|
||||
dec_data.params.newdat = 1;
|
||||
}));
|
||||
}
|
||||
|
||||
@ -1824,8 +1826,7 @@ void MainWindow::on_actionDecode_remaining_files_in_directory_triggered()
|
||||
void MainWindow::diskDat() //diskDat()
|
||||
{
|
||||
int k;
|
||||
// int kstep=m_nsps/2;
|
||||
int kstep=3456;
|
||||
int kstep=m_FFTSize;
|
||||
m_diskData=true;
|
||||
|
||||
float db=m_config.degrade();
|
||||
@ -3671,6 +3672,8 @@ void MainWindow::on_actionJT9_triggered()
|
||||
if(m_modeTx!="JT9") on_pbTxMode_clicked();
|
||||
statusChanged();
|
||||
m_nsps=6912;
|
||||
m_FFTSize = m_nsps / 2;
|
||||
Q_EMIT FFTSize (m_FFTSize);
|
||||
QString t1=(QString)QChar(short(m_nSubMode+65));
|
||||
m_hsymStop=173;
|
||||
if(m_config.decode_at_52s()) m_hsymStop=179;
|
||||
@ -3729,6 +3732,8 @@ void MainWindow::on_actionJTMSK_triggered()
|
||||
switch_mode (Modes::JTMSK);
|
||||
statusChanged();
|
||||
m_nsps=6;
|
||||
m_FFTSize = 7 * 512;
|
||||
Q_EMIT FFTSize (m_FFTSize);
|
||||
mode_label->setStyleSheet("QLabel{background-color: #ff6666}");
|
||||
mode_label->setText(m_mode);
|
||||
m_toneSpacing=0.0;
|
||||
@ -3770,6 +3775,8 @@ void MainWindow::on_actionMSK144_triggered()
|
||||
switch_mode (Modes::MSK144);
|
||||
statusChanged();
|
||||
m_nsps=6;
|
||||
m_FFTSize = 7 * 512;
|
||||
Q_EMIT FFTSize (m_FFTSize);
|
||||
mode_label->setStyleSheet("QLabel{background-color: #ff6666}");
|
||||
mode_label->setText(m_mode);
|
||||
m_toneSpacing=0.0;
|
||||
@ -3810,6 +3817,8 @@ void MainWindow::on_actionJT65_triggered()
|
||||
m_modulator->setPeriod(m_TRperiod); // TODO - not thread safe
|
||||
m_detector->setPeriod(m_TRperiod); // TODO - not thread safe
|
||||
m_nsps=6912; //For symspec only
|
||||
m_FFTSize = m_nsps / 2;
|
||||
Q_EMIT FFTSize (m_FFTSize);
|
||||
m_hsymStop=173;
|
||||
if(m_config.decode_at_52s()) m_hsymStop=179;
|
||||
m_toneSpacing=0.0;
|
||||
@ -3860,6 +3869,8 @@ void MainWindow::on_actionJT9_JT65_triggered()
|
||||
m_modulator->setPeriod(m_TRperiod); // TODO - not thread safe
|
||||
m_detector->setPeriod(m_TRperiod); // TODO - not thread safe
|
||||
m_nsps=6912;
|
||||
m_FFTSize = m_nsps / 2;
|
||||
Q_EMIT FFTSize (m_FFTSize);
|
||||
m_hsymStop=173;
|
||||
if(m_config.decode_at_52s()) m_hsymStop=179;
|
||||
m_toneSpacing=0.0;
|
||||
@ -3894,6 +3905,8 @@ void MainWindow::on_actionJT4_triggered()
|
||||
m_modulator->setPeriod(m_TRperiod); // TODO - not thread safe
|
||||
m_detector->setPeriod(m_TRperiod); // TODO - not thread safe
|
||||
m_nsps=6912; //For symspec only
|
||||
m_FFTSize = m_nsps / 2;
|
||||
Q_EMIT FFTSize (m_FFTSize);
|
||||
m_hsymStop=179;
|
||||
m_toneSpacing=0.0;
|
||||
ui->actionJT4->setChecked(true);
|
||||
@ -3937,6 +3950,8 @@ void MainWindow::on_actionWSPR_2_triggered()
|
||||
m_modulator->setPeriod(m_TRperiod); // TODO - not thread safe
|
||||
m_detector->setPeriod(m_TRperiod); // TODO - not thread safe
|
||||
m_nsps=6912; //For symspec only
|
||||
m_FFTSize = m_nsps / 2;
|
||||
Q_EMIT FFTSize (m_FFTSize);
|
||||
m_hsymStop=396;
|
||||
m_toneSpacing=12000.0/8192.0;
|
||||
mode_label->setStyleSheet("QLabel{background-color: #ff66ff}");
|
||||
@ -3970,6 +3985,8 @@ void MainWindow::on_actionEcho_triggered()
|
||||
m_modulator->setPeriod(m_TRperiod); // TODO - not thread safe
|
||||
m_detector->setPeriod(m_TRperiod); // TODO - not thread safe
|
||||
m_nsps=6912; //For symspec only
|
||||
m_FFTSize = m_nsps / 2;
|
||||
Q_EMIT FFTSize (m_FFTSize);
|
||||
m_hsymStop=10;
|
||||
m_toneSpacing=1.0;
|
||||
switch_mode(Modes::Echo);
|
||||
@ -4001,6 +4018,8 @@ void MainWindow::on_actionISCAT_triggered()
|
||||
m_detector->setPeriod(m_TRperiod);
|
||||
m_wideGraph->setPeriod(m_TRperiod,m_nsps);
|
||||
m_nsps=6912; //For symspec only
|
||||
m_FFTSize = m_nsps / 2;
|
||||
Q_EMIT FFTSize (m_FFTSize);
|
||||
m_hsymStop=103;
|
||||
m_toneSpacing=11025.0/256.0;
|
||||
WSPR_config(false);
|
||||
@ -4699,6 +4718,8 @@ void MainWindow::transmit (double snr)
|
||||
|
||||
if (m_modeTx == "JTMSK" or m_modeTx == "MSK144") {
|
||||
m_nsps=6;
|
||||
m_FFTSize = 7 * 512;
|
||||
Q_EMIT FFTSize (m_FFTSize);
|
||||
m_toneSpacing=6000.0/m_nsps;
|
||||
double f0=1000.0;
|
||||
int nsym;
|
||||
|
@ -260,6 +260,7 @@ private:
|
||||
Q_SIGNAL void suspendAudioInputStream () const;
|
||||
Q_SIGNAL void resumeAudioInputStream () const;
|
||||
Q_SIGNAL void startDetector (AudioDevice::Channel) const;
|
||||
Q_SIGNAL void FFTSize (unsigned) const;
|
||||
Q_SIGNAL void detectorClose () const;
|
||||
Q_SIGNAL void finished () const;
|
||||
Q_SIGNAL void transmitFrequency (double) const;
|
||||
@ -308,6 +309,7 @@ private:
|
||||
Frequency m_dialFreqRxWSPR; // best guess at WSPR QRG
|
||||
|
||||
Detector * m_detector;
|
||||
unsigned m_FFTSize;
|
||||
SoundInput * m_soundInput;
|
||||
Modulator * m_modulator;
|
||||
SoundOutput * m_soundOutput;
|
||||
|
Loading…
Reference in New Issue
Block a user