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:
Bill Somerville 2016-06-17 01:27:00 +00:00
parent 0de0a5dbe8
commit 5c81b808e5
4 changed files with 74 additions and 44 deletions

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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;