aboutsummaryrefslogtreecommitdiffstats
path: root/src/DabModulator.cpp
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2023-05-16 22:04:21 +0200
committerMatthias P. Braendli <matthias.braendli@mpb.li>2023-05-16 22:04:21 +0200
commit1d07999d373b0fb0b67de576aa4d7b10308b4150 (patch)
tree78f4556978a96e8084a4e54268de915a839d48ac /src/DabModulator.cpp
parent829863ab82ca3743c64c76310af5eebcaab1fc84 (diff)
downloaddabmod-1d07999d373b0fb0b67de576aa4d7b10308b4150.tar.gz
dabmod-1d07999d373b0fb0b67de576aa4d7b10308b4150.tar.bz2
dabmod-1d07999d373b0fb0b67de576aa4d7b10308b4150.zip
Avoid undefined format conversion and measure clipping
Diffstat (limited to 'src/DabModulator.cpp')
-rw-r--r--src/DabModulator.cpp170
1 files changed, 97 insertions, 73 deletions
diff --git a/src/DabModulator.cpp b/src/DabModulator.cpp
index 64ebf03..5213d8d 100644
--- a/src/DabModulator.cpp
+++ b/src/DabModulator.cpp
@@ -59,19 +59,22 @@
using namespace std;
DabModulator::DabModulator(EtiSource& etiSource,
- mod_settings_t& settings) :
+ mod_settings_t& settings,
+ const std::string& format) :
ModInput(),
RemoteControllable("modulator"),
m_settings(settings),
- myEtiSource(etiSource),
- myFlowgraph()
+ m_format(format),
+ m_etiSource(etiSource),
+ m_flowgraph()
{
PDEBUG("DabModulator::DabModulator() @ %p\n", this);
RC_ADD_PARAMETER(rate, "(Read-only) IQ output samplerate");
+ RC_ADD_PARAMETER(num_clipped_samples, "(Read-only) Number of samples clipped in last frame during format conversion");
if (m_settings.dabMode == 0) {
- setMode(2);
+ setMode(1);
}
else {
setMode(m_settings.dabMode);
@@ -83,36 +86,36 @@ void DabModulator::setMode(unsigned mode)
{
switch (mode) {
case 1:
- myNbSymbols = 76;
- myNbCarriers = 1536;
- mySpacing = 2048;
- myNullSize = 2656;
- mySymSize = 2552;
- myFicSizeOut = 288;
+ m_nbSymbols = 76;
+ m_nbCarriers = 1536;
+ m_spacing = 2048;
+ m_nullSize = 2656;
+ m_symSize = 2552;
+ m_ficSizeOut = 288;
break;
case 2:
- myNbSymbols = 76;
- myNbCarriers = 384;
- mySpacing = 512;
- myNullSize = 664;
- mySymSize = 638;
- myFicSizeOut = 288;
+ m_nbSymbols = 76;
+ m_nbCarriers = 384;
+ m_spacing = 512;
+ m_nullSize = 664;
+ m_symSize = 638;
+ m_ficSizeOut = 288;
break;
case 3:
- myNbSymbols = 153;
- myNbCarriers = 192;
- mySpacing = 256;
- myNullSize = 345;
- mySymSize = 319;
- myFicSizeOut = 384;
+ m_nbSymbols = 153;
+ m_nbCarriers = 192;
+ m_spacing = 256;
+ m_nullSize = 345;
+ m_symSize = 319;
+ m_ficSizeOut = 384;
break;
case 4:
- myNbSymbols = 76;
- myNbCarriers = 768;
- mySpacing = 1024;
- myNullSize = 1328;
- mySymSize = 1276;
- myFicSizeOut = 288;
+ m_nbSymbols = 76;
+ m_nbCarriers = 768;
+ m_spacing = 1024;
+ m_nullSize = 1328;
+ m_symSize = 1276;
+ m_ficSizeOut = 288;
break;
default:
throw std::runtime_error("DabModulator::setMode invalid mode size");
@@ -126,27 +129,27 @@ int DabModulator::process(Buffer* dataOut)
PDEBUG("DabModulator::process(dataOut: %p)\n", dataOut);
- if (not myFlowgraph) {
+ if (not m_flowgraph) {
etiLog.level(debug) << "Setting up DabModulator...";
const unsigned mode = m_settings.dabMode;
setMode(mode);
- myFlowgraph = make_shared<Flowgraph>(m_settings.showProcessTime);
+ m_flowgraph = make_shared<Flowgraph>(m_settings.showProcessTime);
////////////////////////////////////////////////////////////////
// CIF data initialisation
////////////////////////////////////////////////////////////////
auto cifPrbs = make_shared<PrbsGenerator>(864 * 8, 0x110);
- auto cifMux = make_shared<FrameMultiplexer>(myEtiSource);
+ auto cifMux = make_shared<FrameMultiplexer>(m_etiSource);
auto cifPart = make_shared<BlockPartitioner>(mode);
- auto cifMap = make_shared<QpskSymbolMapper>(myNbCarriers);
+ auto cifMap = make_shared<QpskSymbolMapper>(m_nbCarriers);
auto cifRef = make_shared<PhaseReference>(mode);
auto cifFreq = make_shared<FrequencyInterleaver>(mode);
- auto cifDiff = make_shared<DifferentialModulator>(myNbCarriers);
+ auto cifDiff = make_shared<DifferentialModulator>(m_nbCarriers);
- auto cifNull = make_shared<NullSymbol>(myNbCarriers);
+ auto cifNull = make_shared<NullSymbol>(m_nbCarriers);
auto cifSig = make_shared<SignalMultiplexer>(
- (1 + myNbSymbols) * myNbCarriers * sizeof(complexf));
+ (1 + m_nbSymbols) * m_nbCarriers * sizeof(complexf));
// TODO this needs a review
bool useCicEq = false;
@@ -167,8 +170,8 @@ int DabModulator::process(Buffer* dataOut)
shared_ptr<CicEqualizer> cifCicEq;
if (useCicEq) {
cifCicEq = make_shared<CicEqualizer>(
- myNbCarriers,
- (float)mySpacing * (float)m_settings.outputRate / 2048000.0f,
+ m_nbCarriers,
+ (float)m_spacing * (float)m_settings.outputRate / 2048000.0f,
cic_ratio);
}
@@ -186,9 +189,9 @@ int DabModulator::process(Buffer* dataOut)
}
auto cifOfdm = make_shared<OfdmGenerator>(
- (1 + myNbSymbols),
- myNbCarriers,
- mySpacing,
+ (1 + m_nbSymbols),
+ m_nbCarriers,
+ m_spacing,
m_settings.enableCfr,
m_settings.cfrClip,
m_settings.cfrErrorClip);
@@ -196,7 +199,7 @@ int DabModulator::process(Buffer* dataOut)
rcs.enrol(cifOfdm.get());
auto cifGain = make_shared<GainControl>(
- mySpacing,
+ m_spacing,
m_settings.gainMode,
m_settings.digitalgain,
m_settings.normalise,
@@ -205,7 +208,7 @@ int DabModulator::process(Buffer* dataOut)
rcs.enrol(cifGain.get());
auto cifGuard = make_shared<GuardIntervalInserter>(
- myNbSymbols, mySpacing, myNullSize, mySymSize,
+ m_nbSymbols, m_spacing, m_nullSize, m_symSize,
m_settings.ofdmWindowOverlap);
rcs.enrol(cifGuard.get());
@@ -227,17 +230,21 @@ int DabModulator::process(Buffer* dataOut)
cifRes = make_shared<Resampler>(
2048000,
m_settings.outputRate,
- mySpacing);
+ m_spacing);
}
- myOutput = make_shared<OutputMemory>(dataOut);
+ if (not m_format.empty()) {
+ m_formatConverter = make_shared<FormatConverter>(m_format);
+ }
+
+ m_output = make_shared<OutputMemory>(dataOut);
- myFlowgraph->connect(cifPrbs, cifMux);
+ m_flowgraph->connect(cifPrbs, cifMux);
////////////////////////////////////////////////////////////////
// Processing FIC
////////////////////////////////////////////////////////////////
- shared_ptr<FicSource> fic(myEtiSource.getFic());
+ shared_ptr<FicSource> fic(m_etiSource.getFic());
////////////////////////////////////////////////////////////////
// Data initialisation
////////////////////////////////////////////////////////////////
@@ -269,15 +276,15 @@ int DabModulator::process(Buffer* dataOut)
PDEBUG(" Adding tail\n");
ficPunc->append_tail_rule(PuncturingRule(3, 0xcccccc));
- myFlowgraph->connect(fic, ficPrbs);
- myFlowgraph->connect(ficPrbs, ficConv);
- myFlowgraph->connect(ficConv, ficPunc);
- myFlowgraph->connect(ficPunc, cifPart);
+ m_flowgraph->connect(fic, ficPrbs);
+ m_flowgraph->connect(ficPrbs, ficConv);
+ m_flowgraph->connect(ficConv, ficPunc);
+ m_flowgraph->connect(ficPunc, cifPart);
////////////////////////////////////////////////////////////////
// Configuring subchannels
////////////////////////////////////////////////////////////////
- for (const auto& subchannel : myEtiSource.getSubchannels()) {
+ for (const auto& subchannel : m_etiSource.getSubchannels()) {
////////////////////////////////////////////////////////////
// Data initialisation
@@ -329,23 +336,23 @@ int DabModulator::process(Buffer* dataOut)
// Configuring time interleaver
auto subchInterleaver = make_shared<TimeInterleaver>(subchSizeOut);
- myFlowgraph->connect(subchannel, subchPrbs);
- myFlowgraph->connect(subchPrbs, subchConv);
- myFlowgraph->connect(subchConv, subchPunc);
- myFlowgraph->connect(subchPunc, subchInterleaver);
- myFlowgraph->connect(subchInterleaver, cifMux);
+ m_flowgraph->connect(subchannel, subchPrbs);
+ m_flowgraph->connect(subchPrbs, subchConv);
+ m_flowgraph->connect(subchConv, subchPunc);
+ m_flowgraph->connect(subchPunc, subchInterleaver);
+ m_flowgraph->connect(subchInterleaver, cifMux);
}
- myFlowgraph->connect(cifMux, cifPart);
- myFlowgraph->connect(cifPart, cifMap);
- myFlowgraph->connect(cifMap, cifFreq);
- myFlowgraph->connect(cifRef, cifDiff);
- myFlowgraph->connect(cifFreq, cifDiff);
- myFlowgraph->connect(cifNull, cifSig);
- myFlowgraph->connect(cifDiff, cifSig);
+ m_flowgraph->connect(cifMux, cifPart);
+ m_flowgraph->connect(cifPart, cifMap);
+ m_flowgraph->connect(cifMap, cifFreq);
+ m_flowgraph->connect(cifRef, cifDiff);
+ m_flowgraph->connect(cifFreq, cifDiff);
+ m_flowgraph->connect(cifNull, cifSig);
+ m_flowgraph->connect(cifDiff, cifSig);
if (tii) {
- myFlowgraph->connect(tiiRef, tii);
- myFlowgraph->connect(tii, cifSig);
+ m_flowgraph->connect(tiiRef, tii);
+ m_flowgraph->connect(tii, cifSig);
}
shared_ptr<ModPlugin> prev_plugin = static_pointer_cast<ModPlugin>(cifSig);
@@ -354,15 +361,18 @@ int DabModulator::process(Buffer* dataOut)
static_pointer_cast<ModPlugin>(cifOfdm),
static_pointer_cast<ModPlugin>(cifGain),
static_pointer_cast<ModPlugin>(cifGuard),
- static_pointer_cast<ModPlugin>(cifFilter), // optional block
- static_pointer_cast<ModPlugin>(cifRes), // optional block
- static_pointer_cast<ModPlugin>(cifPoly), // optional block
- static_pointer_cast<ModPlugin>(myOutput),
+ // optional blocks
+ static_pointer_cast<ModPlugin>(cifFilter),
+ static_pointer_cast<ModPlugin>(cifRes),
+ static_pointer_cast<ModPlugin>(cifPoly),
+ static_pointer_cast<ModPlugin>(m_formatConverter),
+ // mandatory block
+ static_pointer_cast<ModPlugin>(m_output),
});
for (auto& p : plugins) {
if (p) {
- myFlowgraph->connect(prev_plugin, p);
+ m_flowgraph->connect(prev_plugin, p);
prev_plugin = p;
}
}
@@ -372,13 +382,13 @@ int DabModulator::process(Buffer* dataOut)
////////////////////////////////////////////////////////////////////
// Processing data
////////////////////////////////////////////////////////////////////
- return myFlowgraph->run();
+ return m_flowgraph->run();
}
meta_vec_t DabModulator::process_metadata(const meta_vec_t& metadataIn)
{
- if (myOutput) {
- return myOutput->get_latest_metadata();
+ if (m_output) {
+ return m_output->get_latest_metadata();
}
return {};
@@ -390,6 +400,9 @@ void DabModulator::set_parameter(const string& parameter, const string& value)
if (parameter == "rate") {
throw ParameterError("Parameter 'rate' is read-only");
}
+ else if (parameter == "num_clipped_samples") {
+ throw ParameterError("Parameter 'num_clipped_samples' is read-only");
+ }
else {
stringstream ss;
ss << "Parameter '" << parameter <<
@@ -404,6 +417,16 @@ const string DabModulator::get_parameter(const string& parameter) const
if (parameter == "rate") {
ss << m_settings.outputRate;
}
+ else if (parameter == "num_clipped_samples") {
+ if (m_formatConverter) {
+ ss << m_formatConverter->get_num_clipped_samples();
+ }
+ else {
+ ss << "Parameter '" << parameter <<
+ "' is not available when no format conversion is done.";
+ throw ParameterError(ss.str());
+ }
+ }
else {
ss << "Parameter '" << parameter <<
"' is not exported by controllable " << get_rc_name();
@@ -416,5 +439,6 @@ const RemoteControllable::map_t DabModulator::get_all_values() const
{
map_t map;
map["rate"] = m_settings.outputRate;
+ map["num_clipped_samples"] = m_formatConverter ? m_formatConverter->get_num_clipped_samples() : 0;
return map;
}