]> git.donarmstrong.com Git - lilypond.git/commitdiff
Fix #87.
authorHan-Wen Nienhuys <hanwen@xs4all.nl>
Thu, 11 Jan 2007 14:47:47 +0000 (15:47 +0100)
committerHan-Wen Nienhuys <hanwen@xs4all.nl>
Thu, 11 Jan 2007 14:47:47 +0000 (15:47 +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.

Conflicts:

input/regression/midi-grace.ly
lily/include/midi-item.hh
lily/midi-item.cc
lily/note-performer.cc

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 6365305675938e91ac6741c408af402d03469bea..3a3cc5f2f8831dd0d3872e33df74571e7b369aec 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 5372aacafcd8866f3df68976275e509b07e14932..75dc5917b1051af9c00d5dda3a89ae2a6e36d380 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);
 }
 
 
@@ -114,14 +126,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 239f3f941a1c46e5aa77e82a82ec0960e6836d1a..892c678a941ab7d45546428b0e15ed628eb715a4 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 d26e567bff8e8c67fa84f0350461bea9af199918..69a0ae78d1105e39c890a5b7c9cc0f298d0e64eb 100644 (file)
@@ -121,5 +121,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 6ec530f68cfd0d1a4dd85ce495618a2f13ade476..b48049b952512809d9a7a0ad99d3ea24dee6d6e8 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_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 2d17efbc6093290576400cdb7819accec5c213e1..cb75744a92350d566ca3440261a4500e3c0053eb 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 2f1aa5bce605182ee0b32e8f51ad640c51fcd51b..69916c74ce4b9106c4729b5834519c1a657207cf 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;
@@ -246,12 +241,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
@@ -460,11 +449,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 20dfb45ef54e251d8d407ce31bfcb4a79d5f5353..d87fb557a2ceb1637f71db56f6ce4d68f398a222 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++)
@@ -65,7 +72,7 @@ Midi_walker::do_start_note (Midi_note *note)
       /* if this pith already in queue */
       if (stop_note_queue[i].val->get_pitch () == note->get_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 */
@@ -89,11 +96,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);
     }
 }
 
@@ -101,9 +108,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_)
@@ -112,10 +119,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);
     }
 }
 
@@ -123,26 +130,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))
     {
@@ -152,18 +162,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 8d9dfb44c17c4005d169d54f0cc77435bf2fc709..b21d96935d5b6a851bab0110ebded4cc07ac4287 100644 (file)
@@ -66,7 +66,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);
              Audio_element_info info (p, n);
              announce_element (info);
index 73a61767ceb0c4e95e8ffd1e2410731f86b3da40..c50c5a150d6381aea9818b3f822e809a8a83b84e 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 ();
 }