lenmus / lomse

A C++ library for rendering, editing and playing back music scores.
MIT License
120 stars 28 forks source link

Fix bug: MusicXML duration ignored in tuplets #306

Closed cecilios closed 3 years ago

cecilios commented 3 years ago

Test file: overlap-problem.xml.txt

image

The cause of the error is the following:

The test file was generated by MuseScore. It defines <divisions>480</divisions> and assigns a duration of 69 to each note in the 7-tuplet (excesive, rounded up). Thus, total duration of the 7-tuplet is 483 instead of 480. To compensate the extra duration introduced, MuseScore adds a <backup> element with a duration of 3, so that next rest get properly positioned at 480 ticks, but causing an overlap between last 7-tuplet note and the rest. The <backup> and the overlap error could have been easily avoided by choosing another <divisions> value such as 345*7 = 420. This suggests a bug in the MuseScore MusicXML exporter.

When there is a tuplet, Lomse MusicXML importer ignored assigned duration and recomputed notes duration from total tuplet duration. Thus Lomse correctly computes the end of the tuplet at 480, but then, the backup shifts back current time position by an small amount, causing that the next rest after the 7-tuplet get placed, in time, slightly before than all other rests in the other staves. And this error is propagated to all following StaffObjs in fourth instrument, barlines included, and so, they are rendered slightly before. If the <backup> is removed the file was correctly rendered.

This PR fixes the MusicXML importer so that now MusicXML duration is always used and Lomse does not recompute it.

But once this bug is fixed, the file is displayed with a big gap after the first rest:

image

The cause is that last note of 7-tuplet is still sounding at timepos 480 (start of rest after that note), and thus, current spacing algorithm behaves as if there were two voices sounding in beat two of fourth instrument: the quarter rest and the last 7-tuplet note (approx. a 32th note) and thus, this small overlapped note forces excessive space after the rest.

Taking into account that:

I have decided not to open an issue for now. I will wait until more evidence than this case really needs to be addressed in Lomse.

dmitrio95 commented 3 years ago

Actually MuseScore also seems not to import this test file fully correctly, and the two rests in the first bar have slightly wrong time positions and are misplaced: изображение

As a consequence, importing and re-exporting this file back to MusicXML adds an extra <forward> tag for the same 3 divisions, and with this PR Lomse starts shifting barlines in the last staff a bit to the right (the re-exported score: overlap-problem-ms3.musicxml.txt): изображение

I don't think that is worth fixing though as it is indeed caused by an incorrect information in the MusicXML file. Perhaps there could be some way to ensure that barlines are always aligned vertically or that all voices in a measure have the same length after import — such solutions would limit an impact of this issue just to the incorrect measure itself. However this indeed may not worth the effort, and I agree that this can be postponed until more affected scores happen to be found.

cecilios commented 3 years ago

Thanks for checking this and for the comments. As the PR is not for solving the problems created by this score but for fixing a real bug in the importer I will merge this PR.

As to the error displayed now with the updated score after merging the PR I fully agree that this case is not worth correcting, at least until confirmed that can be a problem for real scores.

In general, forcing to align the barlines can be complex although for MusicXML perhaps some restrictions can be imposed. The problem is that Lomse was designed with the idea of allowing to encode and render incorrect scores. My application was oriented to teaching music and thus I had plans to build a music editor that would allow students to write scores in the same way than using pencil and paper: start with an empty staff and add objects to it without any constrains (or with the constrains set in the program by the teacher). Also I had the objective of allowing to notate poly-metric music without relaying on tricks such as hidden barlines or other. Therefore, Lomse does not use the traditional model of the scores based on measures. For Lomse a measure, if exists, is just the content between two barlines.

As this editor is no longer an objective, perhaps in a future it could be appropriate to move Lomse to the traditional model of the scores based on measures; that will automatically align all barlines.