Skip to content

Commit

Permalink
Merge pull request #3205 from uklotzde/compatible_keys
Browse files Browse the repository at this point in the history
Extend compatible keys from 4 to 6 possible keys
  • Loading branch information
daschuer authored Oct 23, 2020
2 parents f3895f7 + 55ef2c9 commit 6f2ad03
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 35 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
* Fix missing manual in deb package lp:1889776
* Fix caching of duplicate tracks that reference the same file #3027
* Fix loss of precision when dealing with floating-point sample positions while setting loop out position and seeking using vinyl control #3126 #3127
* prevent moving a loop beyond track end #3117 https://bugs.launchpad.net/mixxx/+bug/1799574
* Prevent moving a loop beyond track end #3117 https://bugs.launchpad.net/mixxx/+bug/1799574
* Use 6 instead of only 4 compatible musical keys (major/minor) #3205

==== 2.2.4 2020-05-10 ====

Expand Down
42 changes: 21 additions & 21 deletions src/test/keyutilstest.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include <QDebug>

#include "track/keyutils.h"
#include "proto/keys.pb.h"
#include "track/keyutils.h"

using ::testing::ElementsAre;

namespace {
using ::testing::UnorderedElementsAre;

class KeyUtilsTest : public testing::Test {
};
Expand Down Expand Up @@ -206,30 +205,31 @@ TEST_F(KeyUtilsTest, ShortestStepsToKey) {
}

TEST_F(KeyUtilsTest, GetCompatibleKeys) {
// The relative major, the perfect 4th and the perfect 5th are all
// compatible. This is easily checked with the Circle of Fifths.
// The relative major/minor, the perfect 4th major/minor and the
// perfect 5th major/minor are all compatible. This is easily
// checked with the Circle of Fifths.

// Test keys on the boundary between 1 and 12 to check that wrap-around
// works.
mixxx::track::io::key::ChromaticKey key =
mixxx::track::io::key::A_MINOR;
QList<mixxx::track::io::key::ChromaticKey> compatible =
KeyUtils::getCompatibleKeys(key);
qSort(compatible);
EXPECT_THAT(compatible, ElementsAre(
mixxx::track::io::key::C_MAJOR,
mixxx::track::io::key::D_MINOR,
mixxx::track::io::key::E_MINOR,
mixxx::track::io::key::A_MINOR));
EXPECT_THAT(compatible,
UnorderedElementsAre(mixxx::track::io::key::C_MAJOR,
mixxx::track::io::key::F_MAJOR,
mixxx::track::io::key::G_MAJOR,
mixxx::track::io::key::D_MINOR,
mixxx::track::io::key::E_MINOR,
mixxx::track::io::key::A_MINOR));

key = mixxx::track::io::key::F_MAJOR;
compatible = KeyUtils::getCompatibleKeys(key);
qSort(compatible);
EXPECT_THAT(compatible, ElementsAre(
mixxx::track::io::key::C_MAJOR,
mixxx::track::io::key::F_MAJOR,
mixxx::track::io::key::B_FLAT_MAJOR,
mixxx::track::io::key::D_MINOR));
EXPECT_THAT(compatible,
UnorderedElementsAre(mixxx::track::io::key::C_MAJOR,
mixxx::track::io::key::F_MAJOR,
mixxx::track::io::key::B_FLAT_MAJOR,
mixxx::track::io::key::D_MINOR,
mixxx::track::io::key::A_MINOR,
mixxx::track::io::key::G_MINOR));
}

} // namespace
8 changes: 0 additions & 8 deletions src/test/rescalertest.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include <QDebug>

#include "util/math.h"
#include "util/rescaler.h"


using ::testing::ElementsAre;

namespace {

class RescalerUtilsTest : public testing::Test {
};

Expand Down Expand Up @@ -62,5 +56,3 @@ TEST_F(RescalerUtilsTest, Test) {
result = RescalerUtils::oneByXToLinear(result, 1000, 0, 100);
EXPECT_TRUE(fabs(result - 50) < 0.0000000001);
}

} // namespace
18 changes: 13 additions & 5 deletions src/track/keyutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -515,15 +515,15 @@ QList<mixxx::track::io::key::ChromaticKey> KeyUtils::getCompatibleKeys(
return compatible;
}

int openKeyNumber = KeyUtils::keyToOpenKeyNumber(key);
// We know the key is in the set of valid values. Save whether or not the
// value is minor.
bool major = keyIsMajor(key);
int openKeyNumber = KeyUtils::keyToOpenKeyNumber(key);

// The compatible keys of particular key are:
// * The relative major/minor key.
// * The perfect 4th (sub-dominant) key.
// * The perfect 5th (dominant) key.
// * The perfect 4th (sub-dominant) major/minor key.
// * The perfect 5th (dominant) major/minor key.
//
// The Circle of Fifths is a handy tool that encodes this compatibility.
// Keys on the same radial of the circle are compatible and adjacent keys on
Expand All @@ -535,14 +535,22 @@ QList<mixxx::track::io::key::ChromaticKey> KeyUtils::getCompatibleKeys(
// The key is compatible with tracks in the same key.
compatible << key;

auto relativeKey = openKeyNumberToKey(openKeyNumber, !major);
int relativeOpenKeyNumber = KeyUtils::keyToOpenKeyNumber(relativeKey);

// The relative major/minor key is compatible.
compatible << openKeyNumberToKey(openKeyNumber, !major);
compatible << relativeKey;

// The perfect 4th and perfect 5th are compatible.
// The perfect 4th and perfect 5th of BOTH major and minor key are compatible
// (as explained by Phil Morse: https://youtu.be/9eECvYYAwbg?t=2370)
compatible << openKeyNumberToKey(
openKeyNumber == 12 ? 1 : openKeyNumber + 1, major);
compatible << openKeyNumberToKey(
relativeOpenKeyNumber == 12 ? 1 : relativeOpenKeyNumber + 1, !major);
compatible << openKeyNumberToKey(
openKeyNumber == 1 ? 12 : openKeyNumber - 1, major);
compatible << openKeyNumberToKey(
relativeOpenKeyNumber == 1 ? 12 : relativeOpenKeyNumber - 1, !major);
return compatible;
}

Expand Down

0 comments on commit 6f2ad03

Please sign in to comment.