49int Resample::gcd(
int a,
int b)
61RowVectorXd Resample::buildKernel(
int p,
int q,
int iNZeros)
63 int M = std::max(p, q);
64 int halfLen = iNZeros * M;
65 int L = 2 * halfLen + 1;
73 const double fc =
static_cast<double>(std::min(p, q)) / (2.0 *
static_cast<double>(M));
76 for (
int k = 0; k < L; ++k) {
77 double n = k - halfLen;
78 double win = 0.54 - 0.46 * std::cos(2.0 *
M_PI * k / (L - 1));
80 if (std::abs(n) < 1e-10) {
81 h(k) = 2.0 * fc * win;
84 h(k) = std::sin(2.0 *
M_PI * fc * n) / (
M_PI * n) * win;
89 h *=
static_cast<double>(p);
95RowVectorXd Resample::polyphaseConv(
const RowVectorXd& vecX,
96 const RowVectorXd& vecH,
101 const long long nIn =
static_cast<long long>(vecX.size());
102 const long long L =
static_cast<long long>(vecH.size());
105 const long long nOut = (nIn * p + q - 1) / q;
109 for (
long long m = 0; m < nOut; ++m) {
112 long long center = m *
static_cast<long long>(q) + halfLen;
118 long long j_min = (center - L + 1 + p - 1) / p;
121 long long j_max = center / p;
126 for (
long long j = j_min; j <= j_max; ++j) {
127 long long tap = center - j *
static_cast<long long>(p);
128 if (tap >= 0 && tap < L) {
129 val += vecH(
static_cast<int>(tap)) * vecX(
static_cast<int>(j));
132 y(
static_cast<int>(m)) = val;
147 if (vecData.size() == 0) {
148 qWarning() <<
"Resample::resample: empty input.";
151 if (dNewSFreq <= 0.0 || dOldSFreq <= 0.0) {
152 qWarning() <<
"Resample::resample: sampling frequencies must be positive.";
158 const int scale = 1000;
159 int p_raw =
static_cast<int>(std::round(dNewSFreq * scale));
160 int q_raw =
static_cast<int>(std::round(dOldSFreq * scale));
161 int g = gcd(p_raw, q_raw);
169 const int halfLen = iNZeros * std::max(p, q);
170 RowVectorXd h = buildKernel(p, q, iNZeros);
172 return polyphaseConv(vecData, h, p, q, halfLen);
180 const RowVectorXi& vecPicks,
183 if (matData.size() == 0)
187 const int scale = 1000;
188 int p_raw =
static_cast<int>(std::round(dNewSFreq * scale));
189 int q_raw =
static_cast<int>(std::round(dOldSFreq * scale));
190 int g = gcd(p_raw, q_raw);
197 const int halfLen = iNZeros * std::max(p, q);
198 RowVectorXd h = buildKernel(p, q, iNZeros);
200 const int nIn =
static_cast<int>(matData.cols());
201 const int nOut =
static_cast<int>((
static_cast<long long>(nIn) * p + q - 1) / q);
202 const int nCh =
static_cast<int>(matData.rows());
204 MatrixXd result(nCh, nOut);
206 if (vecPicks.size() == 0) {
207 for (
int i = 0; i < nCh; ++i) {
208 result.row(i) = polyphaseConv(matData.row(i), h, p, q, halfLen);
215 for (
int k = 0; k < vecPicks.size(); ++k) {
217 if (i >= 0 && i < nCh) {
218 result.row(i) = polyphaseConv(matData.row(i), h, p, q, halfLen);
Declaration of Resample — polyphase anti-aliased rational resampling for MEG/EEG data.
Shared utilities (I/O helpers, spectral analysis, layout management, warp algorithms).
static Eigen::RowVectorXd resample(const Eigen::RowVectorXd &vecData, double dNewSFreq, double dOldSFreq, int iNZeros=10)
static Eigen::MatrixXd resampleMatrix(const Eigen::MatrixXd &matData, double dNewSFreq, double dOldSFreq, const Eigen::RowVectorXi &vecPicks=Eigen::RowVectorXi(), int iNZeros=10)