Skip to content

feat: support multi-note tremolos in mx::api#330

Open
webern wants to merge 1 commit into
mainfrom
claude/mx-api-interface-jdo2yy
Open

feat: support multi-note tremolos in mx::api#330
webern wants to merge 1 commit into
mainfrom
claude/mx-api-interface-jdo2yy

Conversation

@webern

@webern webern commented Jul 7, 2026

Copy link
Copy Markdown
Owner

Human Summary

That MarkData class is already a hodgepodge of things that are only applicable if the markType happens to correspond to it. It is not nice, and this extended the pattern. Not sure about this one but it is a quick path to making the feature reachable.

Summary

mx::api could represent single-note (glyph) tremolos but silently dropped the measured, two-note
form written as <tremolo type="start">/<tremolo type="stop"> on adjacent notes. This adds it.

  • MarkType gains tremoloStart and tremoloStop, marking the first and second note of a
    measured tremolo. The existing tremoloSingleOne..Five glyph marks are unchanged.
  • MarkData gains tremoloMarks (std::optional<int>), the slash count (0-8) for the new mark
    types. The tremoloSingle* marks keep encoding their count in the enumerator itself, as before.
  • MusicXML's <tremolo> has no number attribute (unlike slur/tie), so there is nothing to key a
    cross-note match on. Pairing the start on one note with the stop on a later note is left to the
    api consumer via document order, the same way NoteData::isTieStart/isTieStop already work.
  • OrnamentsFunctions.cpp (read) and NotationsWriter.cpp (write) are updated symmetrically;
    isMarkTremolo/isMarkOrnament include the two new mark types. Unmeasured tremolos are still
    not representable and continue to be dropped as before.

Testing

  • New tests in NoteDataTest.cpp: an in-memory round trip of two adjacent notes carrying
    tremoloStart/tremoloStop marks, and a read test against data/synthetic/tremolo.3.0.xml
  • make test: all pass (4745 assertions in 382 test cases, plus the three examples)
  • make test-api-roundtrip: 159 passed, 0 failed (of 159 pinned; no regressions)
  • make discover-api-roundtrip: no newly-attributable passes; the two corpus files with real
    start/stop tremolo content (musuite/testTremolo.xml, lysuite/ly23e_Tuplets_Tremolo.xml)
    still fail on unrelated pre-existing subset gaps (an identification/rights mismatch and a
    time-modification gap, respectively), so no roundtrip-baseline.txt entry was added
  • make fmt / make check clean

References

Add MarkType::tremoloStart/tremoloStop plus MarkData::tremoloMarks (the
slash count, 0-8) so a <tremolo type="start"/"stop"> pair spanning two
adjacent notes can be authored and round-tripped. The existing
tremoloSingleOne..Five glyph marks are unchanged. Pairing across notes is
left to the api consumer via document order, matching the isTieStart/
isTieStop precedent -- MusicXML's <tremolo> has no `number` attribute to
key off of.

Closes #329.
@webern webern added feature new feature request non-breaking fixes or implementation that do not require breaking changes api Affects the mx::api layer impl Affects the mx::impl layer ai Issues opened by, or through, a coding agent. labels Jul 7, 2026 — with Claude
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

Coverage report

Core-dev coverage src/private/mx/core/

Metric Coverage Covered / Total
Lines 77.8% 28513 / 36642
Functions 74.3% 6352 / 8552
Branches 50.7% 22678 / 44751

API coverage src/private/mx/{api,impl,utility}/

Metric Coverage Covered / Total
Lines 80.9% 6437 / 7956
Functions 68.1% 2230 / 3276
Branches 49.7% 5525 / 11122

Core HTML report | API HTML report

Commit 0f5c38ddfffa33ff61e573490bf363e32ab9f2a6.

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

gen-quality gen/

gen-quality: 84.5 / 100   (floor 84.5, +0.0)

  structure     86.5  x0.50   [fn 90.5 / file 82.6]
  cyclomatic    88.4  x0.25
  cognitive     76.6  x0.25

  409 functions across 31 files, 7702 lines (largest file 1044)
  max cc 56  max cognitive 44  max fn loc 152

Worst offenders (top 5 per axis; full lists in score.json):
  cyclomatic gen/xsd/analyze.py:311     report                             56
  cyclomatic gen/plates/build.py:956    _validate_config_against_ir        35
  cyclomatic gen/press/context.py:145   plate_context                      34
  cyclomatic gen/__main__.py:46         _ir                                23
  cyclomatic gen/tests/test_ir.py:102   _check_references                  20
  cognitive  gen/xsd/analyze.py:311     report                             44
  cognitive  gen/ir/resolve.py:119      flat_elements                      40
  cognitive  gen/tests/test_ir.py:102   _check_references                  38
  cognitive  gen/press/context.py:145   plate_context                      37
  cognitive  gen/xsd/analyze.py:207     _sccs                              37
  size       gen/xsd/analyze.py:311     report                             152
  size       gen/press/context.py:145   plate_context                      96
  size       gen/plates/build.py:533    _value_plate                       89
  size       gen/plates/build.py:956    _validate_config_against_ir        89
  size       gen/ir/resolve.py:119      flat_elements                      78

Commit 0f5c38ddfffa33ff61e573490bf363e32ab9f2a6.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai Issues opened by, or through, a coding agent. api Affects the mx::api layer feature new feature request impl Affects the mx::impl layer non-breaking fixes or implementation that do not require breaking changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: support multi-note tremolos in mx::api

1 participant