]> git.donarmstrong.com Git - lilypond.git/commitdiff
patch::: 1.5.4.jcn4
authorJan Nieuwenhuizen <janneke@gnu.org>
Sun, 12 Aug 2001 00:53:54 +0000 (02:53 +0200)
committerJan Nieuwenhuizen <janneke@gnu.org>
Sun, 12 Aug 2001 00:53:54 +0000 (02:53 +0200)
1.5.4.jcn4

33 files changed:
CHANGES
VERSION
flower/include/rational.hh
flower/rational.cc
input/regression/stem-spacing.ly
lily/auto-beam-engraver.cc
lily/bar-number-engraver.cc
lily/chord-tremolo-iterator.cc
lily/folded-repeat-iterator.cc
lily/include/moment.hh
lily/include/new-spacing-spanner.hh [new file with mode: 0644]
lily/local-key-engraver.cc
lily/midi-def.cc
lily/midi-walker.cc
lily/moment.cc
lily/multi-measure-rest-engraver.cc
lily/new-spacing-spanner.cc [new file with mode: 0644]
lily/note-heads-engraver.cc
lily/note-performer.cc
lily/percent-repeat-iterator.cc
lily/separating-group-spanner.cc
lily/separating-line-group-engraver.cc
lily/simple-spacer.cc
lily/spacing-engraver.cc
lily/spacing-spanner.cc
lily/span-dynamic-performer.cc
lily/tempo-performer.cc
lily/time-scaled-music-iterator.cc
lily/timing-translator.cc
lily/tuplet-engraver.cc
lily/unfolded-repeat-iterator.cc
scm/grob-description.scm
scm/grob-property-description.scm

diff --git a/CHANGES b/CHANGES
index d6b0577d3800d3ba39c3b674521d1dba3e945235..ad19fd996e32f7bf7cb1063174f62cf0a32ed8c7 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,8 @@
-1.5.4.jcn3
+1.5.4.jcn4
 ==========
 
+* New_spacing_spanner: revised spacing generation.
+
 * Spelling fixes, notably staffs->staves, except for ChangeLogs.
 
 * Removed `Default' from accidental comment names.
diff --git a/VERSION b/VERSION
index a05fd3fda4b8b02f909cf92af219c25ca7850d94..fead2c56c16b4d8074767d07fab456b23cc284a2 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -2,7 +2,7 @@ PACKAGE_NAME=LilyPond
 MAJOR_VERSION=1
 MINOR_VERSION=5
 PATCH_LEVEL=4
-MY_PATCH_LEVEL=jcn3
+MY_PATCH_LEVEL=jcn4
 
 # use the above to send patches: MY_PATCH_LEVEL is always empty for a
 # released version.
index 270ee5634157ce8998a9089261f1d4d864c30aff..ab4a3d41cfb862b8e83ba8942b1a3ae59e9a4024 100644 (file)
@@ -44,8 +44,8 @@ public:
   Rational div_rat (Rational) const;
   Rational mod_rat (Rational) const;
   void negate ();
-  operator bool () const;
-  operator int () const;
+  //   operator bool () const;
+  int to_int () const;
   operator double () const;
   Rational operator - () const;
   /**
index 5c3c8c5cbd6727b642d18a10bb397a37333abf1b..d5e679a9e973e0711a18ce443986f2ab51e9e9e1 100644 (file)
 #include "string-convert.hh"  
 #include "libc-extension.hh"
 
-Rational::operator bool () const
-{
-  return sign_;
-}
-
-Rational::operator int () const
-{
-  return sign_ * num_ / den_;
-}
-
 Rational::operator double () const
 {
   return (double)sign_ * num_ / den_;
index 989c43c530f68c688d6b4f39f1efa5e84427b56c..788da4fa70a17c0d01b7acbe97b5f2f7b667e5f0 100644 (file)
@@ -5,7 +5,9 @@ texidoc="
 In a limited number of cases, LilyPond corrects for optical spacing
 effects.  In this example, space for opposite pointed stems is adjuste
 "
+
 }
+
 \score { 
   \context Voice \notes\relative c {
     
@@ -15,5 +17,18 @@ effects.  In this example, space for opposite pointed stems is adjuste
   \paper {
     linewidth=-1.0
   }  
-  \midi { }
 }
+
+\score { 
+  \context Voice \notes\relative c {
+    
+       \time 12/4  c''4 c c c  a f' f, a 
+       
+  }
+  \paper {
+    linewidth=-1.0
+    \translator { \ScoreContext
+    SpacingSpanner \override #'stem-spacing-correction = #0.0
+  }  }
+}
\ No newline at end of file
index 781f03393fdf7df09676a2d4d9edf658ce6fd66e..fdd0f1e633dd91f53f30d3a1fedb14255abe5075 100644 (file)
@@ -117,7 +117,7 @@ Auto_beam_engraver::test_moment (Direction dir, Moment test_mom)
     function = gh_list (ly_symbol2scm ("end"), SCM_UNDEFINED);
 
   Moment one_beat = *unsmob_moment (get_property ("beatLength"));
-  int num = *unsmob_moment (get_property ("measureLength")) / one_beat;
+  int num = int ((*unsmob_moment (get_property ("measureLength")) / one_beat).main_part_);
   int den = one_beat.den ();
   SCM time = gh_list (gh_int2scm (num), gh_int2scm (den), SCM_UNDEFINED);
 
@@ -163,7 +163,7 @@ Auto_beam_engraver::test_moment (Direction dir, Moment test_mom)
     moment = * unsmob_moment (gh_cdr (m));
   
   Rational r;
-  if (moment)
+  if (moment.to_bool ())
     {
       /* Ugh? measurePosition can be negative, when \partial
         We may have to fix this elsewhere (timing translator)
index 48268f7a0d37b30d73398b7f78d54302d18da6f4..84646867d907f08167b1eb61a22bd1afe6171c9c 100644 (file)
@@ -49,7 +49,7 @@ Bar_number_engraver::create_grobs ()
   Moment mp = (unsmob_moment (smp)) ? *unsmob_moment (smp) : Moment (0);
   
   if (gh_number_p (bn) &&
-      !mp && now_mom () > Moment (0))
+      !mp.to_bool () && now_mom () > Moment (0))
     {
       create_items ();
 
index ea1d410b6bf2f797b15e2f98e0620c8f021dd6d7..1cfbc590d32623048437bd7acab6717f0ebdb7de 100644 (file)
@@ -39,7 +39,7 @@ Chord_tremolo_iterator::Chord_tremolo_iterator (Chord_tremolo_iterator const &sr
 void
 Chord_tremolo_iterator::process (Moment m)
 {
-  if (!m)
+  if (!m.to_bool () )
     {
       Music_iterator *yeah = try_music (music_l ());
       if (yeah)
index 3012c6642912e1e78c257b08ac6022c93a00c21e..18cfe09204d44fdd842efaea557dbd81ddfe5499 100644 (file)
@@ -71,7 +71,7 @@ Folded_repeat_iterator::construct_children ()
 void
 Folded_repeat_iterator::process (Moment m)
 {
-  if (!m)
+  if (!m.to_bool () )
     {
       bool success = try_music (music_l ());
       if (!success)
index a882bb098623e2c2bceb319db137d8344aaac5e8..9a19370e4ed7cc876ed52a269571e054ed5dd03f 100644 (file)
@@ -39,8 +39,8 @@ public:
   Rational grace_part_;
 
   void set_infinite (int k);
-  
-  operator bool ();
+
+  bool to_bool () const;
   int den () const;
   int num () const;
   /*
diff --git a/lily/include/new-spacing-spanner.hh b/lily/include/new-spacing-spanner.hh
new file mode 100644 (file)
index 0000000..0137a5c
--- /dev/null
@@ -0,0 +1,30 @@
+/*   
+  spacing-spanner.hh -- declare New_spacing_spanner
+  
+  source file of the GNU LilyPond music typesetter
+  
+  (c) 1999--2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+  
+ */
+
+#ifndef SPACING_SPANNER_HH
+#define SPACING_SPANNER_HH
+
+#include "spanner.hh"
+#include "spring.hh"
+
+class New_spacing_spanner
+{
+public:
+  static void set_interface (Grob*);
+  static void do_measure (Grob*,Link_array<Grob> const &) ;
+  static void stretch_to_regularity (Grob*, Array<Spring> *, Link_array<Grob> const &);
+  DECLARE_SCHEME_CALLBACK (set_springs, (SCM ));
+  static Real stem_dir_correction (Grob*,Grob*,Grob*)  ;
+  static Real default_bar_spacing (Grob*,Grob*,Grob*,Moment)  ;
+  static Real note_spacing (Grob*,Grob*,Grob*,Moment)  ;
+  static Real get_duration_space (Grob*,Moment dur, Moment shortest) ;
+};
+
+#endif /* SPACING_SPANNER_HH */
+
index fb491fdf4c00743a55f5920bea3be7bc63aeb18b..ed71c533773a215e1f84ec607fced5b9577bc72a 100644 (file)
@@ -277,7 +277,7 @@ Local_key_engraver::process_music ()
       daddy_trans_l_->set_property ("localKeySignature",  ly_deep_copy (sig));
       last_keysig_ = sig;
     }
-  else if (!mp)
+  else if (!mp.to_bool () )
     {
       if (!to_boolean (get_property ("noResetKey")))
        daddy_trans_l_->set_property ("localKeySignature",  ly_deep_copy (sig));
index 20174ca73fd7101495d8d38188dd286eec39b951..6f3a2cd642e62fcade2be97c4216df40dc757d70 100644 (file)
@@ -24,7 +24,7 @@ Midi_def::get_tempo_i (Moment one_beat_mom)
 {
   Moment w = *unsmob_moment (scope_p_->scm_elem ("whole-in-seconds"));
   Moment wholes_per_min = Moment (60) /w;
-  int beats_per_min = wholes_per_min / one_beat_mom;
+  int beats_per_min =  int ((wholes_per_min / one_beat_mom).main_part_);
   return int (beats_per_min);
 }
 
index 078dada743f831413de56619228b29de5eafff8b..17548174b49d48161037100ee54cf3352b745bee 100644 (file)
@@ -23,7 +23,14 @@ Midi_note_event::Midi_note_event ()
 int
 compare (Midi_note_event const& left, Midi_note_event const& right)
 {
-  return sign (left.key - right.key);
+  Moment m =   (left.key - right.key);
+
+  if (m<0)
+    return -1;
+  else if (m > 0)
+    return 1;
+  else
+    return 0;
 }
 
 Midi_walker::Midi_walker (Audio_staff* audio_staff_l, Midi_track* track_l)
@@ -144,7 +151,7 @@ Midi_walker::process ()
       //midi_p->channel_i_ = track_l_->number_i_;
       if (Midi_note* note_p = dynamic_cast<Midi_note*> (midi_p))
        {
-         if (note_p->length_mom ())
+         if (note_p->length_mom ().to_bool ())
            do_start_note (note_p);
        }
       else
index 5a3ff5f8fc238924fcd20f4dd7dd976d6b7d4afa..1f7f62e77384cd74b5c1331537b2f5a2bbda5856 100644 (file)
@@ -171,8 +171,8 @@ Moment::den () const { return main_part_.den (); }
 int
 Moment::num () const { return main_part_.num (); }
 
-
-Moment::operator bool ()
+bool
+Moment::to_bool () const
 {
   return main_part_ || grace_part_;
 }
index bd66558dad2f112b65f74ea9262067533c32d4d4..21c205532495045df4467a20ab6cb4d7e44990ac 100644 (file)
@@ -127,7 +127,7 @@ Multi_measure_rest_engraver::stop_translation_timestep ()
   Moment mp = (unsmob_moment (smp)) ? *unsmob_moment (smp) : Moment (0);
 
   if (mmrest_p_ && (now_mom () >= start_moment_) 
-      && !mp
+      && !mp.to_bool ()
       && mmrest_p_->get_bound (LEFT) && mmrest_p_->get_bound (RIGHT))
     {
       typeset_grob (mmrest_p_);
@@ -160,7 +160,7 @@ Multi_measure_rest_engraver::start_translation_timestep ()
   SCM smp = get_property ("measurePosition");
   Moment mp = (unsmob_moment (smp)) ? *unsmob_moment (smp) : Moment (0);
   
-  if (mmrest_p_ && !mp)
+  if (mmrest_p_ && !mp.to_bool ())
     {
       lastrest_p_ = mmrest_p_;
       int cur = gh_scm2int (get_property ("currentBarNumber"));
diff --git a/lily/new-spacing-spanner.cc b/lily/new-spacing-spanner.cc
new file mode 100644 (file)
index 0000000..009dd0f
--- /dev/null
@@ -0,0 +1,510 @@
+/*   
+  spacing-spanner.cc --  implement Spacing_spanner
+  
+  source file of the GNU LilyPond music typesetter
+  
+  (c) 1999--2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+  
+ */
+
+#include "new-spacing-spanner.hh"
+#include "paper-column.hh"
+#include "dimensions.hh"
+#include "paper-def.hh"
+#include "warn.hh"
+#include "paper-score.hh"
+#include "line-of-score.hh"
+#include "misc.hh"
+#include "separation-item.hh"
+
+
+void
+New_spacing_spanner::set_interface (Grob*me)
+{
+  me->set_extent_callback (SCM_EOL, X_AXIS);
+  me->set_extent_callback (SCM_EOL, Y_AXIS) ; 
+}
+
+/*
+
+  The algorithm is partly taken from :
+
+  John S. Gourlay. ``Spacing a Line of Music,'' Technical Report
+  OSU-CISRC-10/87-TR35, Department of Computer and Information
+  Science, The Ohio State University, 1987.
+
+  TOO HAIRY.
+
+  TODO: write comments 
+  
+ */
+void
+New_spacing_spanner::do_measure (Grob*me, Link_array<Grob> const & cols) 
+{
+  Moment shortest;
+  Moment mean_shortest;
+
+  /*
+    space as if this duration  is present. 
+   */
+  Moment base_shortest_duration = *unsmob_moment (me->get_grob_property ("maximum-duration-for-spacing"));
+  shortest.set_infinite (1);
+
+  int n = 0;
+  for (int i =0 ; i < cols.size (); i++)  
+    {
+      if (Paper_column::musical_b (cols[i]))
+       {
+         Moment *when = unsmob_moment (cols[i]->get_grob_property  ("when"));
+
+         /*
+           ignore grace notes for shortest notes.
+          */
+         if (when && when->grace_part_)
+           continue;
+         
+         SCM  st = cols[i]->get_grob_property ("shortest-starter-duration");
+         Moment this_shortest = *unsmob_moment (st);
+         shortest = shortest <? this_shortest;
+         if (!mean_shortest.main_part_.infty_b ())
+           {
+             n++;
+             mean_shortest += this_shortest;
+           }
+       }
+    }
+  
+  Array<Spring> springs;
+
+  Item * first_col = 0;
+  Item * last_col = 0;
+  
+  for (int i= 0; i < cols.size () - 1; i++)
+    {
+      Item * l = dynamic_cast<Item*> (cols[i]);
+
+      if (!Paper_column::musical_b (l))
+       continue ;
+
+      if (!first_col)
+       first_col = l;
+      
+      last_col = l;
+      int j = i+1;
+      for (; j < cols.size () -1 ; j++)
+       if (Paper_column::musical_b (cols[j]))
+         break ;
+      
+      Item * r =  dynamic_cast<Item*> (cols[j]);
+      Paper_column * lc = dynamic_cast<Paper_column*> (l);
+      Paper_column *rc = dynamic_cast<Paper_column*> (r);
+      if (!lc || !rc)
+       continue;
+
+      Real note_space = note_spacing (me,lc, rc, shortest <? base_shortest_duration);
+      Real hinterfleisch = note_space;
+      Real headwid = gh_scm2double (me->get_grob_property ("arithmetic-multiplier"));
+      
+      for (SCM s = lc->get_grob_property ("spacing-sequence"); gh_pair_p (s); s = gh_cdr (s))
+       {
+         Grob *lm = unsmob_grob (gh_caar (s));
+         Grob *rm = unsmob_grob (gh_cdar (s));
+
+         // TODO; configgable.
+         hinterfleisch += -headwid + Separation_item::my_width (lm)[RIGHT] -
+           0.5 * Separation_item::my_width (rm)[LEFT];
+
+
+         /*
+           UGH: KLUDGE!
+         */
+         
+         //      if (delta_t > Moment (1,32))
+         hinterfleisch += stem_dir_correction (me, l, r);
+       }
+
+      Real stretch_distance = note_space - headwid;
+      Spring s;
+      s.distance_f_ = hinterfleisch;
+      s.strength_f_ = 1 / stretch_distance;
+
+      s.item_l_drul_[LEFT] = l;
+      s.item_l_drul_[RIGHT] = r;
+
+      s.add_to_cols();
+      if (r->find_prebroken_piece (LEFT))
+       {
+         s.item_l_drul_[RIGHT] = r->find_prebroken_piece(LEFT);
+         s.add_to_cols();
+       }
+    }
+
+  Item * l = dynamic_cast<Item*> (cols[0])->find_prebroken_piece (RIGHT);
+
+  /*
+    TODO read different spacing hints from break-alignment.
+   */
+  Spring s;
+
+  Real break_dist = 0.0;
+  SCM espace = l->get_grob_property ("extra-space");
+  if (gh_pair_p (espace))
+    break_dist += gh_scm2double (gh_cdr (espace));
+
+  if (!break_dist)
+    break_dist = 1.0;
+
+  Real break_stretch = 0.0;
+
+  // todo: naming of "distance"
+  espace = l->get_grob_property ("stretch-distance");
+  if (gh_pair_p (espace))
+    break_stretch += gh_scm2double (gh_cdr (espace));
+
+  if (!break_stretch)
+    break_stretch = 1.0;
+  
+  s.distance_f_ = break_dist;
+  s.strength_f_ = 1/break_stretch;
+  s.item_l_drul_[LEFT] = l;
+  s.item_l_drul_[RIGHT] = first_col;
+
+  s.add_to_cols ();
+
+  s.item_l_drul_[LEFT] = dynamic_cast<Item*>(cols[0]);
+  s.add_to_cols ();
+}
+
+/*
+  Look at COLS, searching for columns that have 'regular-distance-to
+  set. A sequence of columns that have this property set should have
+  an equal distance (an equispaced run). Extract the projected
+  distance from SPRINGS, and scale SPRINGS for the equispaced run, to the
+  widest space necessary.
+
+
+  TODO:
+  
+  -- inefficient code; maybe it is easier to twiddle with the springs
+  after they've become grob properties (ie. have their
+  minimum-distances set)
+
+  -- does not adjust strength field of the springs very well: result
+  awkward spacing at the start of a line. (?)
+
+  -- will be confused when there are multiple equispaced runs in a measure.
+
+  -- dealing with springs for line breaks is a little tricky; in any
+  case, we will only space per measure.
+
+  -- we scale to actual distances, not to optical effects. Eg. if the
+  equispaced run contains optical corrections, then the scaling will
+  cancel those.
+
+  -- Regular_spacing_engraver doesn't mark the first column of the
+  next bar, making the space before a barline too short, in this case
+
+
+       x<- 16ths--> x(8th)
+       x(8th)       x(8th)      <- equispaced run.      
+  
+*/
+
+void
+New_spacing_spanner::stretch_to_regularity (Grob *me,
+                                       Array<Spring> * springs,
+                                       Link_array<Grob> const & cols)
+{
+  /*
+    Find the starting column of the run. REGULAR-DISTANCE-TO points
+    back to a previous column, so we look ahead to find a column
+    pointing back to the first one.
+    
+   */
+  Grob    * first_regular_spaced_col = 0;
+  for (int i = 0 ;  i <  cols.size () && !first_regular_spaced_col; i++)
+    {
+      SCM rdt = cols[i]->get_grob_property ("regular-distance-to");
+      if (cols.find_l (unsmob_grob (rdt)))
+       first_regular_spaced_col = unsmob_grob (rdt);
+    }
+  for (int i = springs->size ();  i-- ;)
+    springs->elem (i).set_to_cols ();
+  
+  int i;
+  for (i = 0; i < springs->size ()
+        && springs->elem (i).item_l_drul_[RIGHT] != first_regular_spaced_col;
+       i++)
+    ;
+
+
+  if (i==springs->size ())
+    return ;
+    
+  Real maxdist = 0.0;
+  Real dist  =0.0;
+  Grob *last_col = first_regular_spaced_col;
+  Grob *last_regular_spaced_col = first_regular_spaced_col;
+  
+
+  /*
+    find the max distance for this run. 
+   */
+  for (int j = i;  j < springs->size (); j++)
+    {
+      Spring *s = &(springs->elem_ref (j));
+      if (s->item_l_drul_[LEFT] != last_col)
+       continue;
+      
+      dist += s->distance_f_;
+
+      last_col = s->item_l_drul_[RIGHT];
+      SCM rdt = last_col->get_grob_property ("regular-distance-to");
+      if (unsmob_grob (rdt) == last_regular_spaced_col)
+       {
+         maxdist = maxdist >? dist;
+         dist = 0.0;
+         last_regular_spaced_col = last_col;
+       }
+
+    }
+
+  /*
+    Scale the springs
+   */
+  dist =0.0;
+  last_col =  first_regular_spaced_col;
+  last_regular_spaced_col = first_regular_spaced_col;
+  for (int j = i;   j < springs->size (); j++)
+    {
+      Spring *s = &springs->elem_ref (j);
+      if (s->item_l_drul_[LEFT] != last_col)
+       continue;
+      dist += s->distance_f_;
+
+      last_col = s->item_l_drul_[RIGHT];
+      SCM rdt = last_col->get_grob_property ("regular-distance-to");
+      if (unsmob_grob (rdt) == last_regular_spaced_col)
+       {
+         do {
+           springs->elem_ref (i).distance_f_ *= maxdist / dist;
+           springs->elem_ref (i).strength_f_ *= dist / maxdist;            
+         } while (i++ < j);
+         last_regular_spaced_col = last_col;
+         dist =0.0;
+       }
+    }
+}
+
+/**
+   Do something if breakable column has no spacing hints set.
+ */
+Real
+New_spacing_spanner::default_bar_spacing (Grob*me, Grob *lc, Grob *rc,
+                                     Moment shortest) 
+{
+  Real symbol_distance = lc->extent (lc,X_AXIS)[RIGHT] ;
+  Real durational_distance = 0;
+  Moment delta_t = Paper_column::when_mom (rc) - Paper_column::when_mom (lc);
+
+  /*
+               ugh should use shortest_playing distance
+  */
+  if (delta_t.to_bool ())
+    {
+      durational_distance =  get_duration_space (me, delta_t, shortest);
+    }
+
+  return  symbol_distance >? durational_distance;
+}
+
+
+/**
+  Get the measure wide ant for arithmetic spacing.
+
+  @see
+  John S. Gourlay. ``Spacing a Line of Music,'' Technical Report
+  OSU-CISRC-10/87-TR35, Department of Computer and Information Science,
+  The Ohio State University, 1987.
+
+  */
+Real
+New_spacing_spanner::get_duration_space (Grob*me, Moment d, Moment shortest) 
+{
+  Real log =  log_2 (shortest.main_part_);
+  Real k = gh_scm2double (me->get_grob_property ("arithmetic-basicspace"))
+    - log;
+
+  Rational compdur = d.main_part_ + d.grace_part_ /Rational (3);
+  
+  return (log_2 (compdur) + k) * gh_scm2double (me->get_grob_property ("arithmetic-multiplier"));
+}
+
+
+Real
+New_spacing_spanner::note_spacing (Grob*me, Grob *lc, Grob *rc,
+                              Moment shortest) 
+{
+  Moment shortest_playing_len = 0;
+  SCM s = lc->get_grob_property ("shortest-playing-duration");
+
+  //  SCM s = lc->get_grob_property ("mean-playing-duration");  
+  if (unsmob_moment (s))
+    shortest_playing_len = *unsmob_moment (s);
+  
+  if (! shortest_playing_len.to_bool ())
+    {
+      programming_error ("can't find a ruling note at " + Paper_column::when_mom (lc).str ());
+      shortest_playing_len = 1;
+    }
+  
+  if (! shortest.to_bool ())
+    {
+      programming_error ("no minimum in measure at " + Paper_column::when_mom (lc).str ());
+      shortest = 1;
+    }
+  Moment delta_t = Paper_column::when_mom (rc) - Paper_column::when_mom (lc);
+  Real dist = get_duration_space (me, shortest_playing_len, shortest);
+
+
+  /*
+    ugh: 0.1 is an arbitrary distance.
+   */
+  dist *= (double) (delta_t.main_part_ / shortest_playing_len.main_part_)
+    + 0.1 * (double) (delta_t.grace_part_ / shortest_playing_len.main_part_);
+
+
+
+  Moment *lm = unsmob_moment (lc->get_grob_property ("when"));
+  Moment *rm = unsmob_moment (rc->get_grob_property ("when"));
+
+  if (lm && rm)
+    {
+      if (lm->grace_part_ && rm->grace_part_)
+       dist *= 0.5;
+      else if (!rm->grace_part_ && lm->grace_part_)
+       dist *= 0.7;
+    }
+
+  
+  return dist;
+}
+
+
+/**
+   Correct for optical illusions. See [Wanske] p. 138. The combination
+   up-stem + down-stem should get extra space, the combination
+   down-stem + up-stem less.
+
+   This should be more advanced, since relative heights of the note
+   heads also influence required correction.
+
+   Also might not work correctly in case of multi voices or staff
+   changing voices
+
+   TODO: lookup correction distances?  More advanced correction?
+   Possibly turn this off?
+
+   TODO: have to check wether the stems are in the same staff.
+
+   This routine reads the DIR-LIST property of both its L and R arguments.  */
+Real
+New_spacing_spanner::stem_dir_correction (Grob*me, Grob*l, Grob*r) 
+{
+  SCM dl = l->get_grob_property ("dir-list");
+  SCM dr = r->get_grob_property ("dir-list");
+  
+  if (scm_ilength (dl) != 1 || scm_ilength (dr) != 1)
+    return 0.;
+
+  dl = gh_car (dl);
+  dr = gh_car (dr);
+
+  assert (gh_number_p (dl) && gh_number_p (dr));
+  int d1 = gh_scm2int (dl);
+  int d2 = gh_scm2int (dr);
+
+  if (d1 == d2)
+    return 0.0;
+
+
+  Real correction = 0.0;
+  Real ssc = gh_scm2double (me->get_grob_property ("stem-spacing-correction"));
+
+  if (d1 && d2 && d1 * d2 == -1)
+    {
+      correction = d1 * ssc;
+    }
+  else
+    programming_error ("Stem directions not set correctly for optical correction");
+  return correction;
+}
+  
+
+MAKE_SCHEME_CALLBACK (New_spacing_spanner, set_springs,1);
+SCM
+New_spacing_spanner::set_springs (SCM smob)
+{
+  Grob *me = unsmob_grob (smob);
+  Link_array<Grob> all (me->pscore_l_->line_l_->column_l_arr ()) ;
+
+  int j = 0;
+
+  for (int i = 1; i < all.size (); i++)
+    {
+      Grob *sc = all[i];
+      if (Item::breakable_b (sc))
+        {
+         Link_array<Grob> measure (all.slice (j, i+1));          
+          do_measure (me, measure);
+         j = i;
+        }
+    }
+
+  /*
+    farewell, cruel world
+   */
+  me->suicide ();
+  return SCM_UNSPECIFIED;
+}
+
+
+
+/*
+  maximum-duration-for-spacing
+From: bf250@freenet.carleton.ca (John Sankey)
+To: gnu-music-discuss@gnu.org
+Subject: note spacing suggestion
+Date: Mon, 10 Jul 2000 11:28:03 -0400 (EDT)
+
+Currently, Lily spaces notes by starting with a basic distance,
+arithmetic_multiplier, which it applies to the minimum duration note
+of the bar. Then she adds a logarithmic increment, scaled from
+arithmetic_basicspace, for longer notes. (Then, columns are aligned
+and justified.) Fundamentally, this matches visual spacing to musical
+weight and works well.
+
+A lot of the time in music, I see a section basically in melodic
+notes that occasionally has a rapid ornamental run (scale). So, there
+will be a section in 1/4 notes, then a brief passage in 1/32nds, then
+a return to long notes. Currently, Lily gives the same horizontal
+space to the 1/32nd notes in their bar (even if set in small size as
+is commonly done for cadenzii) as she gives to 1/4 notes in bars
+where 1/4 note is the minimum duration. The resulting visual weight
+does not match the musical weight over the page.
+
+Looking at the music I am typesetting, I feel that Lily's spacing
+could be significantly improved if, with no change in the basic
+method used, arithmetic_multiplier could be applied referred to the
+same duration throughout a piece. Of course, the current method
+should be retained for those who have already set music in it, so I
+suggest a property called something like arithmetic_base=16 to fix
+1/16 duration as the reference for arithmetic_multiplier; the default
+would be a dynamic base is it is now.
+
+Does anyone else feel that this would be a useful improvement for
+their music? (Of course, if arithmetic_multiplier became a regular
+property, this could be used to achieve a similar result by
+tweaking.)
+  
+ */
index 87a5bff3f2d5a82fbe03c311aa907eef9b08a692..69d16f6c6714251134fc8333edb97a9d757760e7 100644 (file)
@@ -21,6 +21,7 @@
 class Note_heads_engraver : public Engraver
 {
   Link_array<Item> note_p_arr_;
+  
   Link_array<Item> dot_p_arr_;
   Link_array<Note_req> note_req_l_arr_;
   Moment note_end_mom_;
index c2665f5495b8fc680e5e25a74114eebf0edef2ea..c5c522405a6d1d32efe956ebc670c7a9ce938127 100644 (file)
@@ -85,7 +85,8 @@ Note_performer::stop_translation_timestep ()
   for (int i=0; i < note_p_arr_.size (); i++)
     {
       Audio_note* n = note_p_arr_[i];
-      if (Moment m= n->delayed_until_mom_)
+      Moment m= n->delayed_until_mom_;
+      if (m.to_bool ())
        {
          global_l->add_moment_to_process (m);
          delayed_p_arr_.push (n);
index 3d1120981b578146a4e1de32cade848101b9feaa..48a81ebe4ddf737f2ddbe6b0b9b790b443d61c24 100644 (file)
@@ -44,7 +44,7 @@ Percent_repeat_iterator::construct_children ()
 void
 Percent_repeat_iterator::process (Moment m)
 {
-  if (!m)
+  if (!m.to_bool ())
     {
       Music_iterator *yeah = try_music (music_l ());
       if (yeah)
index bc5e030994bd1404c465ac22bd4b2ee433a40fc3..d102e35bdb4c36945d71eb7424d673c5ceab69a9 100644 (file)
@@ -96,6 +96,10 @@ Separating_group_spanner::set_spacing_rods (SCM smob)
        find_rods (rb, gh_cdr (s));
     }
 
+#if 0
+  /*
+    TODO; restore this.
+   */
   /*
     We've done our job, so we get lost. 
    */
@@ -110,6 +114,7 @@ Separating_group_spanner::set_spacing_rods (SCM smob)
       it->suicide ();
     }
   me->suicide ();
+#endif
   return SCM_UNSPECIFIED ;
 }
 
index 73e0f2e16070f2f85ccbc11a3b081552e2c9f3d6..5ac89108964b20cb48853902c5d23a9da64c5b3a 100644 (file)
@@ -18,7 +18,14 @@ class Separating_line_group_engraver : public Engraver
 {
 protected:
   Item * break_malt_p_;
-  Item * nobreak_malt_p_;
+  Item * musical_malt_p_;
+
+  /*
+    malt_p_ : we used to have a Single_malt_grouping_item
+    
+   */
+  Item * last_step_musical_malt_p_;
+  
   Spanner * sep_span_p_;
   
   virtual void acknowledge_grob (Grob_info);
@@ -32,9 +39,10 @@ public:
 
 Separating_line_group_engraver::Separating_line_group_engraver ()
 {
+  last_step_musical_malt_p_ = 0;
   sep_span_p_ = 0;
   break_malt_p_ = 0;
-  nobreak_malt_p_ =0;
+  musical_malt_p_ =0;
 }
 
 void
@@ -68,7 +76,7 @@ Separating_line_group_engraver::acknowledge_grob (Grob_info i)
   
   bool ib =Item::breakable_b (it);
   Item *&p_ref_ (ib ? break_malt_p_
-                : nobreak_malt_p_);
+                : musical_malt_p_);
 
   if (!p_ref_)
     {
@@ -92,12 +100,26 @@ Separating_line_group_engraver::stop_translation_timestep ()
       typeset_grob (break_malt_p_);
       break_malt_p_ =0;
     }
-  if (nobreak_malt_p_)
+  if (musical_malt_p_)
     {
-      Separating_group_spanner::add_spacing_unit (sep_span_p_, nobreak_malt_p_);
-      typeset_grob (nobreak_malt_p_);
-      nobreak_malt_p_ =0;
+      Separating_group_spanner::add_spacing_unit (sep_span_p_, musical_malt_p_);
+
+      if (last_step_musical_malt_p_)
+       {
+         Paper_column *col = 
+           last_step_musical_malt_p_->column_l();
+         SCM newtup = gh_cons (last_step_musical_malt_p_->self_scm (),
+                               musical_malt_p_->self_scm ());
+         col->set_grob_property ("spacing-sequence",
+                                 gh_cons (newtup,
+                                          col->get_grob_property ("spacing-sequence")));
+       }
+      
+      typeset_grob (musical_malt_p_);
     }
+  last_step_musical_malt_p_ = musical_malt_p_;
+  musical_malt_p_ =0;
+
 }
 
 
index 2b9bbdde8348a4e74f4f6f34afd3249e4de0163a..0340596ad3b0168e01be82028e209f3a79143165 100644 (file)
@@ -189,7 +189,9 @@ Simple_spacer::add_columns (Link_array<Grob> cols)
        }
       else
        {
-         programming_error ("No spring between adjacent columns");
+         programming_error (_f("No spring between column %d and next one",
+                               Paper_column::rank_i (cols[i])
+                               ));
          desc.hooke_f_ = 1.0;
          desc.ideal_f_ = default_space_f_;
        }
index edeb8ebb9eac696725e4fe49d3277cc953b42327..198080648d046c4d83a963a1b6561b16b4e3d932 100644 (file)
@@ -111,7 +111,7 @@ Spacing_engraver::stop_translation_timestep ()
   for (int i=0; i < playing_durations_.size (); i++)
     {
       Moment m = (playing_durations_[i].info_.req_l_)->length_mom ();
-      if (m)
+      if (m.to_bool ())
        {
          shortest_playing = shortest_playing <? m;
        }
@@ -123,7 +123,7 @@ Spacing_engraver::stop_translation_timestep ()
   for (int i=0; i < now_durations_.size (); i++)
     {
       Moment m = now_durations_[i].info_.req_l_->length_mom ();
-      if (m)
+      if (m.to_bool ())
        starter = starter <? m;
 
       playing_durations_.insert (now_durations_[i]);
index 636757b94d611417921ce30880521fbb6d5f0b24..e5a519f1ea9e2e5914df4346e4e486ab431ed7ff 100644 (file)
@@ -410,7 +410,7 @@ Spacing_spanner::default_bar_spacing (Grob*me, Grob *lc, Grob *rc,
   /*
                ugh should use shortest_playing distance
   */
-  if (delta_t)
+  if (delta_t.to_bool ())
     {
       durational_distance =  get_duration_space (me, delta_t, shortest);
     }
@@ -431,11 +431,12 @@ Spacing_spanner::default_bar_spacing (Grob*me, Grob *lc, Grob *rc,
 Real
 Spacing_spanner::get_duration_space (Grob*me, Moment d, Moment shortest) 
 {
-  Real log =  log_2 (shortest);
+  Real log =  log_2 (shortest.main_part_);
   Real k = gh_scm2double (me->get_grob_property ("arithmetic-basicspace"))
     - log;
-  
-  return (log_2 (d) + k) * gh_scm2double (me->get_grob_property ("arithmetic-multiplier"));
+
+  Rational compdur = d.main_part_  + d.grace_part_ / Rational (3);
+  return (log_2 (compdur) + k) * gh_scm2double (me->get_grob_property ("arithmetic-multiplier"));
 }
 
 
@@ -450,13 +451,13 @@ Spacing_spanner::note_spacing (Grob*me, Grob *lc, Grob *rc,
   if (unsmob_moment (s))
     shortest_playing_len = *unsmob_moment (s);
   
-  if (! shortest_playing_len)
+  if (! shortest_playing_len.to_bool ())
     {
       programming_error ("can't find a ruling note at " + Paper_column::when_mom (lc).str ());
       shortest_playing_len = 1;
     }
   
-  if (! shortest)
+  if (! shortest.to_bool ())
     {
       programming_error ("no minimum in measure at " + Paper_column::when_mom (lc).str ());
       shortest = 1;
index 7276bd6c702b43f08d2800be2a2df4a941af5d91..f76f7a88764ec641e8a718ea78ab28122cd44b71 100644 (file)
@@ -153,8 +153,8 @@ Span_dynamic_performer::stop_translation_timestep ()
       for (int i=0; i < finished_dynamic_tuple_arr_.size (); i++)
        {
          Audio_dynamic_tuple* a = &finished_dynamic_tuple_arr_[i];
-         Real volume = start_volume + dv * (Real) (a->mom_ - start_mom)
-           / (Real)dt;
+         Real volume = start_volume + dv * (Real) (a->mom_ - start_mom).main_part_
+           / (Real)dt.main_part_;
          a->audio_l_->volume_ = volume;
        }
       finished_dynamic_tuple_arr_.clear ();
index 53ca7c056ce7ee8dfbc65f1dad821664882f1b84..f24dd0f8aab44cac0028e0a25476851fefe8f645 100644 (file)
@@ -51,9 +51,9 @@ Tempo_performer::create_audio_elements ()
       SCM met = tempo_req_l_->get_mus_property ("metronome-count");
       Duration *d = unsmob_duration (tempo_req_l_->get_mus_property ("duration"));
       
-      audio_p_ = new Audio_tempo (d->length_mom () /
-                                 Moment (1, 4) 
-                                 * Moment (gh_scm2int (met)));
+      Rational r =  (d->length_mom () / Moment (1, 4) * Moment (gh_scm2int (met))).main_part_;
+      
+      audio_p_ = new Audio_tempo (int (r));
 
       Audio_element_info info (audio_p_, tempo_req_l_);
       announce_element (info);
index b666f766bd929659016df64acd405407b211ad30..df242b03ff2a99ae22eeebea597d0cd53ee2e4d2 100644 (file)
@@ -16,7 +16,7 @@
 void
 Time_scaled_music_iterator::process (Moment m)
 {
-  if (!m)
+  if (!m.to_bool ())
     {
       Music_iterator *yeah = try_music (music_l ());
       if (yeah)
index dbe365e11c2c81f3001d09150464c6df75b57ca5..d90e93cec7da8aa322edb4aaf747de8722f9fc31 100644 (file)
@@ -141,7 +141,7 @@ Timing_translator::start_translation_timestep ()
       dt = 0;
     }
   
-  if (!dt)
+  if (!dt.to_bool ())
     return;
 
   Moment measposp;
index 65b38e8a48fe01f9456b7df1adf96c08d779ffd0..453d958b37b7647ae2286535a2272a5a0c9d14dc 100644 (file)
@@ -124,7 +124,7 @@ Tuplet_engraver::start_translation_timestep ()
              started_span_p_arr_[i] =0;
            }
          
-         if (tsd)
+         if (tsd.to_bool ())
            span_stop_moments_[i] += tsd.main_part_;
        }
 
index 56c6195aed0864c6da2c0528019674d6f0232ee5..73343eee83af721a4af3e01c9866b6a22f9d3017 100644 (file)
@@ -303,7 +303,7 @@ Unfolded_repeat_iterator::add_repeat_command (SCM what)
 void
 Unfolded_repeat_iterator::process (Moment m) 
 {
-  if (!m)
+  if (!m.to_bool ())
     {
       if (volta_b_)
        add_repeat_command (ly_symbol2scm ("start-repeat"));
index 916afa7884afdfaf0e1366fd1a13e214543208d4..a66b6ddadc405275395e6dc327e7d2081edd2d9c 100644 (file)
                 ))
              
        (SpacingSpanner . (
-               (spacing-procedure . ,Spacing_spanner::set_springs)
+               (spacing-procedure . ,New_spacing_spanner::set_springs)
                (stem-spacing-correction . 0.5)
+
+
+               ;; TODO: change naming -- unintuitive
                (arithmetic-basicspace . 2.0)
                (arithmetic-multiplier . ,(* 0.9 1.32))
                ;; assume that notes at least this long are present.
index a20fc98a6adfccc306f75eb08b49808b15a11080..ae582e5b886b1ec0c561bf12349dcf86dab571e7 100644 (file)
@@ -273,7 +273,7 @@ itself.  Return value is ignored.")
 (grob-property-description 'stem-end-position number? "Where does the stem end (the end is opposite to the support-head.")
 (grob-property-description 'stem-length number? "length of stem.")
 (grob-property-description 'stem-shorten list? "shorten stems in forced directions given flag multiplicity.")
-(grob-property-description 'stem-spacing-correction number? "optical correction amount.")
+(grob-property-description 'stem-spacing-correction number? "optical correction amount.  [TODO: doco] ")
 (grob-property-description 'stems list? "list of stem objects, corresponding to the notes that the arpeggio has to be before.")
 (grob-property-description 'stretch-distance number-pair? "pair of distances.")
 (grob-property-description 'style symbol? "a string determining what style of  glyph is typeset. Valid choices depend on the function that is reading this property. .")