Re: MIDI bug - re-attacking a note

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Re: MIDI bug - re-attacking a note

Michael Welsh Duggan
Sorry about the lack of a Reference or Reply-to.  I am replying based
on the web archive of this message.

Yuval Harel writes:

>
> When a note is attacked while it is already playing, no MIDI event
> is generated. This occurs often in piano notation.
>
> Here is an example:
>
> \version "2.6.3"
> \score {
>         <<
>                 c4 \\
>                 {r8
>                         c8 % <-- this note is not played
>                 }
>         >>
>         \midi {}
> }
I have a patch which I wrote for 2.4.5 which fixes this behavior.

Possible problems with this patch: In the past, it was mentioned that
for some instruments, reattacking the note actually should have
different behaviors depending on the instrument.  (I personally, have
no idea.)  This patch introduces semantics which appear to work well
for piano music, at least.

Here follows the patch as ported to CVS:



--
Michael Welsh Duggan
([hidden email])

_______________________________________________
bug-lilypond mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/bug-lilypond
Reply | Threaded
Open this post in threaded view
|

Re: MIDI bug - re-attacking a note

Michael Welsh Duggan
Michael Welsh Duggan <[hidden email]> writes:

> I have a patch which I wrote for 2.4.5 which fixes this behavior.
>
> Possible problems with this patch: In the past, it was mentioned that
> for some instruments, reattacking the note actually should have
> different behaviors depending on the instrument.  (I personally, have
> no idea.)  This patch introduces semantics which appear to work well
> for piano music, at least.
>
> Here follows the patch as ported to CVS:

Which was stripped.  Here is is, inline:

Index: VERSION
===================================================================
RCS file: /cvsroot/lilypond/lilypond/VERSION,v
retrieving revision 1.654
diff -u -p -u -r1.654 VERSION
--- VERSION 22 Aug 2005 23:12:44 -0000 1.654
+++ VERSION 25 Aug 2005 21:34:50 -0000
@@ -2,5 +2,5 @@ PACKAGE_NAME=LilyPond
 MAJOR_VERSION=2
 MINOR_VERSION=7
 PATCH_LEVEL=8
-MY_PATCH_LEVEL=
+MY_PATCH_LEVEL=mwd
 
Index: flower/include/pqueue.hh
===================================================================
RCS file: /cvsroot/lilypond/lilypond/flower/include/pqueue.hh,v
retrieving revision 1.18
diff -u -p -u -r1.18 pqueue.hh
--- flower/include/pqueue.hh 12 Aug 2005 00:04:47 -0000 1.18
+++ flower/include/pqueue.hh 25 Aug 2005 21:34:50 -0000
@@ -84,8 +84,45 @@ public:
     T max_t;
     return max_t;
   }
-  void delmin ()
+
+  void del (int i)
   {
+    assert (i < size ());
+    T last = heap_array_.pop ();
+
+    if (i == size ())
+      return;
+    
+    int tgt = ++i;
+
+    int next = i / 2;
+    while (next && compare (elt (next), last) > 0)
+      {
+        elt (tgt) = elt (next);
+        tgt = next;
+        next = tgt / 2;
+      }
+
+    if (tgt == i)
+      {
+        next = tgt * 2;
+        while (next <= size ())
+          {
+            if (((next + 1) < size ()) &&
+                (compare (elt (next + 1), elt (next)) < 0))
+              next++;
+            if (compare (last, elt (next)) < 0)
+              break;
+            elt (tgt) = elt (next);
+            tgt = next;
+            next = tgt * 2;
+          }
+      }
+    elt (tgt) = last;
+    OK ();
+  }
+        
+  void delmin () {
     assert (size ());
     T last = heap_array_.top ();
 
Index: lily/midi-walker.cc
===================================================================
RCS file: /cvsroot/lilypond/lilypond/lily/midi-walker.cc,v
retrieving revision 1.50
diff -u -p -u -r1.50 midi-walker.cc
--- lily/midi-walker.cc 13 Aug 2005 21:35:22 -0000 1.50
+++ lily/midi-walker.cc 25 Aug 2005 21:34:51 -0000
@@ -60,26 +60,39 @@ Midi_walker::do_start_note (Midi_note *n
   bool play_start = true;
   for (int i = 0; i < stop_note_queue.size (); i++)
     {
-      /* if this pith already in queue */
-      if (stop_note_queue[i].val->get_pitch () == note->get_pitch ())
+      /* if this pitch already in queue */
+      if (stop_note_queue[i].val->get_pitch () == note->get_pitch ())
  {
-  if (stop_note_queue[i].key < stop_mom)
-    {
-      /* let stopnote in queue be ignored,
- new stop note wins */
-      stop_note_queue[i].ignore_b_ = true;
-      /* don't replay start note, */
-      play_start = false;
-      break;
-    }
-  else
-    {
-      /* skip this stopnote,
- don't play the start note */
-      delete note;
-      note = 0;
-      break;
-    }
+          if (ptr->audio_column_->at_mom () ==
+              (stop_note_queue[i].key - stop_note_queue[i].val->get_length()))
+            {
+              // The two notes started at the same time.  Merge them.
+              if (stop_note_queue[i].key < stop_mom)
+                {
+                  Midi_note_event e;
+                  e.val = stop_note_queue[i].val;
+                  e.key = stop_mom;
+                  stop_note_queue.del (i);
+                  stop_note_queue.insert (e);
+                }
+              delete note;
+              note = 0;
+              break;
+            }
+  else
+            {
+              // A note was played that interruped a played note.
+              // Stop the old note, and continue to the greatest moment
+              // between the two.
+              if (stop_note_queue[i].key > stop_mom)
+                {
+                  stop_mom = stop_note_queue[i].key;
+                }
+              output_event (ptr->audio_column_->at_mom (),
+                            stop_note_queue[i].val);
+              stop_note_queue.del(i);
+              break;
+            }
  }
     }
 


--
Michael Welsh Duggan
([hidden email])


_______________________________________________
bug-lilypond mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/bug-lilypond