From 4dd00f44e5161f4d77b50d050c9935a2400a465c Mon Sep 17 00:00:00 2001 From: rettinghaus Date: Sat, 11 Jul 2026 17:08:09 +0200 Subject: [PATCH 1/8] add test --- .../musicxml/tests/data/testOctaveShift.xml | 785 ++++++++++++++++++ .../musicxml/tests/musicxml_tests.cpp | 3 + 2 files changed, 788 insertions(+) create mode 100644 src/importexport/musicxml/tests/data/testOctaveShift.xml diff --git a/src/importexport/musicxml/tests/data/testOctaveShift.xml b/src/importexport/musicxml/tests/data/testOctaveShift.xml new file mode 100644 index 0000000000000..005965c6f0668 --- /dev/null +++ b/src/importexport/musicxml/tests/data/testOctaveShift.xml @@ -0,0 +1,785 @@ + + + + + Alls octave-shifts + + + + MuseScore 0.7.0 + 2007-09-10 + + + + + + + + + + Piano + + Piano + keyboard.piano + + + + 1 + 1 + 78.7402 + 0 + + + + + + + 1 + + 0 + + + + G + 2 + + + + + C + 4 + + 1 + 1 + quarter + up + + + + D + 4 + + 1 + 1 + quarter + up + + + + E + 4 + + 1 + 1 + quarter + up + + + + F + 4 + + 1 + 1 + quarter + up + + + + + + G + 4 + + 1 + 1 + quarter + up + + + + F + 4 + + 1 + 1 + quarter + up + + + + E + 4 + + 1 + 1 + quarter + up + + + + D + 4 + + 1 + 1 + quarter + up + + + + + + + + + + + C + 5 + + 1 + 1 + quarter + up + + + + D + 5 + + 1 + 1 + quarter + up + + + + E + 5 + + 1 + 1 + quarter + up + + + + F + 5 + + 1 + 1 + quarter + up + + + + + + G + 5 + + 1 + 1 + quarter + up + + + + F + 5 + + 1 + 1 + quarter + up + + + + E + 5 + + 1 + 1 + quarter + up + + + + D + 5 + + 1 + 1 + quarter + up + + + + + + + + + + + + + + + + C + 3 + + 1 + 1 + quarter + up + + + + D + 3 + + 1 + 1 + quarter + up + + + + E + 3 + + 1 + 1 + quarter + up + + + + F + 3 + + 1 + 1 + quarter + up + + + + + + G + 3 + + 1 + 1 + quarter + up + + + + F + 3 + + 1 + 1 + quarter + up + + + + E + 3 + + 1 + 1 + quarter + up + + + + D + 3 + + 1 + 1 + quarter + up + + + + + + + + + + + + + + + + C + 6 + + 1 + 1 + quarter + up + + + + D + 6 + + 1 + 1 + quarter + up + + + + E + 6 + + 1 + 1 + quarter + up + + + + F + 6 + + 1 + 1 + quarter + up + + + + + + G + 6 + + 1 + 1 + quarter + up + + + + F + 6 + + 1 + 1 + quarter + up + + + + E + 6 + + 1 + 1 + quarter + up + + + + D + 6 + + 1 + 1 + quarter + up + + + + + + + + + + + + + + + + C + 2 + + 1 + 1 + quarter + up + + + + D + 2 + + 1 + 1 + quarter + up + + + + E + 2 + + 1 + 1 + quarter + up + + + + F + 2 + + 1 + 1 + quarter + up + + + + + + G + 2 + + 1 + 1 + quarter + up + + + + F + 2 + + 1 + 1 + quarter + up + + + + E + 2 + + 1 + 1 + quarter + up + + + + D + 2 + + 1 + 1 + quarter + up + + + + + + + + + + + + + + + + C + 4 + + 1 + 1 + quarter + up + + + + D + 4 + + 1 + 1 + quarter + up + + + + E + 4 + + 1 + 1 + quarter + up + + + + F + 4 + + 1 + 1 + quarter + up + + + + + + + + + + + + + + + + G + 4 + + 1 + 1 + quarter + up + + + + F + 4 + + 1 + 1 + quarter + up + + + + E + 4 + + 1 + 1 + quarter + up + + + + D + 4 + + 1 + 1 + quarter + up + + + + + + C + 4 + + 1 + 1 + quarter + up + + + + D + 4 + + 1 + 1 + quarter + up + + + + E + 4 + + 1 + 1 + quarter + up + + + + F + 4 + + 1 + 1 + quarter + up + + + + + + G + 4 + + 1 + 1 + quarter + up + + + + F + 4 + + 1 + 1 + quarter + up + + + + E + 4 + + 1 + 1 + quarter + up + + + + D + 4 + + 1 + 1 + quarter + up + + + + + + C + 4 + + 1 + 1 + quarter + up + + + + D + 4 + + 1 + 1 + quarter + up + + + + E + 4 + + 1 + 1 + quarter + up + + + + F + 4 + + 1 + 1 + quarter + up + + + + + + G + 4 + + 1 + 1 + quarter + up + + + + F + 4 + + 1 + 1 + quarter + up + + + + E + 4 + + 1 + 1 + quarter + up + + + + D + 4 + + 1 + 1 + quarter + up + + + + + + + + light-heavy + + + + diff --git a/src/importexport/musicxml/tests/musicxml_tests.cpp b/src/importexport/musicxml/tests/musicxml_tests.cpp index 380d4f7d85fb6..13536bc1b33a0 100644 --- a/src/importexport/musicxml/tests/musicxml_tests.cpp +++ b/src/importexport/musicxml/tests/musicxml_tests.cpp @@ -1087,6 +1087,9 @@ TEST_F(MusicXml_Tests, numberedLyrics) { TEST_F(MusicXml_Tests, numerals) { musicXmlIoTest("testNumerals"); } +TEST_F(MusicXml_Tests, octaveShift) { + musicXmlIoTest("testOctaveShift"); +} TEST_F(MusicXml_Tests, ornaments) { musicXmlIoTest("testOrnaments"); } From bf6f13fc2e7091cad615a90e68af4523aa6a3f91 Mon Sep 17 00:00:00 2001 From: rettinghaus Date: Sat, 11 Jul 2026 17:15:34 +0200 Subject: [PATCH 2/8] do not write placement for ocatve-shifts --- src/importexport/musicxml/internal/export/exportmusicxml.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/importexport/musicxml/internal/export/exportmusicxml.cpp b/src/importexport/musicxml/internal/export/exportmusicxml.cpp index 5997e3532549d..6a9e8903fb0d8 100644 --- a/src/importexport/musicxml/internal/export/exportmusicxml.cpp +++ b/src/importexport/musicxml/internal/export/exportmusicxml.cpp @@ -5677,7 +5677,7 @@ void ExportMusicXml::ottava(Ottava const* const ot, staff_idx_t staff, const Fra const Fraction tickToWrite = isStart ? ot->tick() : ot->tick2(); moveToTickIfNeed(tickToWrite, ot->track(), measureStart); - directionTag(m_xml, m_attr, ot); + directionTag(m_xml, m_attr, 0); m_xml.startElement("direction-type"); octaveShiftXml += color2xml(ot); octaveShiftXml += positioningAttributes(ot, ot->tick() == tick); From bc137181f61254597142a354bb268c655f01a914 Mon Sep 17 00:00:00 2001 From: rettinghaus Date: Sat, 11 Jul 2026 17:19:07 +0200 Subject: [PATCH 3/8] add export of 22MA and 22MB --- .../musicxml/internal/export/exportmusicxml.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/importexport/musicxml/internal/export/exportmusicxml.cpp b/src/importexport/musicxml/internal/export/exportmusicxml.cpp index 6a9e8903fb0d8..26f8f64256074 100644 --- a/src/importexport/musicxml/internal/export/exportmusicxml.cpp +++ b/src/importexport/musicxml/internal/export/exportmusicxml.cpp @@ -5648,6 +5648,10 @@ void ExportMusicXml::ottava(Ottava const* const ot, staff_idx_t staff, const Fra sz = u"15"; tp = u"down"; break; + case OttavaType::OTTAVA_22MA: + sz = u"22"; + tp = u"down"; + break; case OttavaType::OTTAVA_8VB: sz = u"8"; tp = u"up"; @@ -5656,6 +5660,10 @@ void ExportMusicXml::ottava(Ottava const* const ot, staff_idx_t staff, const Fra sz = u"15"; tp = u"up"; break; + case OttavaType::OTTAVA_22MB: + sz = u"22"; + tp = u"up"; + break; default: LOGD("ottava subtype %d not understood", int(st)); } From d76d707317870e71df37f4b772823a9a0b0a198d Mon Sep 17 00:00:00 2001 From: rettinghaus Date: Sat, 11 Jul 2026 17:24:32 +0200 Subject: [PATCH 4/8] fix import of ottava lines --- .../musicxml/internal/import/importmusicxmlpass1.cpp | 6 +++--- .../musicxml/internal/import/importmusicxmlpass2.cpp | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/importexport/musicxml/internal/import/importmusicxmlpass1.cpp b/src/importexport/musicxml/internal/import/importmusicxmlpass1.cpp index 784ac1f009345..2b75c3cb1ef3b 100644 --- a/src/importexport/musicxml/internal/import/importmusicxmlpass1.cpp +++ b/src/importexport/musicxml/internal/import/importmusicxmlpass1.cpp @@ -3287,13 +3287,13 @@ void MusicXmlParserPass1::handleOctaveShift(const Fraction& cTime, short sz = 0; switch (size) { - case 8: sz = 1; + case 22: sz = 3; break; case 15: sz = 2; break; + case 8: default: - m_logger->logError(String(u"invalid octave-shift size %1").arg(size), &m_e); - return; + sz = 1; } if (!cTime.isValid() || cTime < Fraction(0, 1)) { diff --git a/src/importexport/musicxml/internal/import/importmusicxmlpass2.cpp b/src/importexport/musicxml/internal/import/importmusicxmlpass2.cpp index 96987e7eb0ca8..aa89922d19d38 100644 --- a/src/importexport/musicxml/internal/import/importmusicxmlpass2.cpp +++ b/src/importexport/musicxml/internal/import/importmusicxmlpass2.cpp @@ -5297,6 +5297,8 @@ void MusicXmlParserDirection::octaveShift(const String& type, const int number, o->setOttavaType(OttavaType::OTTAVA_8VA); } else if (ottavasize == 15) { o->setOttavaType(OttavaType::OTTAVA_15MA); + } else if (ottavasize == 22) { + o->setOttavaType(OttavaType::OTTAVA_22MA); } } else if (type == u"up") { m_placement = m_placement.empty() ? u"below" : m_placement; @@ -5304,6 +5306,8 @@ void MusicXmlParserDirection::octaveShift(const String& type, const int number, o->setOttavaType(OttavaType::OTTAVA_8VB); } else if (ottavasize == 15) { o->setOttavaType(OttavaType::OTTAVA_15MB); + } else if (ottavasize == 22) { + o->setOttavaType(OttavaType::OTTAVA_22MB); } } From 4a618dd5f64be90687b8052e0a2aa62d2021b4af Mon Sep 17 00:00:00 2001 From: rettinghaus Date: Sat, 11 Jul 2026 20:23:54 +0200 Subject: [PATCH 5/8] adjust tests --- .../tests/data/testColorExport_ref.xml | 4 +-- ...cludeInvisibleElements_noinvisible_ref.xml | 4 +-- .../musicxml/tests/data/testLayout.xml | 4 +-- .../musicxml/tests/data/testLines1.xml | 16 ++++----- .../musicxml/tests/data/testOctaveShift.xml | 34 +++++++++---------- .../tests/data/testOverlappingSpanners.xml | 8 ++--- .../tests/data/testTimeTickExport_ref.xml | 4 +-- 7 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/importexport/musicxml/tests/data/testColorExport_ref.xml b/src/importexport/musicxml/tests/data/testColorExport_ref.xml index 46efef2327e1a..3592b430f2db0 100644 --- a/src/importexport/musicxml/tests/data/testColorExport_ref.xml +++ b/src/importexport/musicxml/tests/data/testColorExport_ref.xml @@ -274,7 +274,7 @@ Ausdruck - + @@ -363,7 +363,7 @@ 1 quarter - + diff --git a/src/importexport/musicxml/tests/data/testExcludeInvisibleElements_noinvisible_ref.xml b/src/importexport/musicxml/tests/data/testExcludeInvisibleElements_noinvisible_ref.xml index c89c88a967b73..2598348934493 100644 --- a/src/importexport/musicxml/tests/data/testExcludeInvisibleElements_noinvisible_ref.xml +++ b/src/importexport/musicxml/tests/data/testExcludeInvisibleElements_noinvisible_ref.xml @@ -474,7 +474,7 @@ - + @@ -519,7 +519,7 @@ quarter up - + diff --git a/src/importexport/musicxml/tests/data/testLayout.xml b/src/importexport/musicxml/tests/data/testLayout.xml index 9673172815544..bb6e00d9c87eb 100644 --- a/src/importexport/musicxml/tests/data/testLayout.xml +++ b/src/importexport/musicxml/tests/data/testLayout.xml @@ -119,7 +119,7 @@ 4 - + @@ -177,7 +177,7 @@ down 2 - + diff --git a/src/importexport/musicxml/tests/data/testLines1.xml b/src/importexport/musicxml/tests/data/testLines1.xml index 2e1fee258214d..254c699b83eca 100644 --- a/src/importexport/musicxml/tests/data/testLines1.xml +++ b/src/importexport/musicxml/tests/data/testLines1.xml @@ -59,7 +59,7 @@ quarter up - + @@ -84,7 +84,7 @@ quarter up - + @@ -111,7 +111,7 @@ quarter down - + @@ -136,7 +136,7 @@ quarter down - + @@ -163,7 +163,7 @@ quarter up - + @@ -198,7 +198,7 @@ quarter up - + @@ -215,7 +215,7 @@ quarter down - + @@ -250,7 +250,7 @@ quarter down - + diff --git a/src/importexport/musicxml/tests/data/testOctaveShift.xml b/src/importexport/musicxml/tests/data/testOctaveShift.xml index 005965c6f0668..eb7e063982a47 100644 --- a/src/importexport/musicxml/tests/data/testOctaveShift.xml +++ b/src/importexport/musicxml/tests/data/testOctaveShift.xml @@ -515,7 +515,7 @@ C - 4 + 7 1 1 @@ -525,7 +525,7 @@ D - 4 + 7 1 1 @@ -535,7 +535,7 @@ E - 4 + 7 1 1 @@ -545,7 +545,7 @@ F - 4 + 7 1 1 @@ -567,7 +567,7 @@ G - 4 + 1 1 1 @@ -577,7 +577,7 @@ F - 4 + 1 1 1 @@ -587,7 +587,7 @@ E - 4 + 1 1 1 @@ -597,7 +597,7 @@ D - 4 + 1 1 1 @@ -609,7 +609,7 @@ C - 4 + 1 1 1 @@ -619,7 +619,7 @@ D - 4 + 1 1 1 @@ -629,7 +629,7 @@ E - 4 + 1 1 1 @@ -639,13 +639,18 @@ F - 4 + 1 1 1 quarter up + + + + + @@ -772,11 +777,6 @@ quarter up - - - - - light-heavy diff --git a/src/importexport/musicxml/tests/data/testOverlappingSpanners.xml b/src/importexport/musicxml/tests/data/testOverlappingSpanners.xml index 9e51af5542079..3b2e00ee40bbc 100644 --- a/src/importexport/musicxml/tests/data/testOverlappingSpanners.xml +++ b/src/importexport/musicxml/tests/data/testOverlappingSpanners.xml @@ -286,7 +286,7 @@ up 1 - + @@ -328,7 +328,7 @@ down 2 - + @@ -391,7 +391,7 @@ up 1 - + @@ -433,7 +433,7 @@ down 2 - + diff --git a/src/importexport/musicxml/tests/data/testTimeTickExport_ref.xml b/src/importexport/musicxml/tests/data/testTimeTickExport_ref.xml index a249682dd8d23..379fb060854f2 100644 --- a/src/importexport/musicxml/tests/data/testTimeTickExport_ref.xml +++ b/src/importexport/musicxml/tests/data/testTimeTickExport_ref.xml @@ -85,7 +85,7 @@ - + @@ -140,7 +140,7 @@ whole 1 - + From 9fa69b1c71f2e393fb0cabaf0de7898524bc0f30 Mon Sep 17 00:00:00 2001 From: rettinghaus Date: Sat, 11 Jul 2026 20:24:14 +0200 Subject: [PATCH 6/8] minor fixes --- .../internal/export/exportmusicxml.cpp | 6 +++ .../internal/import/importmusicxmlpass2.cpp | 2 +- ...ExcludeInvisibleElements_invisible_ref.xml | 8 +-- .../musicxml/tests/data/testOctaveShift.xml | 52 +++++++++---------- 4 files changed, 37 insertions(+), 31 deletions(-) diff --git a/src/importexport/musicxml/internal/export/exportmusicxml.cpp b/src/importexport/musicxml/internal/export/exportmusicxml.cpp index 26f8f64256074..0482dcb0d9207 100644 --- a/src/importexport/musicxml/internal/export/exportmusicxml.cpp +++ b/src/importexport/musicxml/internal/export/exportmusicxml.cpp @@ -1675,6 +1675,8 @@ static void pitch2xml(const Note* note, String& s, int& alter, int& octave) // correct for ottava lines int ottava = 0; switch (note->ppitch() - note->pitch()) { + case 36: ottava = 3; + break; case 24: ottava = 2; break; case 12: ottava = 1; @@ -1685,6 +1687,8 @@ static void pitch2xml(const Note* note, String& s, int& alter, int& octave) break; case -24: ottava = -2; break; + case -36: ottava = -3; + break; default: LOGD("pitch2xml() tick=%d pitch()=%d ppitch()=%d", tick.ticks(), note->pitch(), note->ppitch()); } @@ -5675,6 +5679,8 @@ void ExportMusicXml::ottava(Ottava const* const ot, staff_idx_t staff, const Fra octaveShiftXml = String(u"octave-shift type=\"stop\" size=\"8\" number=\"%1\"").arg(n + 1); } else if (st == OttavaType::OTTAVA_15MA || st == OttavaType::OTTAVA_15MB) { octaveShiftXml = String(u"octave-shift type=\"stop\" size=\"15\" number=\"%1\"").arg(n + 1); + } else if (st == OttavaType::OTTAVA_22MA || st == OttavaType::OTTAVA_22MB) { + octaveShiftXml = String(u"octave-shift type=\"stop\" size=\"22\" number=\"%1\"").arg(n + 1); } else { LOGD("ottava subtype %d not understood", int(st)); } diff --git a/src/importexport/musicxml/internal/import/importmusicxmlpass2.cpp b/src/importexport/musicxml/internal/import/importmusicxmlpass2.cpp index aa89922d19d38..9b72f58d79a49 100644 --- a/src/importexport/musicxml/internal/import/importmusicxmlpass2.cpp +++ b/src/importexport/musicxml/internal/import/importmusicxmlpass2.cpp @@ -5286,7 +5286,7 @@ void MusicXmlParserDirection::octaveShift(const String& type, const int number, return; } int ottavasize = m_e.intAttribute("size"); - if (!(ottavasize == 8 || ottavasize == 15)) { + if (!(ottavasize == 8 || ottavasize == 15 || ottavasize == 22)) { m_logger->logError(String(u"unknown octave-shift size %1").arg(ottavasize), &m_e); } else { Ottava* o = spdesc.isStopped ? toOttava(spdesc.sp) : Factory::createOttava(m_score->dummy()); diff --git a/src/importexport/musicxml/tests/data/testExcludeInvisibleElements_invisible_ref.xml b/src/importexport/musicxml/tests/data/testExcludeInvisibleElements_invisible_ref.xml index e3a84495d7978..e1a2f2bfbaca7 100644 --- a/src/importexport/musicxml/tests/data/testExcludeInvisibleElements_invisible_ref.xml +++ b/src/importexport/musicxml/tests/data/testExcludeInvisibleElements_invisible_ref.xml @@ -523,7 +523,7 @@ - + @@ -568,14 +568,14 @@ quarter up - + - + @@ -620,7 +620,7 @@ quarter up - + diff --git a/src/importexport/musicxml/tests/data/testOctaveShift.xml b/src/importexport/musicxml/tests/data/testOctaveShift.xml index eb7e063982a47..2bd2fae1bfddd 100644 --- a/src/importexport/musicxml/tests/data/testOctaveShift.xml +++ b/src/importexport/musicxml/tests/data/testOctaveShift.xml @@ -2,10 +2,11 @@ - Alls octave-shifts + All octave-shifts + Klaus Rettinghaus MuseScore 0.7.0 2007-09-10 @@ -20,7 +21,6 @@ Piano Piano - keyboard.piano @@ -509,7 +509,7 @@ - + @@ -552,22 +552,12 @@ quarter up - - - - - - - - - - G - 1 + 7 1 1 @@ -577,7 +567,7 @@ F - 1 + 7 1 1 @@ -587,7 +577,7 @@ E - 1 + 7 1 1 @@ -597,15 +587,25 @@ D - 1 + 7 1 1 quarter up + + + + + + + + + + C @@ -646,17 +646,12 @@ quarter up - - - - - G - 4 + 1 1 1 @@ -666,7 +661,7 @@ F - 4 + 1 1 1 @@ -676,7 +671,7 @@ E - 4 + 1 1 1 @@ -686,13 +681,18 @@ D - 4 + 1 1 1 quarter up + + + + + From e95bd0c29d946c9945ed7ddaa3a5fe803ef7fc1a Mon Sep 17 00:00:00 2001 From: rettinghaus Date: Sun, 12 Jul 2026 13:43:57 +0200 Subject: [PATCH 7/8] fix code style --- .../musicxml/internal/import/importmusicxmlpass1.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/importexport/musicxml/internal/import/importmusicxmlpass1.cpp b/src/importexport/musicxml/internal/import/importmusicxmlpass1.cpp index 2b75c3cb1ef3b..b77836c12ac00 100644 --- a/src/importexport/musicxml/internal/import/importmusicxmlpass1.cpp +++ b/src/importexport/musicxml/internal/import/importmusicxmlpass1.cpp @@ -3287,11 +3287,11 @@ void MusicXmlParserPass1::handleOctaveShift(const Fraction& cTime, short sz = 0; switch (size) { - case 22: sz = 3; + case 22: sz = 3; break; - case 15: sz = 2; + case 15: sz = 2; break; - case 8: + case 8: default: sz = 1; } From 9cd4eac515835e0d0bfaf954100c4f2b0bedbff5 Mon Sep 17 00:00:00 2001 From: Klaus Rettinghaus Date: Tue, 14 Jul 2026 16:47:32 +0200 Subject: [PATCH 8/8] use nullptr Co-authored-by: James Mizen --- src/importexport/musicxml/internal/export/exportmusicxml.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/importexport/musicxml/internal/export/exportmusicxml.cpp b/src/importexport/musicxml/internal/export/exportmusicxml.cpp index 0482dcb0d9207..01c6dbf531180 100644 --- a/src/importexport/musicxml/internal/export/exportmusicxml.cpp +++ b/src/importexport/musicxml/internal/export/exportmusicxml.cpp @@ -5691,7 +5691,7 @@ void ExportMusicXml::ottava(Ottava const* const ot, staff_idx_t staff, const Fra const Fraction tickToWrite = isStart ? ot->tick() : ot->tick2(); moveToTickIfNeed(tickToWrite, ot->track(), measureStart); - directionTag(m_xml, m_attr, 0); + directionTag(m_xml, m_attr, nullptr); m_xml.startElement("direction-type"); octaveShiftXml += color2xml(ot); octaveShiftXml += positioningAttributes(ot, ot->tick() == tick);