FT8 demod: implement callback as an interface class. Added test .wav file and file option in the sdrbench options

This commit is contained in:
f4exb 2023-01-09 00:38:15 +01:00
parent 23e01ea064
commit 7cd08ef1e9
8 changed files with 101 additions and 28 deletions

View File

@ -445,7 +445,7 @@ public:
float down_hz_; float down_hz_;
static std::mutex cb_mu_; static std::mutex cb_mu_;
cb_t cb_; // call-back into Python CallbackInterface *cb_; // call-back interface
std::mutex hack_mu_; std::mutex hack_mu_;
int hack_size_; int hack_size_;
@ -469,7 +469,7 @@ public:
int hints2[], int hints2[],
double deadline, double deadline,
double final_deadline, double final_deadline,
cb_t cb, CallbackInterface *cb,
std::vector<cdecode> prevdecs std::vector<cdecode> prevdecs
) )
{ {
@ -3513,10 +3513,10 @@ public:
float snr = guess_snr(m79); float snr = guess_snr(m79);
if (cb_ != 0) if (cb_)
{ {
cb_mu_.lock(); cb_mu_.lock();
int ret = cb_( int ret = cb_->hcb(
a174, a174,
best_hz + down_hz_, best_hz + down_hz_,
best_off, best_off,
@ -3603,7 +3603,7 @@ void entry(
int hints2[], int hints2[],
double time_left, double time_left,
double total_time_left, double total_time_left,
cb_t cb, CallbackInterface *cb,
int nprevdecs, int nprevdecs,
struct cdecode *xprevdecs struct cdecode *xprevdecs
) )

View File

@ -22,16 +22,21 @@
#define ft8_h #define ft8_h
namespace FT8 { namespace FT8 {
// Callback function to get the results // Callback interface to get the results
typedef int (*cb_t)( class CallbackInterface
int *a91, {
float hz0, public:
float off, virtual int hcb(
const char *, int *a91,
float snr, float hz0,
int pass, float off,
int correct_bits const char *,
); float snr,
int pass,
int correct_bits
) = 0; //!< virtual nathod called each time there is a result
};
// same as Python class CDECODE // same as Python class CDECODE
// //
struct cdecode struct cdecode
@ -53,7 +58,7 @@ void entry(
int hints2[], int hints2[],
double time_left, double time_left,
double total_time_left, double total_time_left,
cb_t cb, CallbackInterface *cb,
int, int,
struct cdecode * struct cdecode *
); );

View File

@ -46,7 +46,8 @@ void MainBench::run()
<< " testType: " << (int) m_parser.getTestType() << " testType: " << (int) m_parser.getTestType()
<< " nsamples: " << m_parser.getNbSamples() << " nsamples: " << m_parser.getNbSamples()
<< " repet: " << m_parser.getRepetition() << " repet: " << m_parser.getRepetition()
<< " log2f: " << m_parser.getLog2Factor(); << " log2f: " << m_parser.getLog2Factor()
<< " file: " << m_parser.getFileName();
if (m_parser.getTestType() == ParserBench::TestDecimatorsII) { if (m_parser.getTestType() == ParserBench::TestDecimatorsII) {
testDecimateII(); testDecimateII();
@ -63,7 +64,7 @@ void MainBench::run()
} else if (m_parser.getTestType() == ParserBench::TestGolay2312) { } else if (m_parser.getTestType() == ParserBench::TestGolay2312) {
testGolay2312(); testGolay2312();
} else if (m_parser.getTestType() == ParserBench::TestFT8) { } else if (m_parser.getTestType() == ParserBench::TestFT8) {
testFT8(); testFT8(m_parser.getFileName());
} else { } else {
qDebug() << "MainBench::run: unknown test type: " << m_parser.getTestType(); qDebug() << "MainBench::run: unknown test type: " << m_parser.getTestType();
} }

View File

@ -54,7 +54,7 @@ private:
void testDecimateFI(); void testDecimateFI();
void testDecimateFF(); void testDecimateFF();
void testGolay2312(); void testGolay2312();
void testFT8(); void testFT8(const QString& wavFile); //!< use with sdrbench/samples/ft8/230105_091630.wav in -f option
void decimateII(const qint16 *buf, int len); void decimateII(const qint16 *buf, int len);
void decimateInfII(const qint16 *buf, int len); void decimateInfII(const qint16 *buf, int len);
void decimateSupII(const qint16 *buf, int len); void decimateSupII(const qint16 *buf, int len);

View File

@ -38,7 +38,11 @@ ParserBench::ParserBench() :
m_log2FactorOption(QStringList() << "l" << "log2-factor", m_log2FactorOption(QStringList() << "l" << "log2-factor",
"Log2 factor for rate conversion.", "Log2 factor for rate conversion.",
"log2", "log2",
"2") "2"),
m_fileOption(QStringList() << "f" << "file",
"File to be used for the test.",
"file",
"")
{ {
m_testStr = "decimateii"; m_testStr = "decimateii";
m_nbSamples = 1048576; m_nbSamples = 1048576;
@ -53,6 +57,7 @@ ParserBench::ParserBench() :
m_parser.addOption(m_nbSamplesOption); m_parser.addOption(m_nbSamplesOption);
m_parser.addOption(m_repetitionOption); m_parser.addOption(m_repetitionOption);
m_parser.addOption(m_log2FactorOption); m_parser.addOption(m_log2FactorOption);
m_parser.addOption(m_fileOption);
} }
ParserBench::~ParserBench() ParserBench::~ParserBench()
@ -111,6 +116,10 @@ void ParserBench::parse(const QCoreApplication& app)
} else { } else {
qWarning() << "ParserBench::parse: repetilog2 factortion invalid. Defaulting to " << m_log2Factor; qWarning() << "ParserBench::parse: repetilog2 factortion invalid. Defaulting to " << m_log2Factor;
} }
// file
m_fileName = m_parser.value(m_fileOption);
} }
ParserBench::TestType ParserBench::getTestType() const ParserBench::TestType ParserBench::getTestType() const

View File

@ -49,18 +49,21 @@ public:
uint32_t getNbSamples() const { return m_nbSamples; } uint32_t getNbSamples() const { return m_nbSamples; }
uint32_t getRepetition() const { return m_repetition; } uint32_t getRepetition() const { return m_repetition; }
uint32_t getLog2Factor() const { return m_log2Factor; } uint32_t getLog2Factor() const { return m_log2Factor; }
const QString& getFileName() const { return m_fileName; }
private: private:
QString m_testStr; QString m_testStr;
uint32_t m_nbSamples; uint32_t m_nbSamples;
uint32_t m_repetition; uint32_t m_repetition;
uint32_t m_log2Factor; uint32_t m_log2Factor;
QString m_fileName;
QCommandLineParser m_parser; QCommandLineParser m_parser;
QCommandLineOption m_testOption; QCommandLineOption m_testOption;
QCommandLineOption m_nbSamplesOption; QCommandLineOption m_nbSamplesOption;
QCommandLineOption m_repetitionOption; QCommandLineOption m_repetitionOption;
QCommandLineOption m_log2FactorOption; QCommandLineOption m_log2FactorOption;
QCommandLineOption m_fileOption;
}; };

Binary file not shown.

View File

@ -31,10 +31,28 @@ void MainBench::testFT8()
} }
#else #else
QMutex cycle_mu; class TestFT8Callback : public FT8::CallbackInterface
std::map<std::string, bool> cycle_already; {
public:
virtual int hcb(
int *a91,
float hz0,
float off,
const char *comment,
float snr,
int pass,
int correct_bits
);
const std::map<std::string, bool>& getMsgMap() {
return cycle_already;
}
private:
QMutex cycle_mu;
std::map<std::string, bool> cycle_already;
};
int hcb(
int TestFT8Callback::hcb(
int *a91, int *a91,
float hz0, float hz0,
float off, float off,
@ -62,7 +80,7 @@ int hcb(
cycle_mu.unlock(); cycle_mu.unlock();
printf("%d %3d %3d %5.2f %6.1f %s [%s:%s:%s] (%s)\n", qDebug("TestFT8Callback::hcb: %d %3d %3d %5.2f %6.1f %s [%s:%s:%s] (%s)",
pass, pass,
(int)snr, (int)snr,
correct_bits, correct_bits,
@ -79,14 +97,15 @@ int hcb(
return 2; // 2 => new decode, do subtract. return 2; // 2 => new decode, do subtract.
} }
void MainBench::testFT8() void MainBench::testFT8(const QString& wavFile)
{ {
qDebug("MainBench::testFT8: start"); qDebug("MainBench::testFT8: start");
int hints[2] = { 2, 0 }; // CQ int hints[2] = { 2, 0 }; // CQ
double budget = 2.5; // compute for this many seconds per cycle double budget = 2.5; // compute for this many seconds per cycle
TestFT8Callback testft8Callback;
int rate; int rate;
std::vector<float> s = FT8::readwav("/home/f4exb/.local/share/WSJT-X/save/230105_091630.wav", rate); // FIXME: download file std::vector<float> s = FT8::readwav(wavFile.toStdString().c_str(), rate);
FT8::entry( FT8::entry(
s.data(), s.data(),
s.size(), s.size(),
@ -98,10 +117,46 @@ void MainBench::testFT8()
hints, hints,
budget, budget,
budget, budget,
hcb, &testft8Callback,
0, 0,
(struct FT8::cdecode *) 0 (struct FT8::cdecode *) 0
); );
qDebug("MainBench::testFT8: end"); qDebug("MainBench::testFT8: done");
const std::map<std::string, bool>& msgMap = testft8Callback.getMsgMap();
if (msgMap.size() != 15)
{
qDebug("MainBench::testFT8: failed: invlid size: %lu expected 15", msgMap.size());
return;
}
QStringList messages = {
"CQ DF5SF JN39",
"CQ DL1SVA JO64",
"CQ DL7CO JO42",
"CQ F4BAL JO10",
"CQ LA1XJA JO49",
"CQ ON7VG JO21",
"CQ OZ1BJF JO55",
"CQ S51TA JN75",
"HA3PT SQ8AA -18",
"JA2KFQ EI4KF -17",
"LY3PW DF2FE R-13",
"N9GQA DG9NAY JN58",
"OK1HEH OH8NW 73 ",
"UN6T EA1FQ IN53",
"W5SUM G8OO -18"
};
for (const auto &msg : messages)
{
if (msgMap.count(msg.toStdString()) != 1)
{
qDebug("MainBench::testFT8: failed: key: %s", qPrintable(msg));
return;
}
}
qDebug("MainBench::testFT8: success");
} }
#endif #endif