Skip to content

Commit c8fe38b

Browse files
committed
Select most appropriate enharmonic from available chords
1 parent 6dda2aa commit c8fe38b

File tree

4 files changed

+64
-8
lines changed

4 files changed

+64
-8
lines changed

src/engraving/dom/pitchspelling.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1168,4 +1168,35 @@ Key clampKey(Key key, PreferSharpFlat prefer)
11681168

11691169
return key;
11701170
}
1171+
1172+
int bestEnharmonicFit(const std::vector<int> tpcs, Key key)
1173+
{
1174+
int keyIndex = int(key) - int(Key::MIN);
1175+
if (keyIndex < 0 || keyIndex >= int(Key::NUM_OF)) {
1176+
return tpcs.front();
1177+
}
1178+
1179+
int bestPenalty = INT_MAX;
1180+
int closestTpc = Tpc::TPC_INVALID;
1181+
1182+
for (int tpc : tpcs) {
1183+
if (tpc == Tpc::TPC_INVALID) {
1184+
continue;
1185+
}
1186+
1187+
int lof = tpc - Tpc::TPC_MIN;
1188+
if (lof < 0 || lof >= 34) {
1189+
continue;
1190+
}
1191+
1192+
int penalty = enharmonicSpelling[keyIndex][lof];
1193+
1194+
if (penalty < bestPenalty) {
1195+
bestPenalty = penalty;
1196+
closestTpc = tpc;
1197+
}
1198+
}
1199+
1200+
return closestTpc;
1201+
}
11711202
}

src/engraving/dom/pitchspelling.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ extern int convertNote(const String& s, NoteSpellingType noteSpelling, NoteCaseT
104104
extern int clampEnharmonic(int tpc, bool useDoubleSharpsFlats = true);
105105
extern int clampPitch(int pitch, bool octaved = false);
106106
extern Key clampKey(Key key, PreferSharpFlat prefer = PreferSharpFlat::NONE);
107+
extern int bestEnharmonicFit(const std::vector<int> tpcs, Key key);
107108

108109
//---------------------------------------------------------
109110
// tpc2alter

src/engraving/editing/transpose.cpp

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,14 @@ void Transpose::transposeFretDiagram(FretDiagram* diagram, Score* score, Interva
599599
return;
600600
}
601601

602-
String name = names.front();
602+
Fraction tick = Fraction(0, 1);
603+
Segment* seg = diagram->segment();
604+
if (seg) {
605+
tick = seg->tick();
606+
}
607+
Key key = !diagram->staff() ? Key::C : diagram->staff()->key(tick);
608+
609+
String name = findBestEnharmonicFit(names, key, score->style());
603610

604611
diagram->setHarmony(name);
605612
harmony = diagram->harmony();
@@ -608,17 +615,10 @@ void Transpose::transposeFretDiagram(FretDiagram* diagram, Score* score, Interva
608615
}
609616

610617
// Transpose harmony without undo
611-
Fraction tick = Fraction(0, 1);
612-
Segment* seg = harmony->getParentSeg();
613-
if (seg) {
614-
tick = seg->tick();
615-
}
616-
617618
Interval kv = harmony->staff()->transpose(harmony->tick());
618619
Interval iv = harmony->part()->instrument(harmony->tick())->transpose();
619620
Interval hInterval((interval.diatonic - kv.diatonic + iv.diatonic), (interval.chromatic - kv.chromatic + iv.chromatic));
620621

621-
Key key = !harmony->staff() ? Key::C : harmony->staff()->key(tick);
622622
for (HarmonyInfo* info : harmony->chords()) {
623623
if (mode == TransposeMode::DIATONICALLY) {
624624
info->setRootTpc(Transpose::transposeTpcDiatonicByKey(info->rootTpc(), transposeInterval, key, trKeys, useDoubleSharpsFlats));
@@ -646,6 +646,28 @@ void Transpose::transposeFretDiagram(FretDiagram* diagram, Score* score, Interva
646646
return;
647647
}
648648

649+
String Transpose::findBestEnharmonicFit(const std::vector<String>& notes, Key key, const MStyle& style)
650+
{
651+
std::vector<int> tpcs;
652+
NoteSpellingType harmonySpelling = style.styleV(Sid::chordSymbolSpelling).value<NoteSpellingType>();
653+
NoteCaseType harmonyCase = NoteCaseType::AUTO;
654+
size_t idx = 0;
655+
for (const String& note : notes) {
656+
int tpc = convertNote(note, harmonySpelling, harmonyCase, idx);
657+
tpcs.push_back(tpc);
658+
}
659+
660+
int tpc = bestEnharmonicFit(tpcs, key);
661+
662+
if (tpc == Tpc::TPC_INVALID) {
663+
return notes.front();
664+
}
665+
666+
String note = tpc2name(tpc, harmonySpelling, harmonyCase);
667+
668+
return note;
669+
}
670+
649671
//---------------------------------------------------------
650672
// transposeTpcDiatonicByKey
651673
//

src/engraving/editing/transpose.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ class Transpose
5757
bool useDoubleSharpsFlats);
5858
static void transposeFretDiagram(FretDiagram* diagram, Score* score, Interval interval, TransposeMode mode, int transposeInterval,
5959
bool trKeys, bool useDoubleSharpsFlats);
60+
61+
static String findBestEnharmonicFit(const std::vector<String>& notes, Key key, const MStyle& style);
6062
};
6163

6264
class TransposeHarmony : public UndoCommand

0 commit comments

Comments
 (0)