This is a trial to classify the different grace synchronisation situations. I do not claim completeness, nor do I claim I’ve listed the best method to solve the major subset of issue 34.
In my collection of grace synchronisation issues (yes, I speak from them in plural) I can see most of them are “two tier situations” (i.e. it just depends where the event in the voice is placed compared with the whole score) and a few of them are “three tier situations” (i.e. it also depends on which events are collected into the same staff during the grace time steps before this event). The “two tier” issues can be divided into several sub classes. One subclass is the group of the “globally collected (and consolidated) two tier situations”. They usually create a GROB immediately by an engraver (mostly in score level). If at least one voice is “in time” the faulty output will be a “grace echo” where the GROBs are repeated, otherwise it would be a “grace delay” where the related GROBs are placed too much right on the printing output. There is a simple workaround for the “grace echo”, namely for “manual bar lines”, “time signatures” and “tempo marks”: Just delete the echoed ones and keep the one at the first grace time step of the main time period. (See LSR #). For “repeat commands” and “rehearsal marks” it’s a little tricky, because you need to do the purging between two engravers for the “repeat commands” and the “rehearsal mark” engraving must be inhibited to process the automatic increment. Another subclass is the group of the “direct modifications of context properties”, namely “set”, “unset”, “override”, “revert” and “applyContext”. “set” and “override” also know the modification “\once”, and there are a few properties to be “set” without the “once” modification, but they are processed like “once”, e.g. “stemLeftBeamCount”, “stemRightBeamCount”. One strategy to solve the grace synchronisation issue is to process all related music events more early if required, i.e. at the first grace time step seen in the complete score. This is a candidate to solve most (perhaps all) “two tier grace situations”. I expect the “three tier grace situations” require a different strategy. For this “process early strategy” the “once” modifications of “set” and “override” may be transformed into a “long once” (i.e. for the complete main time step), into a “twice” (i.e. at the first grace time step of the complete score and at the time step – maybe grace time step – where defined in the voice), into a “semi long once” (i.e. from the first time step of the complete score, but terminated after the grace time step of the voice in which the event is defined), into a “early once” (i.e. only at the first grace time step of the complete score), into a “exact once” (i.e. the time step of the voice, as it is now). The other point is the “applyContext” event, where the user specifies his own SCHEME procedure to be executed – I think the user should specify whether he wants it to be executed “early” or “late”, too. This Question when to execute “applyContext” did lead me to the idea to add a new property to the events. Let’s call it “anticipate”. A TRUE is the request to execute it at the first score-wide grace time step, a FALSE is the request to execute it at the time step specified in the insulated voice. Using this “anticipate” property at the “once set” and “once override” events, too, would be a manual selection of “early once” and “exact once”. It could even be used for all events (without non zero duration) to control their interpretation time step, like a workaround when an “automatic selection” (if the “anticipate” attribute is not set) does not work. The selection at which time step to process an event is effectively done by LILYPONDs iterators. The “top level simultaneous music iterator” is the pivot point for this “anticipated interpretation”. Two or three more function calls between the iterators may implement this strategy. This iterator first checks which is the next time step to be executed by asking all sub-iterators by calling “pending_moment()” and returning the most early time step. At “process()” it asks again all sub-iterators to return the “pending_moment()”, and if this return value is equivalent to the “until” moment, the sup-iterator will be called to “process()” until the given “until” moment. The required modification in Simultaneous_music_iterator::process() could be: If the returned “pending_moment()” of the sub-iterator is not equivalent to the given “until” moment, but (a) the given “until” moment is the first one in the currently processed main time period, and (b) the main time part returned by “pending_moment()” is equivalent to the main time part of the “until” moment, and (c) a new call to the sub-iterator “event_to_anticipate_pending()” returns TRUE, then execute another new call “process_anticipating_events_until()” to the sub-iterator. Any “sub-level simultaneous music iterator” will be acknowledged with the score wide first grace time by receiving an “event_to_anticipate_pending()” call. The function “event_to_anticipate_pending()” shall return FALSE if the next event has a non zero duration, otherwise it shall return the value of the “anticipate” attribute if defined, otherwise it would (calculate and) return a default answer, possibly by executing a SCHEME callback. I’m not sure if only passing the event as parameter to such a SCHEME procedure would be enough in the future. A third function call may be necessary to warn the user on conflicts with a message like “event cannot be pulled before the preceding, not anticipated event”. Other strategies (to solve the remaining “three tier situations”) could be: - A “final engraver” collects all GROBs, and at the end of the main time step it rearranges the “web of GROBs”, i.e. it moves some GROBs into other columns. - The engravers track the situation (e.g. by using some context properties), and detect when a newly created GROB has to be aligned to an already passed (but cached) column. Well, the remaining “three tier situations” I found are: - Key signature change (well, I cannot imagine using it after a grace note, so generally setting the “anticipate” attribute to TRUE should be fine) - Breathe sign (I can imagine using it between grace notes) - Clef change (I know such a situation, I’m playing a woodwind instrument where \acciaccatura c8 e’’’1 is possible, a clef change would save vertical space, especially in the score) ArnoldTheresius -- View this message in context: http://lilypond.1069038.n5.nabble.com/Classification-of-grace-synchronisation-tp178464.html Sent from the Dev mailing list archive at Nabble.com. _______________________________________________ lilypond-devel mailing list [email protected] https://lists.gnu.org/mailman/listinfo/lilypond-devel
