bug-lilypond
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: MIDI bug - re-attacking a note


From: Michael Welsh Duggan
Subject: Re: MIDI bug - re-attacking a note
Date: Fri, 26 Aug 2005 19:52:29 -0400
User-agent: Gnus/5.110004 (No Gnus v0.4) Emacs/22.0.50 (gnu/linux)

Michael Welsh Duggan <address@hidden> 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
(address@hidden)




reply via email to

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