]> git.donarmstrong.com Git - lilypond.git/commitdiff
Fix #87.
authorHan-Wen Nienhuys <hanwen@xs4all.nl>
Thu, 11 Jan 2007 14:17:48 +0000 (15:17 +0100)
committerHan-Wen Nienhuys <hanwen@xs4all.nl>
Thu, 11 Jan 2007 14:17:48 +0000 (15:17 +0100)
Excise moments from midi backend completely, and move duration to
grace_part_ field in grace notes.  This fixes MIDI syncing problems
with grace notes.

input/regression/midi-grace.ly
lily/audio-column.cc
lily/audio-item.cc
lily/include/audio-column.hh
lily/include/audio-item.hh
lily/include/midi-item.hh
lily/include/midi-walker.hh
lily/midi-item.cc
lily/midi-walker.cc
lily/note-performer.cc
lily/performance.cc

index 213de79e37bcd8dc051e22d9453869ee5c296d07..5a58f3cbe83b647ab275d33a3e6ff8587eeab260 100644 (file)
@@ -1,22 +1,16 @@
-\version "2.10.0"
-\header{ texidoc = "Tests MIDI output with grace notes. " }
 
-\score { 
-  \context Voice \relative c {
-    \new Voice = VoiceOne
-       \grace {
-  \override Stem  #'stroke-style = #"grace"
-   c8 
-  \revert Stem #'stroke-style }
- d4 d d d d
-       \grace {
-  \override Stem  #'stroke-style = #"grace"
-   e16 f e f 
-  \revert Stem #'stroke-style }
- d4 d d d d 
-       
-  }
-  \layout { }  
-  \midi { }
-}
+\header {
 
+  texidoc = "Grace notes don't intrroduce syncing problems: the last note
+off will appear at tick 768 (2 * 384)."
+  
+}
+\version "2.10.10"
+\score {
+ \relative c' {
+   c4
+   \grace { b8 }
+   d4
+ }
+ \midi { }
+}
index 0bc1b6690f4f43e7f729ce4b0b58f658dbe58ce0..d052c4e8cc43821632e1490fe3a92ecf99dd9576 100644 (file)
@@ -29,9 +29,16 @@ Audio_column::when () const
   return when_;
 }
 
+int
+Audio_column::ticks () const
+{
+  return int (moment_to_ticks (when_));
+}
+
 void
 Audio_column::offset_when (Moment m)
 {
   when_ += m;
 }
 
+
index 9dd1322d281d1db068ee148a7cedbc5061758e8f..41381458f6e4f474a6d5c3167254d465c387d791 100644 (file)
@@ -75,11 +75,23 @@ Audio_span_dynamic::add_absolute (Audio_dynamic *d)
   dynamics_.push_back (d);
 }
 
-static Real
-moment2real (Moment m)
+Moment
+remap_grace_duration (Moment m)
 {
-  return m.main_part_.to_double ()
-    + 0.1 * m.grace_part_.to_double ();
+  return Moment (m.main_part_ + Rational (9,40) * m.grace_part_,
+                Rational (0));
+}
+
+Real
+moment_to_real (Moment m)
+{
+  return remap_grace_duration (m).main_part_.to_double ();
+}
+
+int
+moment_to_ticks (Moment m)
+{
+  return int (moment_to_real (m) * 384 * 4);
 }
 
 void
@@ -113,14 +125,14 @@ Audio_span_dynamic::render ()
 
   Moment start = dynamics_[0]->get_column ()->when ();
 
-  Real total_t = moment2real (dynamics_.back ()->get_column ()->when () - start);
+  Real total_t = moment_to_real (dynamics_.back ()->get_column ()->when () - start);
   
   for (vsize i = 1; i < dynamics_.size(); i ++)
     {
       Moment dt_moment = dynamics_[i]->get_column ()->when ()
        - start;
 
-      Real dt =  moment2real (dt_moment);
+      Real dt =  moment_to_real (dt_moment);
       
       Real v = start_v + delta_v *  (dt / total_t);
 
index cefa44f5a87da7ffe6a513c5a942ab0f7de19207..0b10c8bd4d479faf633458a7407db7dd0014c4ee 100644 (file)
@@ -26,7 +26,7 @@ public:
 
   vector<Audio_item*> audio_items_;
   Moment when_;
-
+  int ticks () const ;
 protected:
   void offset_when (Moment m);
   friend class Score_performer;
index 00fb2bce8dedf502fae2fa6859ffcbb215a0990c..c02eba58c19cbe04b4f118956ec60c6bafb9729e 100644 (file)
@@ -122,5 +122,9 @@ public:
   int one_beat_;
 };
 
+int moment_to_ticks (Moment);
+Real moment_to_real (Moment);
+Moment remap_grace_duration (Moment);
+
 #endif // AUDIO_ITEM_HH
 
index 9dd942bffcdd8b0f8f56ed7fdb5eb737dd32c5c1..6d77f21afc29872c1162f040b50f1ed61bb3cba9 100644 (file)
@@ -47,9 +47,9 @@ public:
 class Midi_event
 {
 public:
-  Midi_event (Moment delta_mom, Midi_item *midi);
+  Midi_event (int delta, Midi_item *midi);
 
-  Moment delta_mom_;
+  int delta_ticks_;
   Midi_item *midi_;
   string to_string () const;
 };
@@ -134,7 +134,6 @@ public:
   Midi_note (Audio_note *);
   DECLARE_CLASSNAME(Midi_note);
 
-  Moment get_length () const;
   int get_semitone_pitch () const;
   int get_fine_tuning () const;
   virtual string to_string () const;
@@ -225,7 +224,7 @@ public:
   Midi_track ();
   ~Midi_track ();
 
-  void add (Moment delta_time_mom, Midi_item *midi);
+  void add (int, Midi_item *midi);
   virtual string data_string () const;
 };
 
index bc12bb9aa68cc00c76bfa69ebc6765fd5e8f3b81..ee523e5faa850a0dbc71d5daf3d32cbd101b80d4 100644 (file)
@@ -12,7 +12,7 @@
 #include "lily-proto.hh"
 #include "moment.hh"
 
-struct Midi_note_event : PQueue_ent<Moment, Midi_note *>
+struct Midi_note_event : PQueue_ent<int, Midi_note *>
 {
   bool ignore_b_;
   Midi_note_event ();
@@ -36,16 +36,16 @@ public:
 
 private:
   void do_start_note (Midi_note *note);
-  void do_stop_notes (Moment now_mom);
-  void output_event (Moment now_mom, Midi_item *l);
+  void do_stop_notes (int);
+  void output_event (int, Midi_item *l);
 
   int channel_;
   Midi_track *track_;
   Audio_staff *staff_;
   vsize index_;
-  vector<Audio_item*> *items_;
+  vector<Audio_item*> items_;
   PQueue<Midi_note_event> stop_note_queue;
-  Moment last_mom_;
+  int last_tick_;
 };
 
 #endif // MIDI_WALKER_HH
index ebbb20aeecafc3e3ef8ae11aea12cf30e41d0805..ee05d4ed58dcabbf614703854bb542ba4c2c41f6 100644 (file)
@@ -90,21 +90,16 @@ Midi_duration::to_string () const
   return string ("<duration: ") + ::to_string (seconds_) + ">";
 }
 
-Midi_event::Midi_event (Moment delta_mom, Midi_item *midi)
+Midi_event::Midi_event (int delta_ticks, Midi_item *midi)
 {
-  delta_mom_ = delta_mom;
+  delta_ticks_ = delta_ticks;
   midi_ = midi;
 }
 
 string
 Midi_event::to_string () const
 {
-  assert (delta_mom_.grace_part_ == Rational (0));
-  
-  Rational rat_dt = delta_mom_.main_part_ * Rational (384) * Rational (4);
-  int delta = rat_dt.to_int ();
-
-  string delta_string = Midi_item::i2varint_string (delta);
+  string delta_string = Midi_item::i2varint_string (delta_ticks_);
   string midi_string = midi_->to_string ();
   assert (midi_string.length ());
   return delta_string + midi_string;
@@ -243,12 +238,6 @@ Midi_note::Midi_note (Audio_note *a)
   dynamic_byte_ = 0x7f;
 }
 
-Moment
-Midi_note::get_length () const
-{
-  Moment m = audio_->end_column_->when () - audio_->audio_column_->when ();
-  return m;
-}
 
 int
 Midi_note::get_fine_tuning () const
@@ -292,7 +281,7 @@ Midi_note::to_string () const
       str += ::to_string ((char) (0x00));
     }
 
-  str += ::to_string ((char)status_byte);
+  str += ::to_string ((char) status_byte);
   str += ::to_string ((char) (get_semitone_pitch () + c0_pitch_));
   str += ::to_string ((char)dynamic_byte_);
 
@@ -454,11 +443,11 @@ Midi_track::Midi_track ()
 }
 
 void
-Midi_track::add (Moment delta_time_mom, Midi_item *midi)
+Midi_track::add (int delta_ticks, Midi_item *midi)
 {
-  assert (delta_time_mom >= Moment (0));
+  assert (delta_ticks >= 0);
 
-  Midi_event *e = new Midi_event (delta_time_mom, midi);
+  Midi_event *e = new Midi_event (delta_ticks, midi);
   events_.push_back (e);
 }
 
index 3bdc426be042bb8d83c3423924d79a125f82c289..aa491bc930ddf8e202010b2a8ddf30df3b967a98 100644 (file)
@@ -33,21 +33,27 @@ compare (Midi_note_event const &left, Midi_note_event const &right)
     return 0;
 }
 
+bool
+audio_item_less (Audio_item * const a,
+                Audio_item * const b)
+{
+  return a->get_column ()->when_ <  b->get_column ()->when_;
+}
+
 Midi_walker::Midi_walker (Audio_staff *audio_staff, Midi_track *track,
                          int channel)
 {
   channel_ = channel;
   track_ = track;
   index_ = 0;
-  items_ = &audio_staff->audio_items_;
-
-  last_mom_ = 0;
+  items_ = audio_staff->audio_items_;
+  vector_sort (items_, audio_item_less);
+  last_tick_ = 0;
 }
 
 Midi_walker::~Midi_walker ()
 {
-  // ugh
-  do_stop_notes (last_mom_ + Moment (Rational (10, 1)));
+  do_stop_notes (last_tick_ + 384);
 }
 
 /**
@@ -56,8 +62,9 @@ Midi_walker::~Midi_walker ()
 void
 Midi_walker::do_start_note (Midi_note *note)
 {
-  Audio_item *ptr = (*items_)[index_];
-  Moment stop_mom = note->get_length () + ptr->audio_column_->when ();
+  Audio_item *ptr = items_[index_];
+  int stop_ticks = int (moment_to_real (note->audio_->length_mom_) * Real (384 * 4))
+    + ptr->audio_column_->ticks ();
 
   bool play_start = true;
   for (vsize i = 0; i < stop_note_queue.size (); i++)
@@ -66,7 +73,7 @@ Midi_walker::do_start_note (Midi_note *note)
       if (stop_note_queue[i].val->get_semitone_pitch ()
          == note->get_semitone_pitch ())
        {
-         if (stop_note_queue[i].key < stop_mom)
+         if (stop_note_queue[i].key < stop_ticks)
            {
              /* let stopnote in queue be ignored,
                 new stop note wins */
@@ -90,11 +97,11 @@ Midi_walker::do_start_note (Midi_note *note)
     {
       Midi_note_event e;
       e.val = new Midi_note_off (note);
-      e.key = stop_mom;
+      e.key = int (stop_ticks);
       stop_note_queue.insert (e);
 
       if (play_start)
-       output_event (ptr->audio_column_->when (), note);
+       output_event (ptr->audio_column_->ticks (), note);
     }
 }
 
@@ -102,9 +109,9 @@ Midi_walker::do_start_note (Midi_note *note)
    Output note events for all notes which end before #max_mom#
 */
 void
-Midi_walker::do_stop_notes (Moment max_mom)
+Midi_walker::do_stop_notes (int max_ticks)
 {
-  while (stop_note_queue.size () && stop_note_queue.front ().key <= max_mom)
+  while (stop_note_queue.size () && stop_note_queue.front ().key <= max_ticks)
     {
       Midi_note_event e = stop_note_queue.get ();
       if (e.ignore_b_)
@@ -113,10 +120,10 @@ Midi_walker::do_stop_notes (Moment max_mom)
          continue;
        }
 
-      Moment stop_mom = e.key;
+      int stop_ticks = e.key;
       Midi_note *note = e.val;
 
-      output_event (stop_mom, note);
+      output_event (stop_ticks, note);
     }
 }
 
@@ -124,26 +131,29 @@ Midi_walker::do_stop_notes (Moment max_mom)
    Advance the track to #now#, output the item, and adjust current "moment".
 */
 void
-Midi_walker::output_event (Moment now_mom, Midi_item *l)
+Midi_walker::output_event (int now_ticks, Midi_item *l)
 {
-  Moment delta_t = now_mom - last_mom_;
-  last_mom_ = now_mom;
+  int delta_ticks = now_ticks - last_tick_;
+  last_tick_ = now_ticks;
 
   /*
     this is not correct, but at least it doesn't crash when you
     start with graces
   */
-  if (delta_t < Moment (0))
-    delta_t = Moment (0);
+  if (delta_ticks < 0)
+    {
+      programming_error ("Going back in MIDI time.");
+      delta_ticks = 0;
+    }
 
-  track_->add (delta_t, l);
+  track_->add (delta_ticks, l);
 }
 
 void
 Midi_walker::process ()
 {
-  Audio_item *audio = (*items_)[index_];
-  do_stop_notes (audio->audio_column_->when ());
+  Audio_item *audio = items_[index_];
+  do_stop_notes (audio->audio_column_->ticks ());
 
   if (Midi_item *midi = Midi_item::get_midi (audio))
     {
@@ -153,18 +163,18 @@ Midi_walker::process ()
       //midi->channel_ = track_->number_;
       if (Midi_note *note = dynamic_cast<Midi_note *> (midi))
        {
-         if (note->get_length ().to_bool ())
+         if (note->audio_->length_mom_.to_bool ())
            do_start_note (note);
        }
       else
-       output_event (audio->audio_column_->when (), midi);
+       output_event (audio->audio_column_->ticks (), midi);
     }
 }
 
 bool
 Midi_walker::ok () const
 {
-  return index_ < items_->size ();
+  return index_ < items_.size ();
 }
 
 void
index a1503f2b61ac4884331d2e96bb6bc933917eb7d5..ff296311ffead109a8de2936f8542a3170b8aa0d 100644 (file)
@@ -65,7 +65,14 @@ Note_performer::process_music ()
                     tie_event = ev;
                 }
 
-             Audio_note *p = new Audio_note (*pitp, get_event_length (n), 
+             Moment len = get_event_length (n);
+             if (now_mom().grace_part_)
+               {
+                 len.grace_part_ = len.main_part_;
+                 len.main_part_ = Rational (0);
+               }
+             
+             Audio_note *p = new Audio_note (*pitp, len, 
                                               tie_event, transposing.negated ());
              Audio_element_info info (p, n);
              announce_element (info);
index 78070a064a39f8b57c640faca06fc8b0234c7a00..2c02fc32f94f3ff64aacab4a6dfc1bce18845982 100644 (file)
@@ -38,11 +38,9 @@ Performance::output (Midi_stream &midi_stream) const
 {
   int tracks_ = audio_staffs_.size ();
 
-  // ugh
-  int clocks_per_4 = 384;
-
-  midi_stream << Midi_header (1, tracks_, clocks_per_4);
-  message (_ ("Track...") + " ");
+  midi_stream << Midi_header (1, tracks_, 384);
+  if (be_verbose_global)
+    progress_indication (_ ("Track...") + " ");
   
   int channel = 0;
   for (vsize i = 0; i < audio_staffs_.size (); i++)
@@ -107,21 +105,7 @@ Performance::write_output (string out) const
 }
 
 
-void
-Performance::remap_grace_durations ()
-{
-  for (vsize i = 0; i < audio_elements_.size (); i++)
-    {
-      if (Audio_column * col = dynamic_cast<Audio_column*> (audio_elements_[i]))
-       {
-         col->when_.main_part_ = col->when_.main_part_ + Rational (1,4) * col->when_.grace_part_;
-         col->when_.grace_part_ = Rational (0);
-       }
-    }
-}
-
 void
 Performance::process ()
 {
-  remap_grace_durations ();
 }