aboutsummaryrefslogtreecommitdiffstats
path: root/src/GuardIntervalInserter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/GuardIntervalInserter.cpp')
-rw-r--r--src/GuardIntervalInserter.cpp324
1 files changed, 177 insertions, 147 deletions
diff --git a/src/GuardIntervalInserter.cpp b/src/GuardIntervalInserter.cpp
index 3c2db14..26d4fd1 100644
--- a/src/GuardIntervalInserter.cpp
+++ b/src/GuardIntervalInserter.cpp
@@ -29,39 +29,47 @@
#include <cstring>
#include <cassert>
#include <stdexcept>
-#include <complex>
#include <mutex>
-typedef std::complex<float> complexf;
+GuardIntervalInserter::Params::Params(
+ size_t nbSymbols,
+ size_t spacing,
+ size_t nullSize,
+ size_t symSize,
+ size_t& windowOverlap) :
+ nbSymbols(nbSymbols),
+ spacing(spacing),
+ nullSize(nullSize),
+ symSize(symSize),
+ windowOverlap(windowOverlap) {}
GuardIntervalInserter::GuardIntervalInserter(
size_t nbSymbols,
size_t spacing,
size_t nullSize,
size_t symSize,
- size_t& windowOverlap) :
+ size_t& windowOverlap,
+ FFTEngine fftEngine) :
ModCodec(),
RemoteControllable("guardinterval"),
- d_nbSymbols(nbSymbols),
- d_spacing(spacing),
- d_nullSize(nullSize),
- d_symSize(symSize),
- d_windowOverlap(windowOverlap)
+ m_fftEngine(fftEngine),
+ m_params(nbSymbols, spacing, nullSize, symSize, windowOverlap)
{
- if (d_nullSize == 0) {
+ if (nullSize == 0) {
throw std::logic_error("NULL symbol must be present");
}
+
RC_ADD_PARAMETER(windowlen, "Window length for OFDM windowng [0 to disable]");
/* We use a raised-cosine window for the OFDM windowing.
- * Each symbol is extended on both sides by d_windowOverlap samples.
+ * Each symbol is extended on both sides by windowOverlap samples.
*
*
* Sym n |####################|
* Sym n+1 |####################|
*
- * We now extend the symbols by d_windowOverlap (one dash)
+ * We now extend the symbols by windowOverlap (one dash)
*
* Sym n extended -|####################|-
* Sym n+1 extended -|####################|-
@@ -75,7 +83,7 @@ GuardIntervalInserter::GuardIntervalInserter(
* / \
* ... ________________/ \__ ...
*
- * The window length is 2*d_windowOverlap.
+ * The window length is 2*windowOverlap.
*/
update_window(windowOverlap);
@@ -87,44 +95,43 @@ GuardIntervalInserter::GuardIntervalInserter(
void GuardIntervalInserter::update_window(size_t new_window_overlap)
{
- std::lock_guard<std::mutex> lock(d_windowMutex);
+ std::lock_guard<std::mutex> lock(m_params.windowMutex);
- d_windowOverlap = new_window_overlap;
+ m_params.windowOverlap = new_window_overlap;
- // d_window only contains the rising window edge.
- d_window.resize(2*d_windowOverlap);
- for (size_t i = 0; i < 2*d_windowOverlap; i++) {
- d_window[i] = (float)(0.5 * (1.0 - cos(M_PI * i / (2*d_windowOverlap - 1))));
+ // m_params.window only contains the rising window edge.
+ m_params.window.resize(2*m_params.windowOverlap);
+ for (size_t i = 0; i < 2*m_params.windowOverlap; i++) {
+ m_params.window[i] = (float)(0.5 * (1.0 - cos(M_PI * i / (2*m_params.windowOverlap - 1))));
}
}
-int GuardIntervalInserter::process(Buffer* const dataIn, Buffer* dataOut)
+template<typename T>
+int do_process(const GuardIntervalInserter::Params& p, Buffer* const dataIn, Buffer* dataOut)
{
- PDEBUG("GuardIntervalInserter::process(dataIn: %p, dataOut: %p)\n",
+ PDEBUG("GuardIntervalInserter do_process(dataIn: %p, dataOut: %p)\n",
dataIn, dataOut);
- std::lock_guard<std::mutex> lock(d_windowMutex);
-
- // Every symbol overlaps over a length of d_windowOverlap with
+ // Every symbol overlaps over a length of windowOverlap with
// the previous symbol, and with the next symbol. First symbol
// receives no prefix window, because we don't remember the
// last symbol from the previous TF (yet). Last symbol also
// receives no suffix window, for the same reason.
// Overall output buffer length must stay independent of the windowing.
- dataOut->setLength((d_nullSize + (d_nbSymbols * d_symSize)) * sizeof(complexf));
+ dataOut->setLength((p.nullSize + (p.nbSymbols * p.symSize)) * sizeof(T));
- const complexf* in = reinterpret_cast<const complexf*>(dataIn->getData());
- complexf* out = reinterpret_cast<complexf*>(dataOut->getData());
- size_t sizeIn = dataIn->getLength() / sizeof(complexf);
+ const T* in = reinterpret_cast<const T*>(dataIn->getData());
+ T* out = reinterpret_cast<T*>(dataOut->getData());
+ size_t sizeIn = dataIn->getLength() / sizeof(T);
- const size_t num_symbols = d_nbSymbols + 1;
- if (sizeIn != num_symbols * d_spacing)
+ const size_t num_symbols = p.nbSymbols + 1;
+ if (sizeIn != num_symbols * p.spacing)
{
- PDEBUG("Nb symbols: %zu\n", d_nbSymbols);
- PDEBUG("Spacing: %zu\n", d_spacing);
- PDEBUG("Null size: %zu\n", d_nullSize);
- PDEBUG("Sym size: %zu\n", d_symSize);
- PDEBUG("\n%zu != %zu\n", sizeIn, (d_nbSymbols + 1) * d_spacing);
+ PDEBUG("Nb symbols: %zu\n", p.nbSymbols);
+ PDEBUG("Spacing: %zu\n", p.spacing);
+ PDEBUG("Null size: %zu\n", p.nullSize);
+ PDEBUG("Sym size: %zu\n", p.symSize);
+ PDEBUG("\n%zu != %zu\n", sizeIn, (p.nbSymbols + 1) * p.spacing);
throw std::runtime_error(
"GuardIntervalInserter::process input size not valid!");
}
@@ -132,139 +139,162 @@ int GuardIntervalInserter::process(Buffer* const dataIn, Buffer* dataOut)
// TODO remember the end of the last TF so that we can do some
// windowing too.
- if (d_windowOverlap) {
- {
- // Handle Null symbol separately because it is longer
- const size_t prefixlength = d_nullSize - d_spacing;
-
- // end = spacing
- memcpy(out, &in[d_spacing - prefixlength],
- prefixlength * sizeof(complexf));
-
- memcpy(&out[prefixlength], in, (d_spacing - d_windowOverlap) * sizeof(complexf));
+ std::lock_guard<std::mutex> lock(p.windowMutex);
+ if (p.windowOverlap) {
+ if constexpr (std::is_same_v<complexf, T>) {
+ {
+ // Handle Null symbol separately because it is longer
+ const size_t prefixlength = p.nullSize - p.spacing;
+
+ // end = spacing
+ memcpy(out, &in[p.spacing - prefixlength],
+ prefixlength * sizeof(T));
+
+ memcpy(&out[prefixlength], in, (p.spacing - p.windowOverlap) * sizeof(T));
+
+ // The remaining part of the symbol must have half of the window applied,
+ // sloping down from 1 to 0.5
+ for (size_t i = 0; i < p.windowOverlap; i++) {
+ const size_t out_ix = prefixlength + p.spacing - p.windowOverlap + i;
+ const size_t in_ix = p.spacing - p.windowOverlap + i;
+ out[out_ix] = in[in_ix] * p.window[2*p.windowOverlap - (i+1)];
+ }
- // The remaining part of the symbol must have half of the window applied,
- // sloping down from 1 to 0.5
- for (size_t i = 0; i < d_windowOverlap; i++) {
- const size_t out_ix = prefixlength + d_spacing - d_windowOverlap + i;
- const size_t in_ix = d_spacing - d_windowOverlap + i;
- out[out_ix] = in[in_ix] * d_window[2*d_windowOverlap - (i+1)];
- }
+ // Suffix is taken from the beginning of the symbol, and sees the other
+ // half of the window applied.
+ for (size_t i = 0; i < p.windowOverlap; i++) {
+ const size_t out_ix = prefixlength + p.spacing + i;
+ out[out_ix] = in[i] * p.window[p.windowOverlap - (i+1)];
+ }
- // Suffix is taken from the beginning of the symbol, and sees the other
- // half of the window applied.
- for (size_t i = 0; i < d_windowOverlap; i++) {
- const size_t out_ix = prefixlength + d_spacing + i;
- out[out_ix] = in[i] * d_window[d_windowOverlap - (i+1)];
+ in += p.spacing;
+ out += p.nullSize;
+ // out is now pointing to the proper end of symbol. There are
+ // windowOverlap samples ahead that were already written.
}
- in += d_spacing;
- out += d_nullSize;
- // out is now pointing to the proper end of symbol. There are
- // d_windowOverlap samples ahead that were already written.
- }
-
- // Data symbols
- for (size_t sym_ix = 0; sym_ix < d_nbSymbols; sym_ix++) {
- /* _ix variables are indices into in[], _ox variables are
- * indices for out[] */
- const ssize_t start_rise_ox = -d_windowOverlap;
- const size_t start_rise_ix = 2 * d_spacing - d_symSize - d_windowOverlap;
- /*
- const size_t start_real_symbol_ox = 0;
- const size_t start_real_symbol_ix = 2 * d_spacing - d_symSize;
- */
- const ssize_t end_rise_ox = d_windowOverlap;
- const size_t end_rise_ix = 2 * d_spacing - d_symSize + d_windowOverlap;
- const ssize_t end_cyclic_prefix_ox = d_symSize - d_spacing;
- /* end_cyclic_prefix_ix = end of symbol
- const size_t begin_fall_ox = d_symSize - d_windowOverlap;
- const size_t begin_fall_ix = d_spacing - d_windowOverlap;
- const size_t end_real_symbol_ox = d_symSize;
- end_real_symbol_ix = end of symbol
- const size_t end_fall_ox = d_symSize + d_windowOverlap;
- const size_t end_fall_ix = d_spacing + d_windowOverlap;
- */
-
- ssize_t ox = start_rise_ox;
- size_t ix = start_rise_ix;
-
- for (size_t i = 0; ix < end_rise_ix; i++) {
- out[ox] += in[ix] * d_window.at(i);
- ix++;
- ox++;
- }
- assert(ox == end_rise_ox);
-
- const size_t remaining_prefix_length = end_cyclic_prefix_ox - end_rise_ox;
- memcpy( &out[ox], &in[ix],
- remaining_prefix_length * sizeof(complexf));
- ox += remaining_prefix_length;
- assert(ox == end_cyclic_prefix_ox);
- ix = 0;
-
- const bool last_symbol = (sym_ix + 1 >= d_nbSymbols);
- if (last_symbol) {
- // No windowing at all at end
- memcpy(&out[ox], &in[ix], d_spacing * sizeof(complexf));
- ox += d_spacing;
- }
- else {
- // Copy the middle part of the symbol, d_windowOverlap samples
- // short of the end.
- memcpy( &out[ox],
- &in[ix],
- (d_spacing - d_windowOverlap) * sizeof(complexf));
- ox += d_spacing - d_windowOverlap;
- ix += d_spacing - d_windowOverlap;
- assert(ox == (ssize_t)(d_symSize - d_windowOverlap));
-
- // Apply window from 1 to 0.5 for the end of the symbol
- for (size_t i = 0; ox < (ssize_t)d_symSize; i++) {
- out[ox] = in[ix] * d_window[2*d_windowOverlap - (i+1)];
- ox++;
+ // Data symbols
+ for (size_t sym_ix = 0; sym_ix < p.nbSymbols; sym_ix++) {
+ /* _ix variables are indices into in[], _ox variables are
+ * indices for out[] */
+ const ssize_t start_rise_ox = -p.windowOverlap;
+ const size_t start_rise_ix = 2 * p.spacing - p.symSize - p.windowOverlap;
+ /*
+ const size_t start_real_symbol_ox = 0;
+ const size_t start_real_symbol_ix = 2 * p.spacing - p.symSize;
+ */
+ const ssize_t end_rise_ox = p.windowOverlap;
+ const size_t end_rise_ix = 2 * p.spacing - p.symSize + p.windowOverlap;
+ const ssize_t end_cyclic_prefix_ox = p.symSize - p.spacing;
+ /* end_cyclic_prefix_ix = end of symbol
+ const size_t begin_fall_ox = p.symSize - p.windowOverlap;
+ const size_t begin_fall_ix = p.spacing - p.windowOverlap;
+ const size_t end_real_symbol_ox = p.symSize;
+ end_real_symbol_ix = end of symbol
+ const size_t end_fall_ox = p.symSize + p.windowOverlap;
+ const size_t end_fall_ix = p.spacing + p.windowOverlap;
+ */
+
+ ssize_t ox = start_rise_ox;
+ size_t ix = start_rise_ix;
+
+ for (size_t i = 0; ix < end_rise_ix; i++) {
+ out[ox] += in[ix] * p.window.at(i);
ix++;
+ ox++;
}
- assert(ix == d_spacing);
+ assert(ox == end_rise_ox);
+ const size_t remaining_prefix_length = end_cyclic_prefix_ox - end_rise_ox;
+ memcpy( &out[ox], &in[ix],
+ remaining_prefix_length * sizeof(T));
+ ox += remaining_prefix_length;
+ assert(ox == end_cyclic_prefix_ox);
ix = 0;
- // Cyclic suffix, with window from 0.5 to 0
- for (size_t i = 0; ox < (ssize_t)(d_symSize + d_windowOverlap); i++) {
- out[ox] = in[ix] * d_window[d_windowOverlap - (i+1)];
- ox++;
- ix++;
+
+ const bool last_symbol = (sym_ix + 1 >= p.nbSymbols);
+ if (last_symbol) {
+ // No windowing at all at end
+ memcpy(&out[ox], &in[ix], p.spacing * sizeof(T));
+ ox += p.spacing;
+ }
+ else {
+ // Copy the middle part of the symbol, p.windowOverlap samples
+ // short of the end.
+ memcpy( &out[ox],
+ &in[ix],
+ (p.spacing - p.windowOverlap) * sizeof(T));
+ ox += p.spacing - p.windowOverlap;
+ ix += p.spacing - p.windowOverlap;
+ assert(ox == (ssize_t)(p.symSize - p.windowOverlap));
+
+ // Apply window from 1 to 0.5 for the end of the symbol
+ for (size_t i = 0; ox < (ssize_t)p.symSize; i++) {
+ out[ox] = in[ix] * p.window[2*p.windowOverlap - (i+1)];
+ ox++;
+ ix++;
+ }
+ assert(ix == p.spacing);
+
+ ix = 0;
+ // Cyclic suffix, with window from 0.5 to 0
+ for (size_t i = 0; ox < (ssize_t)(p.symSize + p.windowOverlap); i++) {
+ out[ox] = in[ix] * p.window[p.windowOverlap - (i+1)];
+ ox++;
+ ix++;
+ }
+
+ assert(ix == p.windowOverlap);
}
- assert(ix == d_windowOverlap);
+ out += p.symSize;
+ in += p.spacing;
+ // out is now pointing to the proper end of symbol. There are
+ // windowOverlap samples ahead that were already written.
}
-
- out += d_symSize;
- in += d_spacing;
- // out is now pointing to the proper end of symbol. There are
- // d_windowOverlap samples ahead that were already written.
+ }
+ else {
+ throw std::runtime_error("fixed-point doesn't support window overlap");
}
}
else {
// Handle Null symbol separately because it is longer
// end - (nullSize - spacing) = 2 * spacing - nullSize
- memcpy(out, &in[2 * d_spacing - d_nullSize],
- (d_nullSize - d_spacing) * sizeof(complexf));
- memcpy(&out[d_nullSize - d_spacing], in, d_spacing * sizeof(complexf));
- in += d_spacing;
- out += d_nullSize;
+ memcpy(out, &in[2 * p.spacing - p.nullSize],
+ (p.nullSize - p.spacing) * sizeof(T));
+ memcpy(&out[p.nullSize - p.spacing], in, p.spacing * sizeof(T));
+ in += p.spacing;
+ out += p.nullSize;
// Data symbols
- for (size_t i = 0; i < d_nbSymbols; ++i) {
+ for (size_t i = 0; i < p.nbSymbols; ++i) {
// end - (symSize - spacing) = 2 * spacing - symSize
- memcpy(out, &in[2 * d_spacing - d_symSize],
- (d_symSize - d_spacing) * sizeof(complexf));
- memcpy(&out[d_symSize - d_spacing], in, d_spacing * sizeof(complexf));
- in += d_spacing;
- out += d_symSize;
+ memcpy(out, &in[2 * p.spacing - p.symSize],
+ (p.symSize - p.spacing) * sizeof(T));
+ memcpy(&out[p.symSize - p.spacing], in, p.spacing * sizeof(T));
+ in += p.spacing;
+ out += p.symSize;
}
}
- return sizeIn;
+ const auto sizeOut = dataOut->getLength();
+ return sizeOut;
+}
+
+int GuardIntervalInserter::process(Buffer* const dataIn, Buffer* dataOut)
+{
+ switch (m_fftEngine) {
+ case FFTEngine::FFTW:
+ return do_process<complexf>(m_params, dataIn, dataOut);
+ case FFTEngine::KISS:
+ if (m_params.windowOverlap) {
+ throw std::runtime_error("fixed point and ofdm windowing not supported");
+ }
+ return do_process<complexfix>(m_params, dataIn, dataOut);
+ case FFTEngine::DEXTER:
+ return do_process<complexfix_wide>(m_params, dataIn, dataOut);
+ }
+ throw std::logic_error("Unhandled fftEngine variant");
}
void GuardIntervalInserter::set_parameter(
@@ -293,7 +323,7 @@ const std::string GuardIntervalInserter::get_parameter(const std::string& parame
using namespace std;
stringstream ss;
if (parameter == "windowlen") {
- ss << d_windowOverlap;
+ ss << m_params.windowOverlap;
}
else {
ss << "Parameter '" << parameter <<
@@ -306,6 +336,6 @@ const std::string GuardIntervalInserter::get_parameter(const std::string& parame
const json::map_t GuardIntervalInserter::get_all_values() const
{
json::map_t map;
- map["windowlen"].v = d_windowOverlap;
+ map["windowlen"].v = m_params.windowOverlap;
return map;
}