Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Search bpm fuzzy halfdouble #68

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 23 additions & 9 deletions src/library/searchquery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

namespace {

constexpr double kLibraryRoundRange = 0.05;

const QRegularExpression kDurationRegex(QStringLiteral("^(\\d+)(m|:)?([0-5]?\\d)?s?$"));

// The ordering of operator alternatives separated by '|' is crucial to avoid incomplete
Expand Down Expand Up @@ -506,6 +508,7 @@ inline QString rangeUpperExclusiveSqlString(double lower, double upper) {
inline std::pair<double, double> rangeFromTrailingDecimal(double bpm) {
// Set up a range if we have decimals. This will include matches
// for which we show rounded values in the library. For example
// 124.0 finds 123.95 - 124.05
// 124.1 finds 124.05 - 124.15
// 124.92 finds 124.915 - 124.925
if (bpm == 0.0) {
Expand Down Expand Up @@ -637,17 +640,28 @@ BpmFilterNode::BpmFilterNode(QString& argument, bool fuzzy, bool negate)
break;
}
case MatchMode::HalveDouble: {
DEBUG_ASSERT(bpm == floor(bpm));
// For instance bpm = 127
// We find everything that is displayed as 127.** in the library
m_rangeLower = rangeFromTrailingDecimal(bpm).first; // [126.95
m_rangeUpper = floor(bpm + 1); // ]128
// In case bpm / 2 is a fractional, we include the *.0 value neighbours
// since fractional bpm values are less common in some genres.
m_bpmHalfLower = floor(bpm / 2); // [63
m_bpmHalfUpper = ceil(bpm / 2); // 64]
m_rangeLower = bpm - kLibraryRoundRange; // [126.95
m_rangeUpper = bpm + 1; // ]128

double halfBpm = bpm / 2;
qDebug() << "if (floor(halfBpm) != halfBpm) {" << floor(halfBpm) << halfBpm;
if (floor(halfBpm) != halfBpm) {
// In case bpm / 2 is a fractional, we include the *.0 value neighbours
// since fractional bpm values are less common in some genres.
m_bpmHalfLower = floor(halfBpm) - kLibraryRoundRange; // [62.95
m_bpmHalfUpper = halfBpm + 1; // ]64.5
} else {
// Here we are for instance with 126
// We find everything that is displayed as 63.** in the library
m_bpmHalfLower = halfBpm - kLibraryRoundRange; // [62.95
m_bpmHalfUpper = halfBpm + 1; // ]64
}
// We find everything which would be found when editing the beat grid via / 2
m_bpmDoubleLower = rangeFromTrailingDecimal(bpm * 2).first; // [253.95
m_bpmDoubleUpper = m_rangeUpper * 2; // ]256
m_bpmDoubleLower = (bpm * 2) - kLibraryRoundRange; // [253.95
m_bpmDoubleUpper = m_rangeUpper * 2; // ]256
break;
}
case MatchMode::HalveDoubleStrict: { // 57.0
Expand Down Expand Up @@ -725,7 +739,7 @@ QString BpmFilterNode::toSql() const {
case MatchMode::HalveDouble: {
QStringList searchClauses;
searchClauses << rangeUpperExclusiveSqlString(m_rangeLower, m_rangeUpper);
searchClauses << rangeSqlString(m_bpmHalfLower, m_bpmHalfUpper);
searchClauses << rangeUpperExclusiveSqlString(m_bpmHalfLower, m_bpmHalfUpper);
searchClauses << rangeUpperExclusiveSqlString(m_bpmDoubleLower, m_bpmDoubleUpper);
return concatSqlClauses(searchClauses, "OR");
}
Expand Down
19 changes: 16 additions & 3 deletions src/test/searchqueryparsertest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -498,16 +498,29 @@ TEST_F(SearchQueryParserTest, BpmFilter) {
m_parser.setSearchColumns({"artist", "album"});

// Test BpmFilter's MatchModes:
// HalveDouble
auto pQuery(m_parser.parseQuery("bpm:127", QString()));

// HalveDouble even
auto pQuery = m_parser.parseQuery("bpm:126", QString());
TrackPointer pTrack = newTestTrack();
EXPECT_FALSE(pQuery->match(pTrack));
pTrack->trySetBpm(126.13);
EXPECT_TRUE(pQuery->match(pTrack));

EXPECT_STREQ(
qPrintable(QString("(bpm >= 125.95 AND bpm < 127) OR "
"(bpm >= 62.95 AND bpm < 64) OR "
"(bpm >= 251.95 AND bpm < 254)")),
qPrintable(pQuery->toSql()));

// HalveDouble uneven
pQuery = m_parser.parseQuery("bpm:127", QString());
EXPECT_FALSE(pQuery->match(pTrack));
pTrack->trySetBpm(127.13);
EXPECT_TRUE(pQuery->match(pTrack));

EXPECT_STREQ(
qPrintable(QString("(bpm >= 126.95 AND bpm < 128) OR "
"(bpm BETWEEN 63 AND 64) OR "
"(bpm >= 62.95 AND bpm < 64.5) OR "
"(bpm >= 253.95 AND bpm < 256)")),
qPrintable(pQuery->toSql()));

Expand Down