mirror of https://github.com/f4exb/sdrangel.git
FT8 demod: implement callback as an interface class. Added test .wav file and file option in the sdrbench options
This commit is contained in:
parent
23e01ea064
commit
7cd08ef1e9
10
ft8/ft8.cpp
10
ft8/ft8.cpp
|
@ -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
|
||||||
)
|
)
|
||||||
|
|
27
ft8/ft8.h
27
ft8/ft8.h
|
@ -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 *
|
||||||
);
|
);
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue