lilypond-devel
[Top][All Lists]
Advanced

[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.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]