diff --git a/data/corpus.xml b/data/corpus.xml
index 26fe6372..eda4bafe 100644
--- a/data/corpus.xml
+++ b/data/corpus.xml
@@ -2486,7 +2486,7 @@
synthetic/work-title.3.0.xml
-
+
custom/musescore-slur-start-stop.musicxml
custom/segno_coda_roundtrip.3.0.xml
@@ -2502,8 +2502,10 @@
foundsuite/Deutscher Tanz D.820.1.xml
-
+
synthetic/cancel.location.3.0.xml
+ synthetic/coda.3.0.xml
+ synthetic/coda.3.1.xml
synthetic/figure-number.3.0.xml
synthetic/figured-bass.3.0.xml
synthetic/figured-bass.3.1.xml
@@ -2511,10 +2513,12 @@
synthetic/key-accidental.3.0.xml
synthetic/key-accidental.smufl.3.1.xml
synthetic/prefix.3.0.xml
+ synthetic/segno.3.0.xml
+ synthetic/segno.3.1.xml
synthetic/suffix.3.0.xml
-
+
custom/musescore-slur-start-stop.musicxml
custom/segno_coda_roundtrip.3.0.xml
@@ -2530,13 +2534,15 @@
foundsuite/Deutscher Tanz D.820.1.xml
-
+
synthetic/beat-repeat.3.0.xml
synthetic/beat-type.3.0.xml
synthetic/beats.3.0.xml
synthetic/cancel.location.3.0.xml
synthetic/clef.3.0.xml
synthetic/clef.3.1.xml
+ synthetic/coda.3.0.xml
+ synthetic/coda.3.1.xml
synthetic/directive.3.0.xml
synthetic/double.3.0.xml
synthetic/double.4.0.xml
@@ -2556,6 +2562,8 @@
synthetic/part-clef.4.0.xml
synthetic/part-symbol.3.0.xml
synthetic/part-transpose.4.0.xml
+ synthetic/segno.3.0.xml
+ synthetic/segno.3.1.xml
synthetic/senza-misura.3.0.xml
synthetic/slash-dot.3.0.xml
synthetic/slash-type.3.0.xml
@@ -2569,7 +2577,7 @@
synthetic/transpose.3.1.xml
-
+
custom/musescore-slur-start-stop.musicxml
custom/segno_coda_roundtrip.3.0.xml
@@ -2585,13 +2593,17 @@
foundsuite/Deutscher Tanz D.820.1.xml
-
+
synthetic/cancel.location.3.0.xml
+ synthetic/coda.3.0.xml
+ synthetic/coda.3.1.xml
synthetic/key-accidental.3.0.xml
synthetic/key-accidental.smufl.3.1.xml
+ synthetic/segno.3.0.xml
+ synthetic/segno.3.1.xml
-
+
@@ -2630,7 +2642,7 @@
foundsuite/Deutscher Tanz D.820.1.xml
-
+
synthetic/accent.3.0.xml
synthetic/accidental-mark.3.0.xml
synthetic/accidental-mark.3.1.xml
@@ -2657,6 +2669,8 @@
synthetic/caesura.3.0.xml
synthetic/cancel.location.3.0.xml
synthetic/circular-arrow.3.0.xml
+ synthetic/coda.3.0.xml
+ synthetic/coda.3.1.xml
synthetic/concert-score.4.0.xml
synthetic/creator.3.0.xml
synthetic/credit-image.3.0.xml
@@ -2795,6 +2809,8 @@
synthetic/schleifer.3.0.xml
synthetic/scoop.3.0.xml
synthetic/scoop.3.1.xml
+ synthetic/segno.3.0.xml
+ synthetic/segno.3.1.xml
synthetic/semi-pitched.3.0.xml
synthetic/sfzp.3.1.xml
synthetic/shake.3.0.xml
@@ -2851,7 +2867,7 @@
synthetic/work-title.3.0.xml
-
+
@@ -2870,10 +2886,14 @@
foundsuite/Deutscher Tanz D.820.1.xml
-
+
synthetic/cancel.location.3.0.xml
+ synthetic/coda.3.0.xml
+ synthetic/coda.3.1.xml
synthetic/key-accidental.3.0.xml
synthetic/key-accidental.smufl.3.1.xml
+ synthetic/segno.3.0.xml
+ synthetic/segno.3.1.xml
@@ -3067,7 +3087,7 @@
synthetic/time.3.1.xml
-
+
custom/musescore-slur-start-stop.musicxml
custom/segno_coda_roundtrip.3.0.xml
@@ -3083,7 +3103,7 @@
foundsuite/Deutscher Tanz D.820.1.xml
-
+
synthetic/accent.3.0.xml
synthetic/accidental-mark.3.0.xml
synthetic/accidental-mark.3.1.xml
@@ -3110,6 +3130,8 @@
synthetic/caesura.3.0.xml
synthetic/cancel.location.3.0.xml
synthetic/circular-arrow.3.0.xml
+ synthetic/coda.3.0.xml
+ synthetic/coda.3.1.xml
synthetic/concert-score.4.0.xml
synthetic/creator.3.0.xml
synthetic/credit-image.3.0.xml
@@ -3248,6 +3270,8 @@
synthetic/schleifer.3.0.xml
synthetic/scoop.3.0.xml
synthetic/scoop.3.1.xml
+ synthetic/segno.3.0.xml
+ synthetic/segno.3.1.xml
synthetic/semi-pitched.3.0.xml
synthetic/sfzp.3.1.xml
synthetic/shake.3.0.xml
@@ -3304,7 +3328,7 @@
synthetic/work-title.3.0.xml
-
+
custom/musescore-slur-start-stop.musicxml
custom/segno_coda_roundtrip.3.0.xml
@@ -3320,7 +3344,7 @@
foundsuite/Deutscher Tanz D.820.1.xml
-
+
synthetic/accent.3.0.xml
synthetic/accidental-mark.3.0.xml
synthetic/accidental-mark.3.1.xml
@@ -3347,6 +3371,8 @@
synthetic/caesura.3.0.xml
synthetic/cancel.location.3.0.xml
synthetic/circular-arrow.3.0.xml
+ synthetic/coda.3.0.xml
+ synthetic/coda.3.1.xml
synthetic/concert-score.4.0.xml
synthetic/creator.3.0.xml
synthetic/credit-image.3.0.xml
@@ -3485,6 +3511,8 @@
synthetic/schleifer.3.0.xml
synthetic/scoop.3.0.xml
synthetic/scoop.3.1.xml
+ synthetic/segno.3.0.xml
+ synthetic/segno.3.1.xml
synthetic/semi-pitched.3.0.xml
synthetic/sfzp.3.1.xml
synthetic/shake.3.0.xml
@@ -3541,7 +3569,7 @@
synthetic/work-title.3.0.xml
-
+
custom/musescore-slur-start-stop.musicxml
custom/segno_coda_roundtrip.3.0.xml
@@ -3557,7 +3585,7 @@
foundsuite/Deutscher Tanz D.820.1.xml
-
+
synthetic/accent.3.0.xml
synthetic/accidental-mark.3.0.xml
synthetic/accidental-mark.3.1.xml
@@ -3584,6 +3612,8 @@
synthetic/caesura.3.0.xml
synthetic/cancel.location.3.0.xml
synthetic/circular-arrow.3.0.xml
+ synthetic/coda.3.0.xml
+ synthetic/coda.3.1.xml
synthetic/concert-score.4.0.xml
synthetic/creator.3.0.xml
synthetic/credit-image.3.0.xml
@@ -3722,6 +3752,8 @@
synthetic/schleifer.3.0.xml
synthetic/scoop.3.0.xml
synthetic/scoop.3.1.xml
+ synthetic/segno.3.0.xml
+ synthetic/segno.3.1.xml
synthetic/semi-pitched.3.0.xml
synthetic/sfzp.3.1.xml
synthetic/shake.3.0.xml
@@ -12572,7 +12604,7 @@
synthetic/flip.3.1.xml
-
+
@@ -12599,7 +12631,7 @@
-
+
synthetic/accent.3.0.xml
synthetic/accidental-mark.3.0.xml
synthetic/accidental-mark.3.1.xml
@@ -12644,8 +12676,6 @@
synthetic/circular-arrow.3.0.xml
synthetic/clef.3.0.xml
synthetic/clef.3.1.xml
- synthetic/coda.3.0.xml
- synthetic/coda.3.1.xml
synthetic/concert-score.4.0.xml
synthetic/creator.3.0.xml
synthetic/credit-image.3.0.xml
@@ -12894,8 +12924,6 @@
synthetic/scoop.3.1.xml
synthetic/scordatura.3.1.xml
synthetic/second.4.0.xml
- synthetic/segno.3.0.xml
- synthetic/segno.3.1.xml
synthetic/semi-pitched.3.0.xml
synthetic/senza-misura.3.0.xml
synthetic/sfzp.3.1.xml
@@ -13264,7 +13292,7 @@
synthetic/laughing.3.0.xml
-
+
@@ -13274,7 +13302,7 @@
-
+
synthetic/accent.3.0.xml
synthetic/accidental-mark.3.0.xml
synthetic/accidental-mark.3.1.xml
@@ -13319,8 +13347,6 @@
synthetic/circular-arrow.3.0.xml
synthetic/clef.3.0.xml
synthetic/clef.3.1.xml
- synthetic/coda.3.0.xml
- synthetic/coda.3.1.xml
synthetic/concert-score.4.0.xml
synthetic/creator.3.0.xml
synthetic/credit-image.3.0.xml
@@ -13569,8 +13595,6 @@
synthetic/scoop.3.1.xml
synthetic/scordatura.3.1.xml
synthetic/second.4.0.xml
- synthetic/segno.3.0.xml
- synthetic/segno.3.1.xml
synthetic/semi-pitched.3.0.xml
synthetic/senza-misura.3.0.xml
synthetic/sfzp.3.1.xml
diff --git a/data/synthetic/coda.3.0.features.xml b/data/synthetic/coda.3.0.features.xml
index e76ad0f4..952f5797 100644
--- a/data/synthetic/coda.3.0.features.xml
+++ b/data/synthetic/coda.3.0.features.xml
@@ -5,6 +5,9 @@
synthetic/coda.3.0.xml
3.0
+
+ attributes
+
coda
@@ -28,10 +31,10 @@
direction-type
- footnote
+ divisions
- level
+ duration
measure
@@ -39,6 +42,12 @@
number
+
+ note
+
+
+ octave
+
part
@@ -57,6 +66,9 @@
part-name
+
+ pitch
+
score-part
@@ -72,6 +84,12 @@
staff
+
+ step
+
+
+ type
+
voice
diff --git a/data/synthetic/coda.3.0.xml b/data/synthetic/coda.3.0.xml
index ed43bd69..271a58c3 100644
--- a/data/synthetic/coda.3.0.xml
+++ b/data/synthetic/coda.3.0.xml
@@ -1,29 +1,33 @@
-
- x
- x
-
+
x
-
- x
- x
-
+
+
+ 1
+
- x
- x
1
1
+
+
+ C
+ 4
+
+ 1
+ 1
+ quarter
+
diff --git a/data/synthetic/coda.3.1.features.xml b/data/synthetic/coda.3.1.features.xml
index 737b847a..560b346c 100644
--- a/data/synthetic/coda.3.1.features.xml
+++ b/data/synthetic/coda.3.1.features.xml
@@ -5,6 +5,9 @@
synthetic/coda.3.1.xml
3.1
+
+ attributes
+
coda
@@ -30,10 +33,10 @@
direction-type
- footnote
+ divisions
- level
+ duration
measure
@@ -41,6 +44,12 @@
number
+
+ note
+
+
+ octave
+
part
@@ -59,6 +68,9 @@
part-name
+
+ pitch
+
score-part
@@ -74,6 +86,12 @@
staff
+
+ step
+
+
+ type
+
voice
diff --git a/data/synthetic/coda.3.1.xml b/data/synthetic/coda.3.1.xml
index 42a935af..2069f264 100644
--- a/data/synthetic/coda.3.1.xml
+++ b/data/synthetic/coda.3.1.xml
@@ -1,29 +1,33 @@
-
- x
- x
-
+
x
-
- x
- x
-
+
+
+ 1
+
- x
- x
1
1
+
+
+ C
+ 4
+
+ 1
+ 1
+ quarter
+
diff --git a/data/synthetic/segno.3.0.features.xml b/data/synthetic/segno.3.0.features.xml
index 4af018bf..f96d1443 100644
--- a/data/synthetic/segno.3.0.features.xml
+++ b/data/synthetic/segno.3.0.features.xml
@@ -5,6 +5,9 @@
synthetic/segno.3.0.xml
3.0
+
+ attributes
+
direction
@@ -12,10 +15,10 @@
direction-type
- footnote
+ divisions
- level
+ duration
measure
@@ -23,6 +26,12 @@
number
+
+ note
+
+
+ octave
+
part
@@ -41,6 +50,9 @@
part-name
+
+ pitch
+
score-part
@@ -72,6 +84,12 @@
staff
+
+ step
+
+
+ type
+
voice
diff --git a/data/synthetic/segno.3.0.xml b/data/synthetic/segno.3.0.xml
index 32036efd..28ac8219 100644
--- a/data/synthetic/segno.3.0.xml
+++ b/data/synthetic/segno.3.0.xml
@@ -1,29 +1,33 @@
-
- x
- x
-
+
x
-
- x
- x
-
+
+
+ 1
+
- x
- x
1
1
+
+
+ C
+ 4
+
+ 1
+ 1
+ quarter
+
diff --git a/data/synthetic/segno.3.1.features.xml b/data/synthetic/segno.3.1.features.xml
index e753345f..f1caa09f 100644
--- a/data/synthetic/segno.3.1.features.xml
+++ b/data/synthetic/segno.3.1.features.xml
@@ -5,6 +5,9 @@
synthetic/segno.3.1.xml
3.1
+
+ attributes
+
direction
@@ -12,10 +15,10 @@
direction-type
- footnote
+ divisions
- level
+ duration
measure
@@ -23,6 +26,12 @@
number
+
+ note
+
+
+ octave
+
part
@@ -41,6 +50,9 @@
part-name
+
+ pitch
+
score-part
@@ -74,6 +86,12 @@
staff
+
+ step
+
+
+ type
+
voice
diff --git a/data/synthetic/segno.3.1.xml b/data/synthetic/segno.3.1.xml
index 33b3e5b6..b367649e 100644
--- a/data/synthetic/segno.3.1.xml
+++ b/data/synthetic/segno.3.1.xml
@@ -1,29 +1,33 @@
-
- x
- x
-
+
x
-
- x
- x
-
+
+
+ 1
+
- x
- x
1
1
+
+
+ C
+ 4
+
+ 1
+ 1
+ quarter
+
diff --git a/src/private/mx/impl/DirectionReader.cpp b/src/private/mx/impl/DirectionReader.cpp
index 4241b4ef..ebf04df2 100644
--- a/src/private/mx/impl/DirectionReader.cpp
+++ b/src/private/mx/impl/DirectionReader.cpp
@@ -68,6 +68,7 @@
#include "mx/impl/SoundFunctions.h"
#include "mx/impl/SpannerFunctions.h"
#include "mx/utility/Round.h"
+#include "mx/utility/StringToInt.h"
#include "mx/utility/Unused.h"
namespace mx
@@ -171,6 +172,17 @@ void DirectionReader::parseValues()
myOutDirectionData.soundData = std::move(soundData);
}
}
+
+ // The 's editorial-voice assigns the direction to a voice. A value of
+ // -1 on DirectionData::voice means none was present.
+ if (myDirection->editorialVoiceDirection().voice().has_value())
+ {
+ int parsedVoice = -1;
+ if (utility::stringToInt(myDirection->editorialVoiceDirection().voice()->c_str(), parsedVoice))
+ {
+ myOutDirectionData.voice = parsedVoice;
+ }
+ }
}
else if (myHarmony)
{
diff --git a/src/private/mx/impl/DirectionWriter.cpp b/src/private/mx/impl/DirectionWriter.cpp
index 3b86c1a3..c7d56fa6 100644
--- a/src/private/mx/impl/DirectionWriter.cpp
+++ b/src/private/mx/impl/DirectionWriter.cpp
@@ -21,6 +21,7 @@
#include "mx/core/generated/DirectionTypeChoiceChoice.h"
#include "mx/core/generated/Divisions.h"
#include "mx/core/generated/Dynamics.h"
+#include "mx/core/generated/EditorialVoiceDirectionGroup.h"
#include "mx/core/generated/Empty.h"
#include "mx/core/generated/Figure.h"
#include "mx/core/generated/FiguredBass.h"
@@ -112,6 +113,17 @@ std::vector DirectionWriter::getDirectionLikeThings()
direction.setOffset(coreOffset);
}
+ // Assign the direction to a voice via the editorial-voice . Only emitted when this
+ // direction also writes direction-type content (guarded by myIsFirstDirectionTypeAdded below),
+ // so a voice carried in from a figured-bass or harmony element never produces an empty
+ // .
+ if (myDirectionData.voice >= 0)
+ {
+ core::EditorialVoiceDirectionGroup editorialVoice{};
+ editorialVoice.setVoice(std::to_string(myDirectionData.voice));
+ direction.setEditorialVoiceDirection(std::move(editorialVoice));
+ }
+
for (auto mark : myDirectionData.marks)
{
mark.tickTimePosition = myDirectionData.tickTimePosition;
diff --git a/src/private/mxtest/api/roundtrip-baseline.txt b/src/private/mxtest/api/roundtrip-baseline.txt
index 79f2ad25..87c9511f 100644
--- a/src/private/mxtest/api/roundtrip-baseline.txt
+++ b/src/private/mxtest/api/roundtrip-baseline.txt
@@ -65,3 +65,11 @@ lysuite/ly72b_TransposingInstruments_Full.xml
# round-trips losslessly.
custom/segno_coda_roundtrip.3.0.xml
custom/segno_coda_roundtrip.3.1.xml
+
+# The audit's synthetic single-feature segno/coda fixtures. Each is a minimal score
+# with one part-group, a direction carrying the segno/coda plus a and ,
+# and a single note; all round-trip losslessly.
+synthetic/segno.3.0.xml
+synthetic/segno.3.1.xml
+synthetic/coda.3.0.xml
+synthetic/coda.3.1.xml