feat: pass fps dynamically

This commit is contained in:
2026-05-19 22:36:24 +02:00
parent d4e0241590
commit 58ed5df87c
10 changed files with 71 additions and 50 deletions

View File

@@ -27,11 +27,18 @@ static std::vector<double> make_ones(size_t sw) {
return ones;
}
SsfFilter::SsfFilter(size_t upslope_width) :
sw(upslope_width),
static int get_upslope_width(double fps) {
// was 4 at 60 fps = 66.7 ms
if (fps == 4.0) throw std::invalid_argument("check SsfFilter ctor call, must pass fps now"); // nice-to remove
int usw = static_cast<int>(std::round(0.0667 * fps));
if (usw == 0) throw std::invalid_argument("upslope_width = 0 computed - low fps?");
return usw;
}
SsfFilter::SsfFilter(double fps) :
// Filt(N, shift, offset, taps)
f_delta_u(2, 0, 0, std::vector<double> {1.0, -1.0}),
f_window(upslope_width, 0, 0, make_ones(upslope_width))
f_window(get_upslope_width(fps), 0, 0, make_ones(get_upslope_width(fps)))
{}
double SsfFilter::filter(double val) {
double du = f_delta_u.filter(val);
@@ -40,18 +47,41 @@ double SsfFilter::filter(double val) {
return ssf;
}
size_t SsfStepDetector::initial_samples() { return (size_t) (3.0 * FPS); }
SsfStepDetector::SsfStepDetector(size_t len_refr) :
static size_t get_initial_samples(double fps) {
if (fps == 12.0) throw std::invalid_argument("check SsfStepDetector ctor call, must pass fps now"); // nice-to remove
int init_samp = static_cast<int>(std::round(3.0 * fps));
if (init_samp == 0) throw std::invalid_argument("init_samp = 0 computed - low fps?");
return init_samp;
}
size_t SsfStepDetector::initial_samples(double fps) { return get_initial_samples(fps); }
static size_t get_len_refr(double fps) {
if (fps == 12.0) throw std::invalid_argument("check SsfStepDetector ctor call, must pass fps now"); // nice-to remove
size_t len_refr = static_cast<size_t>(std::round(fps / (MAX_BPM / 60)));
if (len_refr == 0) throw std::invalid_argument("len_refr = 0 computed - low fps?");
return len_refr;
}
static int get_len_ssf_th_smoothing(double fps) {
// was 6 at 60 fps = 100 ms
if (fps == 12.0) throw std::invalid_argument("check SsfStepDetector ctor call, must pass fps now"); // nice-to remove
int sts = static_cast<int>(std::round(0.100 * fps));
if (sts == 0) throw std::invalid_argument("len_ssf_th_smoothing = 0 computed - low fps?");
return sts;
}
SsfStepDetector::SsfStepDetector(double fps) :
// note: also change above, in initial_samples()
LEN_INIT((size_t) (3.0 * FPS)), // initial window length for ssf_threshold
LEN_TH_WIN((size_t) (3.0 * FPS)), // subsequent window length for ssf_threshold
LEN_INIT(get_initial_samples(fps)), // initial window length for ssf_threshold
LEN_TH_WIN(get_initial_samples(fps)), // subsequent window length for ssf_threshold
num_samples(0),
ssf_threshold(std::numeric_limits<double>::infinity()),
ssf_threshold_nm1(std::numeric_limits<double>::infinity()),
f_ssf_threshold_smoothing(6, 0, 0, make_ones(6)),
len_refr(len_refr), n_refr(0), is_refr(false),
f_ssf_threshold_smoothing(get_len_ssf_th_smoothing(fps), 0, 0, make_ones(get_len_ssf_th_smoothing(fps))),
len_refr(get_len_refr(fps)), n_refr(0), is_refr(false),
ssf_nm1(0.0),
ssf_usw2(get_upslope_width(fps)/2),
f_ssf_mean(LEN_TH_WIN, 0, 0, make_ones(LEN_TH_WIN))
{
assert (LEN_INIT >= LEN_TH_WIN && "LEN_INIT < LEN_TH_WIN, check normalization of initial ssf_threshold");
@@ -89,12 +119,10 @@ double SsfStepDetector::filter(double ssf) {
} else if (num_samples > LEN_TH_WIN) {
//DEBUG_PRINT(std::cerr << "adaptive threshold setting" << std::endl);
// adaptive threshold setting
// +2 is half the window size
// TODO: param upon SsfFilter.upslope_width/2 instead of hardcoding -- also f_ssf_threshold_smoothing(), nb. should be even number
if (num_samples == n_refr + 2) {
// the ssf peak comes SsfFilter.upslope_width/2 = 3 samples (half-window + 1 sample) after the crossing
if (num_samples == n_refr + ssf_usw2 + 1) {
//DEBUG_PRINT(std::cerr << "setting adaptive threshold setting" << std::endl);
ssf_threshold_nm1 = ssf_threshold;
// the ssf peak comes 3 samples (half-window + 1 sample) after the crossing
ssf_threshold = f_ssf_threshold_smoothing.filter(ssf) / ((double) f_ssf_threshold_smoothing.size()) * 0.6;
}
}
@@ -193,7 +221,7 @@ bool RunningQuality::append(std::vector<double> &rawBeat, std::vector<double> &r
}
RunningQualityFilter::RunningQualityFilter(size_t upslope_width) : sqi(0.0) {}
RunningQualityFilter::RunningQualityFilter(double fps) : sqi(0.0) {}
double RunningQualityFilter::filter(double y, double ssf, double step) {
if (step == 1.0) {