Skip to content

Commit

Permalink
Implement temposync typein (string to) with test (#176)
Browse files Browse the repository at this point in the history
  • Loading branch information
baconpaul authored Feb 15, 2025
1 parent c10e0ef commit 2297486
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 0 deletions.
53 changes: 53 additions & 0 deletions include/sst/basic-blocks/params/ParamMetadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -848,6 +848,7 @@ struct ParamMetaData

// For now, his is the temposync notation assuming a 2^x and temposync ratio based on 120bpm
std::string temposyncNotation(float f) const;
std::optional<float> valueFromTemposyncNotation(const std::string &s) const;
float snapToTemposync(float f) const;

/*
Expand Down Expand Up @@ -1671,6 +1672,58 @@ inline std::string ParamMetaData::temposyncNotation(float f) const
return res;
}

inline std::optional<float> ParamMetaData::valueFromTemposyncNotation(const std::string &s) const
{
// OK so the basic idea is marching down the string we have numbers and slashes
// then characters from a constrained set
std::string numPart;
std::string restPart;
bool inNum{true};
for (const auto &c : s)
{
if (inNum && ((c >= '0' && c <= '9') || c == '/' || c == ' '))
{
numPart += c;
}
else
{
inNum = false;
if (c != ' ')
restPart += std::toupper(c);
}
}
if (numPart.empty())
return std::nullopt;

auto slpos = numPart.find('/');
auto num = 0, den = 1;
if (slpos == std::string::npos)
{
num = std::stoi(numPart);
}
else
{
num = std::stoi(numPart.substr(0, slpos));
den = std::stoi(numPart.substr(slpos + 1));
}
if (den == 0)
return std::nullopt;

// 1/2 should be 0, 1/4 should be 1
auto frac = 2.0 * num / den;
auto ufrac = 1.0 / frac;
auto pfrac = std::floor(std::log2(ufrac));

if (restPart == "T")
pfrac += 0.51;
if (restPart == "D" || restPart == ".")
{
pfrac -= 0.6;
}

return snapToTemposync(pfrac);
}

inline float ParamMetaData::snapToTemposync(float f) const
{
assert(canTemposync);
Expand Down
30 changes: 30 additions & 0 deletions tests/param_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,3 +355,33 @@ TEST_CASE("25 Second Exp", "[param]")
REQUIRE(md.has_value());
}
}

TEST_CASE("Temposync type In")
{
std::vector<std::pair<std::string, std::string>> cases = {
{"1/32", "1/32 note"}, {"1/16", "1/16 note"}, {"1/8", "1/8 note"},
{"1/4", "1/4 note"}, {"1/2", "1/2 note"}, {"1", "whole note"},
{"1W", "whole note"}, {"2", "double whole note"}, {"2W", "double whole note"},

{"1/4 d", "1/4 dotted"}, {"1/4 .", "1/4 dotted"}, {"1/4.", "1/4 dotted"},
{"1/4d", "1/4 dotted"},

{"1/8 t", "1/8 triplet"}, {"1/16t", "1/16 triplet"},

{"1/4 t", "1/4 triplet"}, {"1/4t", "1/4 triplet"}, {"1/2t", "1/2 triplet"},
{"1T", "whole triplet"},
};
for (const auto &[in, out] : cases)
{
DYNAMIC_SECTION("Convert " << in << " to " << out)
{
auto p = pmd::ParamMetaData().asLfoRate();
auto v = p.valueFromTemposyncNotation(in);
REQUIRE(v.has_value());
auto s = p.valueToString(*v, pmd::ParamMetaData::FeatureState().withTemposync(true));
REQUIRE(s.has_value());
INFO("Result is " << *s << " " << *v);
REQUIRE(*s == out);
}
}
}

0 comments on commit 2297486

Please sign in to comment.