feat: RunningQuality - running SQI

This commit is contained in:
2026-03-09 18:38:21 +01:00
parent fe300dabd3
commit 95d1fee44d
4 changed files with 209 additions and 3 deletions

View File

@@ -20,7 +20,19 @@ namespace pd_signal {
void interp(std::vector<double>& y, std::vector<double>& x, std::vector<double>& xp, std::vector<double>& fp);
/** resample to BEAT_LEN */
void resample(std::vector<double> &out, std::vector<double> x, int beat_len);
void resample(std::vector<double> &out, std::vector<double> &x, int beat_len);
/**
* normalized cross-correlation of the two signals of same length.
* normalization factor is <c>1 / sqrt(\sum_i x_i^2 * \sum_i y_i^2)</c>
*/
double crossCorr(std::vector<double> &x, std::vector<double> &y);
/** clip 'val' to between 'a_min' and 'a_max'. */
double clip(double val, double a_min, double a_max);
/** two-dimensional mean of a collection of signals */
void mean(std::vector<double> &out, std::vector<std::vector<double> >& m);
}

View File

@@ -5,6 +5,7 @@
#include "include/pd_signal.h"
#include <stdexcept>
#include <algorithm>
#include <iostream>
namespace pd_signal {
@@ -86,7 +87,7 @@ void interp(std::vector<double>& y, std::vector<double>& x, std::vector<double>&
}
// resample to BEAT_LEN
void resample(std::vector<double> &out, std::vector<double> x, int beat_len) {
void resample(std::vector<double> &out, std::vector<double> &x, int beat_len) {
std::vector<double> t;
std::vector<double> i;
linspace(t, 0, (double) x.size(), beat_len, false);
@@ -94,4 +95,41 @@ void resample(std::vector<double> &out, std::vector<double> x, int beat_len) {
interp(out, t, i, x);
}
// normalized cross-correlation of the two signals of same length
double crossCorr(std::vector<double> &x, std::vector<double> &y) {
if (x.size() != y.size()) throw std::invalid_argument("x.size() != y.size()");
double xs = 0.0, ys = 0.0, cs = 0.0;
for (size_t i = 0; i < x.size(); i++) {
xs += x[i] * x[i];
ys += y[i] * y[i];
cs += x[i] * y[i];
}
return cs / sqrt(xs * ys);
}
// clip 'val' to between 'a_min' and 'a_max'.
double clip(double val, double a_min, double a_max) {
return std::min(std::max(val, a_min), a_max);
}
// two-dimensional mean of a collection of signals
void mean(std::vector<double> &out, std::vector<std::vector<double> >& m) {
if (m.empty()) {
out.resize(0);
return;
}
const size_t sz = m[0].size();
out.resize(sz);
out.assign(sz, 0.0);
const size_t N = m.size();
for (size_t i = 0; i < N; i++) {
for (size_t j = 0; j < sz; j++) {
out[j] += m[i][j];
}
}
for (size_t j = 0; j < sz; j++) {
out[j] /= static_cast<double>(N);
}
}
}

View File

@@ -17,7 +17,7 @@ static std::vector<double> make_ones(size_t sw) {
SsfFilter::SsfFilter(size_t upslope_width) :
sw(upslope_width),
// Filt(N, shift, offset, taps)
f_delta_u(2, 0, 0, std::vector {1.0, -1.0}),
f_delta_u(2, 0, 0, std::vector<double> {1.0, -1.0}),
f_window(upslope_width, 0, 0, make_ones(upslope_width))
{}
double SsfFilter::filter(double val) {