Honour an explicit dynamics="0" on MusicXML note import#33804
Honour an explicit dynamics="0" on MusicXML note import#33804jonashogstrom wants to merge 1 commit into
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughThis PR fixes velocity handling in the MusicXML pass 2 importer for the 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Warning Review ran into problems🔥 ProblemsLinked repositories: Your configuration references 1 linked repositories, but your current plan allows 0. Analyzed ``, skipped Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Why not using a testNoteDynamics_ref.mscx and TEST_F(MusicXml_Tests, noteDynamics) {
musicXmlImportTestRef("testNoteDynamics");
}Check my backport to 3.x in Jojo-Schmitz#1223 |
Backport of musescore#33804 Co-Authored-By: Jonas Högström <jonas.hogstrom@pobox.com>
Backport of musescore#33804 Co-Authored-By: Jonas Högström <jonas.hogstrom@pobox.com>
The dynamics attribute of the <note> element expresses the note velocity as a percentage of the MIDI 1.0 default forte value of 90. Positive values were imported correctly, but an explicit dynamics="0" (a silent note, e.g. a ghost note or an unpitched gesture with an x notehead) was indistinguishable from an absent attribute and silently dropped, so the note played at full default velocity. Detect the attribute's presence instead of testing the computed value, and clamp the velocity to [1, 127]: the score model reserves velocity 0 for "unset", so 1 is the lowest representable (effectively silent) value, and the upper bound matches the clamping already applied to direction-level <sound dynamics> values. Resolves: musescore#33803 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
80f1fe3 to
3339e9c
Compare
|
Done in the latest push. Converted The reference covers the same four cases the test data exercises — |
|
I live it much better that way, thanks |
Backport of musescore#33804 Co-Authored-By: Jonas Högström <jonas.hogstrom@pobox.com>
Resolves: #33803
The
dynamicsattribute of the<note>element expresses the note velocity as a percentage of the MIDI 1.0 default forte value of 90. Positive values were imported correctly (dynamics="50"→ velocity 45), but an explicitdynamics="0"— a silent note, e.g. a ghost note or an unpitched gesture written with an x notehead — was indistinguishable from an absent attribute (doubleAttribute()returns 0 in both cases) and was silently dropped by thevelocity > 0guard, so the note played at full default velocity.This PR detects the attribute's presence with
hasAttribute()instead of testing the computed value, and clamps the imported velocity to[1, 127]:Note::customizeVelocity()also clamps to this range at playback time, so 1 is what a "silent" note effectively plays at in all backends).[0, 127]clamping already applied to direction-level<sound dynamics>values; previously e.g.dynamics="200"was stored as velocity 180, above the MIDI maximum, which every playback path clamps anyway and which round-tripped back out as an out-of-rangedynamicsvalue.Test: new
noteDynamicsunit test importing a five-note file covering the absent attribute (velocity stays unset),dynamics="0"(→ 1),dynamics="50"(→ 45, the already-working case), anddynamics="200"(→ clamped to 127).Verified end-to-end: a measure with a
dynamics="0"note now exports MIDI with that note at velocity 1 (effectively silent) while unmarked notes are unaffected; previously it played at the full default velocity 80.