Skip to content

fix(importer): apply MusicXML dynamics per part and show them only where written - #2996

Merged
Danielku15 merged 1 commit into
developfrom
feature/issue-2979
Oct 29, 2026
Merged

Danielku15 merged 1 commit into
developfrom
feature/issue-2979

Conversation

@Danielku15

@Danielku15 Danielku15 commented Oct 29, 2026 •

Copy link
Copy Markdown
Member

Note

AI-authored disclosure (alphatab-ai-authored-v1)

Portions of this content were authored by an AI agent. The agent has read
AGENTS.md and the human submitter accepts responsibility for
compliance with the rules in that document.

Issues

Fixes #2979

Proposed changes

The MusicXML importer kept one importer-wide "current dynamic" and gave it to whichever beat it created next in document order. <staff> was ignored, so a dynamic leaked onto other staves of a part (in 43e-Multistaff-ClefDynamics staff 2 showed and played p from beat 1, before it is even written) and into other parts.

  • Display: following MusicXML, a <direction> dynamic belongs to the next note of its staff (and voice, if given) and is shown there. This is expressed by the new optional Beat.showDynamics; when unset (all other importers) rendering is unchanged.
  • Playback: after parsing, the markings are carried forward in time to all staves of their part. MusicXML has no way to say whether a dynamic on staff 1 of a piano part means one hand or both. 43e and the Finale piano exports in test-data use the identical encoding with opposite intent, and MuseScore 4 and Dorico apply dynamics to the whole instrument by default. Strictly per-staff playback would make the left hand of those Finale files play f under a written p. Of markings at the same position, the staff's own one wins, so per-hand dynamics written together still work.
  • Note-attached <notations><dynamics> are now shown too (they were always hidden). Repeats of these are not redrawn, because Guitar Pro writes one on every note.
  • <offset> is not used for dynamics; a marking takes effect at its note.

24 MusicXML references change. Dynamics that are not written disappear (the default f on the first beat, copies on other staves and parts), and written ones that were hidden now show (note-attached dynamics, restated p/pp after hairpins).

showDynamics cannot be expressed in alphaTex or Guitar Pro, so exporting such a score draws inherited dynamics where the value changes, as before.

Checklist

  • I consent that this change becomes part of alphaTab under its current or any future open source license
  • This PR is linked to an accepted issue (see above)
  • Changes are implemented
  • New tests were added
  • I have read AGENTS.md if an AI helped draft any part of this PR

AI authorship disclosure

  • No AI agent authored any part of this PR (description, code, tests, or commit messages)
  • An AI agent contributed to this PR. The AI-authored disclosure block
    (alphatab-ai-authored-v1) is present at the top of this body, and I have
    personally reviewed every change and can explain each one

Further details

  • This is a breaking change
  • This change will require update of the documentation/website

…ere written

Dynamics were kept as one importer-wide state assigned to the next created
beat, leaking across staves and parts. A marking is now shown on the next note
of the staff (and voice) it is written for via the new Beat.showDynamics, and
carried forward in time to all staves of its part for playback, like MuseScore
and Dorico do by default.

Fixes #2979
@Danielku15
Danielku15 merged commit f50d775 into develop Oct 29, 2026
7 checks passed
@Danielku15
Danielku15 deleted the feature/issue-2979 branch October 29, 2026 18:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MusicXML: dynamics on one staff of a multi-staff part also show up on the other staff

1 participant