feat: pd_signal: resample, linspace

This commit is contained in:
2026-03-04 16:27:00 +01:00
parent 0fb4c4d6c1
commit fe300dabd3
3 changed files with 51 additions and 3 deletions

View File

@@ -17,7 +17,7 @@ TEST(SignalTest, interp_t1) {
// 5.99494949495 = (5.5-5.01)/0.99*(7-5.01)+5.01
std::vector<double> 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<double> 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);
}

View File

@@ -8,11 +8,20 @@
#include <vector>
namespace pd_signal {
/** `num` evenly spaced numbers over interval [start,stop] */
void linspace(std::vector<double>& 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<double>& 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<double>& x, std::vector<double>& xp, std::vector<double>& fp, std::vector<double>& y);
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);
}
#endif //PASADASUPERPROJECT_SIGNAL_H

View File

@@ -23,8 +23,28 @@ static int binarySearch(std::vector<double>& data, double x) {
return -(insertion_point) - 1; // no element found directly
}
void linspace(std::vector<double>& 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<double>& 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<double>& x, std::vector<double>& xp, std::vector<double>& fp, std::vector<double>& y) {
void interp(std::vector<double>& y, std::vector<double>& x, std::vector<double>& xp, std::vector<double>& 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<double>& x, std::vector<double>& xp, std::vector<double>
}
}
// resample to 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);
linspace(i, 0, (int) (x.size()-1), (int) x.size(), false);
interp(out, t, i, x);
}
}