From fe300dabd307fcfc9f22a05c95427e3c0e7b3ceb Mon Sep 17 00:00:00 2001 From: David Madl Date: Wed, 4 Mar 2026 16:27:00 +0100 Subject: [PATCH] feat: pd_signal: resample, linspace --- google-tests/test3.cpp | 12 +++++++++++- pasada-lib/include/pd_signal.h | 11 ++++++++++- pasada-lib/pd_signal.cpp | 31 ++++++++++++++++++++++++++++++- 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/google-tests/test3.cpp b/google-tests/test3.cpp index db6cb3d..e148b92 100644 --- a/google-tests/test3.cpp +++ b/google-tests/test3.cpp @@ -17,7 +17,7 @@ TEST(SignalTest, interp_t1) { // 5.99494949495 = (5.5-5.01)/0.99*(7-5.01)+5.01 std::vector y; - interp(x, xp, fp, y); + interp(y, x, xp, fp); // assert y == y_e, nb. upto 5 digits double abs_err = 1e-5; @@ -25,3 +25,13 @@ TEST(SignalTest, interp_t1) { ASSERT_NEAR(y_e[i], y[i], abs_err + 1e-9 * i); } } + +TEST(SignalTest, ranges) { + const double abs_error = 1e-5; + std::vector i; + size_t N = 3; + linspace(i, 0, (int) (N-1), (int) N, false); + ASSERT_NEAR(0.0, i[0], abs_error); + ASSERT_NEAR(1.0, i[1], abs_error); + ASSERT_NEAR(2.0, i[2], abs_error); +} diff --git a/pasada-lib/include/pd_signal.h b/pasada-lib/include/pd_signal.h index 4745a5c..2e32cac 100644 --- a/pasada-lib/include/pd_signal.h +++ b/pasada-lib/include/pd_signal.h @@ -8,11 +8,20 @@ #include namespace pd_signal { + /** `num` evenly spaced numbers over interval [start,stop] */ + void linspace(std::vector& data, double start, double stop, int num); + /** `num` evenly spaced numbers over interval [start,stop] with endpoint=true or [start,stop) with endpoint=false */ + void linspace(std::vector& data, double start, double stop, int num, bool endpoint); + /** * Evaluate at points x the function given by the samples fp[xp[n]]. * Returned in y. */ - void interp(std::vector& x, std::vector& xp, std::vector& fp, std::vector& y); + void interp(std::vector& y, std::vector& x, std::vector& xp, std::vector& fp); + + /** resample to BEAT_LEN */ + void resample(std::vector &out, std::vector x, int beat_len); + } #endif //PASADASUPERPROJECT_SIGNAL_H \ No newline at end of file diff --git a/pasada-lib/pd_signal.cpp b/pasada-lib/pd_signal.cpp index 2a18e58..dfc6d3c 100644 --- a/pasada-lib/pd_signal.cpp +++ b/pasada-lib/pd_signal.cpp @@ -23,8 +23,28 @@ static int binarySearch(std::vector& data, double x) { return -(insertion_point) - 1; // no element found directly } +void linspace(std::vector& data, double start, double stop, int num) { + linspace(data, start, stop, num, true); +} + +// `num` evenly spaced numbers over interval [start,stop] with endpoint=true or [start,stop) with endpoint=false +void linspace(std::vector& data, double start, double stop, int num, bool endpoint) { + if(num < 0) throw std::invalid_argument("num must be >= 0"); + + int end = endpoint ? num : (num-1); + double step = (stop - start) / (double) end; + + double d = start; + data.resize(num); + + for(int i = 0; i < num; i++) { + data[i] = d; + d += step; + } +} + // Evaluate at points x the function given by the samples fp[xp[n]]. -void interp(std::vector& x, std::vector& xp, std::vector& fp, std::vector& y) { +void interp(std::vector& y, std::vector& x, std::vector& xp, std::vector& fp) { if (xp.size() != fp.size()) throw std::invalid_argument("xp.size() != fp.size()"); size_t N = xp.size(); size_t M = x.size(); @@ -65,4 +85,13 @@ void interp(std::vector& x, std::vector& xp, std::vector } } +// resample to BEAT_LEN +void resample(std::vector &out, std::vector x, int beat_len) { + std::vector t; + std::vector i; + linspace(t, 0, (double) x.size(), beat_len, false); + linspace(i, 0, (int) (x.size()-1), (int) x.size(), false); + interp(out, t, i, x); +} + }