aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2024-11-26 10:00:28 +0100
committerMatthias P. Braendli <matthias.braendli@mpb.li>2024-11-26 10:00:28 +0100
commitc13b993a9cbf2dd8c60da19b11f63febe7bc39a8 (patch)
tree06223d42df6318e8761e7928bfb22ce5bacac16f /src
parent2e9500d4854a3db9e0f407021934407155b82776 (diff)
downloaddabmod-c13b993a9cbf2dd8c60da19b11f63febe7bc39a8.tar.gz
dabmod-c13b993a9cbf2dd8c60da19b11f63febe7bc39a8.tar.bz2
dabmod-c13b993a9cbf2dd8c60da19b11f63febe7bc39a8.zip
Restore ofdmwindowing for fixed point
Diffstat (limited to 'src')
-rw-r--r--src/GuardIntervalInserter.cpp250
-rw-r--r--src/GuardIntervalInserter.h7
2 files changed, 148 insertions, 109 deletions
diff --git a/src/GuardIntervalInserter.cpp b/src/GuardIntervalInserter.cpp
index 26d4fd1..3ff8fd5 100644
--- a/src/GuardIntervalInserter.cpp
+++ b/src/GuardIntervalInserter.cpp
@@ -2,7 +2,7 @@
Copyright (C) 2005, 2206, 2007, 2008, 2009, 2010, 2011 Her Majesty
the Queen in Right of Canada (Communications Research Center Canada)
- Copyright (C) 2023
+ Copyright (C) 2024
Matthias P. Braendli, matthias.braendli@mpb.li
http://opendigitalradio.org
@@ -100,9 +100,15 @@ void GuardIntervalInserter::update_window(size_t new_window_overlap)
m_params.windowOverlap = new_window_overlap;
// m_params.window only contains the rising window edge.
- m_params.window.resize(2*m_params.windowOverlap);
+ m_params.windowFloat.resize(2*m_params.windowOverlap);
+ m_params.windowFix.resize(2*m_params.windowOverlap);
+ m_params.windowFixWide.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))));
+ const float value = (float)(0.5 * (1.0 - cos(M_PI * i / (2*m_params.windowOverlap - 1))));
+
+ m_params.windowFloat[i] = value;
+ m_params.windowFix[i] = complexfix::value_type((double)value);
+ m_params.windowFixWide[i] = complexfix_wide::value_type((double)value);
}
}
@@ -141,120 +147,155 @@ int do_process(const GuardIntervalInserter::Params& p, Buffer* const dataIn, Buf
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)];
+ {
+ // 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;
+ if constexpr (std::is_same_v<complexf, T>) {
+ out[out_ix] = in[in_ix] * p.windowFloat[2*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 < p.windowOverlap; i++) {
- const size_t out_ix = prefixlength + p.spacing + i;
- out[out_ix] = in[i] * p.window[p.windowOverlap - (i+1)];
+ if constexpr (std::is_same_v<complexfix, T>) {
+ out[out_ix] = in[in_ix] * p.windowFix[2*p.windowOverlap - (i+1)];
+ }
+ if constexpr (std::is_same_v<complexfix_wide, T>) {
+ out[out_ix] = in[in_ix] * p.windowFixWide[2*p.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.
}
- // 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++;
+ // 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;
+ if constexpr (std::is_same_v<complexf, T>) {
+ out[out_ix] = in[i] * p.windowFloat[p.windowOverlap - (i+1)];
+ }
+ if constexpr (std::is_same_v<complexfix, T>) {
+ out[out_ix] = in[i] * p.windowFix[p.windowOverlap - (i+1)];
+ }
+ if constexpr (std::is_same_v<complexfix_wide, T>) {
+ out[out_ix] = in[i] * p.windowFixWide[p.windowOverlap - (i+1)];
}
- 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;
+ 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.
+ }
- 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;
+ // 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++) {
+ if constexpr (std::is_same_v<complexf, T>) {
+ out[ox] += in[ix] * p.windowFloat.at(i);
+ }
+ if constexpr (std::is_same_v<complexfix, T>) {
+ out[ox] += in[ix] * p.windowFix.at(i);
}
- 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++;
+ if constexpr (std::is_same_v<complexfix_wide, T>) {
+ out[ox] += in[ix] * p.windowFixWide.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(T));
+ ox += remaining_prefix_length;
+ assert(ox == end_cyclic_prefix_ox);
+ ix = 0;
+
+ 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++) {
+ if constexpr (std::is_same_v<complexf, T>) {
+ out[ox] = in[ix] * p.windowFloat[2*p.windowOverlap - (i+1)];
+ }
+ if constexpr (std::is_same_v<complexfix, T>) {
+ out[ox] = in[ix] * p.windowFix[2*p.windowOverlap - (i+1)];
}
- 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++;
+ if constexpr (std::is_same_v<complexfix_wide, T>) {
+ out[ox] = in[ix] * p.windowFixWide[2*p.windowOverlap - (i+1)];
}
+ ox++;
+ ix++;
+ }
+ assert(ix == p.spacing);
- assert(ix == p.windowOverlap);
+ ix = 0;
+ // Cyclic suffix, with window from 0.5 to 0
+ for (size_t i = 0; ox < (ssize_t)(p.symSize + p.windowOverlap); i++) {
+ if constexpr (std::is_same_v<complexf, T>) {
+ out[ox] = in[ix] * p.windowFloat[p.windowOverlap - (i+1)];
+ }
+ if constexpr (std::is_same_v<complexfix, T>) {
+ out[ox] = in[ix] * p.windowFix[p.windowOverlap - (i+1)];
+ }
+ if constexpr (std::is_same_v<complexfix_wide, T>) {
+ out[ox] = in[ix] * p.windowFixWide[p.windowOverlap - (i+1)];
+ }
+ ox++;
+ ix++;
}
- 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.
+ assert(ix == p.windowOverlap);
}
- }
- else {
- throw std::runtime_error("fixed-point doesn't support window overlap");
+
+ 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.
}
}
else {
@@ -287,9 +328,6 @@ int GuardIntervalInserter::process(Buffer* const dataIn, Buffer* dataOut)
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);
diff --git a/src/GuardIntervalInserter.h b/src/GuardIntervalInserter.h
index 8d329ff..738d5b3 100644
--- a/src/GuardIntervalInserter.h
+++ b/src/GuardIntervalInserter.h
@@ -2,7 +2,7 @@
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty
the Queen in Right of Canada (Communications Research Center Canada)
- Copyright (C) 2023
+ Copyright (C) 2024
Matthias P. Braendli, matthias.braendli@mpb.li
http://opendigitalradio.org
@@ -33,7 +33,6 @@
#include "ConfigParser.h"
#include "ModPlugin.h"
#include "RemoteControl.h"
-#include <stdint.h>
#include <vector>
/* The GuardIntervalInserter prepends the cyclic prefix to all
@@ -79,7 +78,9 @@ class GuardIntervalInserter : public ModCodec, public RemoteControllable
size_t& windowOverlap;
mutable std::mutex windowMutex;
- std::vector<float> window;
+ std::vector<float> windowFloat;
+ std::vector<complexfix::value_type> windowFix;
+ std::vector<complexfix_wide::value_type> windowFixWide;
};
protected: