Skip to content

Commit f8f4c7c

Browse files
iveshenry18Jojo-Schmitz
authored andcommitted
ENG-40: Infer direction text to dynamics
A common XML exporter error is to mistake dynamics for direction text. This commit adds two functions for correcting these mistakes. 1. In the case that a whole direction is dynamic, this converts that whole direction to the specified dynamic, including handling the velocity change). 2. In the case that a direction contains a dynamic in addition to other text (i.e. mf cresc.), this converts the dynamic portion to the proper MuseScore dynamic symbol (with no velocity change). In pursuit of this, the dynList of Dyn structs is moved from dynamic.cpp to dynamic.h, so it can be used as the list of symbols to match. Duplicate of musescore#8347, plus fixing a compiler warning (which shows some 120 times), duplicate of musescore#8478
1 parent 3973427 commit f8f4c7c

File tree

8 files changed

+1673
-52
lines changed

8 files changed

+1673
-52
lines changed

importexport/musicxml/importmxmlpass2.cpp

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2601,6 +2601,9 @@ void MusicXMLParserDirection::direction(const QString& partId,
26012601
MusicXMLInferredFingering* inferredFingering = new MusicXMLInferredFingering(totalY(), t, _wordsText, track, placement(), measure, tick + _offset);
26022602
inferredFingerings.push_back(inferredFingering);
26032603
}
2604+
else if (directionToDynamic()) {
2605+
delete t;
2606+
}
26042607
else {
26052608
// Add element to score later, after collecting all the others and sorting by default-y
26062609
// This allows default-y to be at least respected by the order of elements
@@ -2737,7 +2740,9 @@ void MusicXMLParserDirection::directionType(QList<MusicXmlSpannerDesc>& starts,
27372740
_metroText = metronome(_tpoMetro);
27382741
else if (_e.name() == "words") {
27392742
_enclosure = _e.attributes().value("enclosure").toString();
2740-
_wordsText += nextPartOfFormattedString(_e);
2743+
QString nextPart = nextPartOfFormattedString(_e);
2744+
textToDynamic(nextPart);
2745+
_wordsText += nextPart;
27412746
}
27422747
else if (_e.name() == "rehearsal") {
27432748
_enclosure = _e.attributes().value("enclosure").toString();
@@ -2923,6 +2928,44 @@ static Marker* findMarker(const QString& repeat, Score* score)
29232928
return m;
29242929
}
29252930

2931+
//---------------------------------------------------------
2932+
// textToDynamic
2933+
//---------------------------------------------------------
2934+
/**
2935+
Attempts to convert text to dynamic text. No-op if unable.
2936+
*/
2937+
void MusicXMLParserDirection::textToDynamic(QString& text) const
2938+
{
2939+
QString simplifiedText = text.simplified();
2940+
for (auto dyn : dynList) {
2941+
if (dyn.tag == simplifiedText) {
2942+
text = text.replace(simplifiedText, dyn.text);
2943+
}
2944+
}
2945+
}
2946+
2947+
//---------------------------------------------------------
2948+
// directionToDynamic
2949+
//---------------------------------------------------------
2950+
/**
2951+
Attempts to convert direction to dynamic. True if successful,
2952+
else false.
2953+
*/
2954+
bool MusicXMLParserDirection::directionToDynamic()
2955+
{
2956+
if (!_metroText.isEmpty() || !_rehearsalText.isEmpty() || !_enclosure.isEmpty())
2957+
return false;
2958+
QString simplifiedText = _wordsText.simplified();
2959+
for (auto dyn : dynList) {
2960+
if (dyn.tag == simplifiedText || dyn.text == simplifiedText) {
2961+
_dynaVelocity = QString::number(round(dyn.velocity / 0.9));
2962+
_dynamicsList.push_back(simplifiedText);
2963+
return true;
2964+
}
2965+
}
2966+
return false;
2967+
}
2968+
29262969
//---------------------------------------------------------
29272970
// isLikelyFingering
29282971
//---------------------------------------------------------

importexport/musicxml/importmxmlpass2.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,8 @@ class MusicXMLParserDirection {
400400
QString matchRepeat() const;
401401
bool isLikelyFingering() const;
402402
bool isLikelyCredit(const Fraction& tick) const;
403+
void textToDynamic(QString& text) const;
404+
bool directionToDynamic();
403405
void skipLogCurrElem();
404406
};
405407

libmscore/dynamic.cpp

Lines changed: 0 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -27,57 +27,6 @@
2727

2828
namespace Ms {
2929

30-
//-----------------------------------------------------------------------------
31-
// Dyn
32-
// see: http://en.wikipedia.org/wiki/File:Dynamic's_Note_Velocity.svg
33-
//-----------------------------------------------------------------------------
34-
35-
struct Dyn {
36-
int velocity; ///< associated midi velocity (0-127, -1 = none)
37-
bool accent; ///< if true add velocity to current chord velocity
38-
const char* tag; // name of dynamics, eg. "fff"
39-
const char* text; // utf8 text of dynamic
40-
int changeInVelocity;
41-
};
42-
43-
// variant with ligatures, works for both emmentaler and bravura:
44-
45-
static Dyn dynList[] = {
46-
// dynamic:
47-
{ -1, true, "other-dynamics", "", 0 },
48-
{ 1, false, "pppppp", "<sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym>", 0 },
49-
{ 5, false, "ppppp", "<sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym>", 0 },
50-
{ 10, false, "pppp", "<sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym>", 0 },
51-
{ 16, false, "ppp", "<sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym>", 0 },
52-
{ 33, false, "pp", "<sym>dynamicPiano</sym><sym>dynamicPiano</sym>", 0 },
53-
{ 49, false, "p", "<sym>dynamicPiano</sym>", 0 },
54-
{ 64, false, "mp", "<sym>dynamicMezzo</sym><sym>dynamicPiano</sym>", 0 },
55-
{ 80, false, "mf", "<sym>dynamicMezzo</sym><sym>dynamicForte</sym>", 0 },
56-
{ 96, false, "f", "<sym>dynamicForte</sym>", 0 },
57-
{ 112, false, "ff", "<sym>dynamicForte</sym><sym>dynamicForte</sym>", 0 },
58-
{ 126, false, "fff", "<sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym>", 0 },
59-
{ 127, false, "ffff", "<sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym>", 0 },
60-
{ 127, false, "fffff", "<sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym>", 0 },
61-
{ 127, false, "ffffff", "<sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym>", 0 },
62-
63-
// accents:
64-
{ 96, true, "fp", "<sym>dynamicForte</sym><sym>dynamicPiano</sym>", -47 },
65-
{ 49, true, "pf", "<sym>dynamicPiano</sym><sym>dynamicForte</sym>", 47 },
66-
{ 112, true, "sf", "<sym>dynamicSforzando</sym><sym>dynamicForte</sym>", -18 },
67-
{ 112, true, "sfz", "<sym>dynamicSforzando</sym><sym>dynamicForte</sym><sym>dynamicZ</sym>", -18 },
68-
{ 126, true, "sff", "<sym>dynamicSforzando</sym><sym>dynamicForte</sym><sym>dynamicForte</sym>", -18 },
69-
{ 126, true, "sffz", "<sym>dynamicSforzando</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicZ</sym>", -18 },
70-
{ 112, true, "sfp", "<sym>dynamicSforzando</sym><sym>dynamicForte</sym><sym>dynamicPiano</sym>", -47 },
71-
{ 112, true, "sfpp", "<sym>dynamicSforzando</sym><sym>dynamicForte</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym>", -79 },
72-
{ 112, true, "rfz", "<sym>dynamicRinforzando</sym><sym>dynamicForte</sym><sym>dynamicZ</sym>", -18 },
73-
{ 112, true, "rf", "<sym>dynamicRinforzando</sym><sym>dynamicForte</sym>", -18 },
74-
{ 112, true, "fz", "<sym>dynamicForte</sym><sym>dynamicZ</sym>", -18 },
75-
{ 96, true, "m", "<sym>dynamicMezzo</sym>", -16 },
76-
{ 112, true, "r", "<sym>dynamicRinforzando</sym>", -18 },
77-
{ 112, true, "s", "<sym>dynamicSforzando</sym>", -18 },
78-
{ 80, true, "z", "<sym>dynamicZ</sym>", 0 },
79-
{ 49, true, "n", "<sym>dynamicNiente</sym>", -48 }
80-
};
8130

8231
//---------------------------------------------------------
8332
// dynamicsStyle

libmscore/dynamic.h

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,59 @@ namespace Ms {
2121
class Measure;
2222
class Segment;
2323

24+
//-----------------------------------------------------------------------------
25+
// Dyn
26+
// see: http://en.wikipedia.org/wiki/File:Dynamic's_Note_Velocity.svg
27+
//-----------------------------------------------------------------------------
28+
29+
struct Dyn {
30+
int velocity; ///< associated midi velocity (0-127, -1 = none)
31+
bool accent; ///< if true add velocity to current chord velocity
32+
const char* tag; // name of dynamics, eg. "fff"
33+
const char* text; // utf8 text of dynamic
34+
int changeInVelocity;
35+
};
36+
37+
// variant with ligatures, works for both emmentaler and bravura:
38+
39+
static const Dyn dynList[] = {
40+
// dynamic:
41+
{ -1, true, "other-dynamics", "", 0 },
42+
{ 1, false, "pppppp", "<sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym>", 0 },
43+
{ 5, false, "ppppp", "<sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym>", 0 },
44+
{ 10, false, "pppp", "<sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym>", 0 },
45+
{ 16, false, "ppp", "<sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym>", 0 },
46+
{ 33, false, "pp", "<sym>dynamicPiano</sym><sym>dynamicPiano</sym>", 0 },
47+
{ 49, false, "p", "<sym>dynamicPiano</sym>", 0 },
48+
{ 64, false, "mp", "<sym>dynamicMezzo</sym><sym>dynamicPiano</sym>", 0 },
49+
{ 80, false, "mf", "<sym>dynamicMezzo</sym><sym>dynamicForte</sym>", 0 },
50+
{ 96, false, "f", "<sym>dynamicForte</sym>", 0 },
51+
{ 112, false, "ff", "<sym>dynamicForte</sym><sym>dynamicForte</sym>", 0 },
52+
{ 126, false, "fff", "<sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym>", 0 },
53+
{ 127, false, "ffff", "<sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym>", 0 },
54+
{ 127, false, "fffff", "<sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym>", 0 },
55+
{ 127, false, "ffffff", "<sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym>", 0 },
56+
57+
// accents:
58+
{ 96, true, "fp", "<sym>dynamicForte</sym><sym>dynamicPiano</sym>", -47 },
59+
{ 49, true, "pf", "<sym>dynamicPiano</sym><sym>dynamicForte</sym>", 47 },
60+
{ 112, true, "sf", "<sym>dynamicSforzando</sym><sym>dynamicForte</sym>", -18 },
61+
{ 112, true, "sfz", "<sym>dynamicSforzando</sym><sym>dynamicForte</sym><sym>dynamicZ</sym>", -18 },
62+
{ 126, true, "sff", "<sym>dynamicSforzando</sym><sym>dynamicForte</sym><sym>dynamicForte</sym>", -18 },
63+
{ 126, true, "sffz", "<sym>dynamicSforzando</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicZ</sym>", -18 },
64+
{ 112, true, "sfp", "<sym>dynamicSforzando</sym><sym>dynamicForte</sym><sym>dynamicPiano</sym>", -47 },
65+
{ 112, true, "sfpp", "<sym>dynamicSforzando</sym><sym>dynamicForte</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym>", -79 },
66+
{ 112, true, "rfz", "<sym>dynamicRinforzando</sym><sym>dynamicForte</sym><sym>dynamicZ</sym>", -18 },
67+
{ 112, true, "rf", "<sym>dynamicRinforzando</sym><sym>dynamicForte</sym>", -18 },
68+
{ 112, true, "fz", "<sym>dynamicForte</sym><sym>dynamicZ</sym>", -18 },
69+
{ 96, true, "m", "<sym>dynamicMezzo</sym>", -16 },
70+
{ 112, true, "r", "<sym>dynamicRinforzando</sym>", -18 },
71+
{ 112, true, "s", "<sym>dynamicSforzando</sym>", -18 },
72+
{ 80, true, "z", "<sym>dynamicZ</sym>", 0 },
73+
{ 49, true, "n", "<sym>dynamicNiente</sym>", -48 }
74+
};
75+
76+
2477
//-----------------------------------------------------------------------------
2578
// @@ Dynamic
2679
/// dynamics marker; determines midi velocity
35.5 KB
Binary file not shown.

0 commit comments

Comments
 (0)