[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: grace notes break preceding ties in MIDI
From: |
Adam Spiers |
Subject: |
Re: grace notes break preceding ties in MIDI |
Date: |
Sun, 13 Jan 2013 16:40:03 +0000 |
On Sat, Jan 12, 2013 at 12:52 PM, Adam Spiers
<address@hidden> wrote:
> [thread moved from lilypond-user]
>
> On Tue, Jan 8, 2013 at 5:59 PM, Adam Spiers
> <address@hidden> wrote:
>> On Tue, Jan 8, 2013 at 5:41 PM, Eluze <address@hidden> wrote:
>>> I've added an issue to the tracker:
>>> https://code.google.com/p/lilypond/issues/detail?id=3091&thanks=3091&ts=1357666391
>>
>> Thanks!
>>
>>> I'm not aware of a workaround - I could imagine using 2 voices, one without
>>> the grace the other with just the grace and a muted note - but this seems
>>> pretty awkward!
>>
>> Is it perhaps the fault of the
>>
>> if (now_mom ().grace_part_)
>>
>> section in Note_performer::process_music() in lily/note-performer.cc?
>> Does it somehow reintroduce the previous note when shortening it to
>> make room for the grace note, even though the previous note was tied
>> to the one before?
>
> Is there a performer tutorial similar to the engraver tutorial?
>
> http://lilypond.org/doc/v2.16/Documentation/contributor/engraver-tutorial
>
> I've started trying to fix the above bug, but my knowledge of
> LilyPond's C++ performer code (let alone any other code) is poor, and
> getting to grips with the various data structures is slow work. I'm
> running it through gdb which helps, but any other pointers would be
> really useful. Thanks!
I have finally pinned this down! And I'm close to a fix. The culprit
is in Midi_walker::process():
if (note->audio_->length_mom_.to_bool ())
do_start_note (note);
This to_bool () check is too simplistic. Here is the explanation ...
If you have a tie followed by a grace:
a1~a4 \grace b8
then Tie_performer::acknowledge_audio_element() will invoke
Audio_note::tie_to() which will lengthen the duration of the
Audio_note corresponding to the a1 by 1/4, and then set the length of
the Audio_note corresponding corresponding to the a4 to zero.
Later, when Note_performer::process_music() encounters the b8 grace
note, it will shorten the grace_part_ of the now-zero-length
Audio_note for a4 by 1/8, reducing it to -1/8. If you were to invoke
to_string() on the Audio_note at this point, you'd get "0G-1/8".
Now we see why the to_bool() check above is too simplistic. It's
implemented as:
bool
Moment::to_bool () const
{
return main_part_ || grace_part_;
}
but because the grace_part_ is no longer zero, do_start_note will be
invoked for the tied note!
I believe a reasonable approach would be to use a different check:
if (note->audio_->length_mom_.main_part_ ||
note->audio_->length_mom_.grace_part_.sign () == 1)
do_start_note (note);
It may even warrant a new Audio_note::is_positive_duration() method
which could be used here.
Thoughts?
However, this suggested workaround is not sufficient by itself - there
is a related issue with the ordering of NoteOff events which I'm
working on now.