]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/chord.cc
patch::: 1.3.47.jcn3
[lilypond.git] / lily / chord.cc
index adef8d4991c5e2f35ab1edd645515c788a6b3212..8a524f0110d163dd30079599c04e6820aa8e8dc9 100644 (file)
@@ -3,12 +3,16 @@
 
   source file of the GNU LilyPond music typesetter
 
-  (c)  1999 Jan Nieuwenhuizen <janneke@gnu.org>
+  (c)  1999--2000 Jan Nieuwenhuizen <janneke@gnu.org>
 */
 
 #include "chord.hh"
 #include "musical-request.hh"
 #include "warn.hh"
+#include "debug.hh"
+#include "molecule.hh"
+#include "paper-def.hh"
+#include "lookup.hh"
 
 
 /*
@@ -17,7 +21,7 @@
 Chord
 to_chord (Musical_pitch tonic, Array<Musical_pitch>* add_arr_p, Array<Musical_pitch>* sub_arr_p, Musical_pitch* inversion_p, Musical_pitch* bass_p)
 {
-  // urg: catch dim modifier: 5th and 7th should be lowered
+  // urg: catch dim modifier: 3rd, 5th, 7th, .. should be lowered
   bool dim_b = false;
   for (int i=0; i < add_arr_p->size (); i++)
     {
@@ -28,12 +32,10 @@ to_chord (Musical_pitch tonic, Array<Musical_pitch>* add_arr_p, Array<Musical_pi
          dim_b = true;
        }
     }
-  Chord::rebuild_transpose (add_arr_p, tonic);
-  Chord::rebuild_transpose (sub_arr_p, tonic);
+  Chord::rebuild_transpose (add_arr_p, tonic, true);
+  Chord::rebuild_transpose (sub_arr_p, tonic, true);
 
-  Musical_pitch fifth = tonic;
-  fifth.transpose (Musical_pitch (2));
-  fifth.transpose (Musical_pitch (2, -1));
+  Musical_pitch fifth = Chord::base_arr (tonic).top ();
 
   /*
     remove double adds (urg: sus4)
@@ -68,19 +70,21 @@ to_chord (Musical_pitch tonic, Array<Musical_pitch>* add_arr_p, Array<Musical_pi
   if (highest_step < 5)
     missing_arr.push (fifth);
 
+  /*
+    if dim modifier is given: lower all missing
+   */
   if (dim_b)
     {
       for (int i=0; i < missing_arr.size (); i++)
         {
-          missing_arr[i].accidental_i_--;
+         missing_arr[i].accidental_i_--;
        }
     }
 
   /*
     if additions include some 3, don't add third
    */
-  Musical_pitch third = tonic;
-  third.transpose (Musical_pitch (2));
+  Musical_pitch third = Chord::base_arr (tonic)[1];
   if (Chord::find_notename_i (add_arr_p, third) != -1)
     {
       int i = Chord::find_pitch_i (&missing_arr, third);
@@ -192,37 +196,64 @@ to_chord (Array<Musical_pitch> pitch_arr, Tonic_req* tonic_req, Inversion_req* i
   return Chord (pitch_arr, inversion_p, bass_p);
 }
 
+Chord::Chord ()
+{
+  inversion_b_ = false;
+  bass_b_ = false;
+}
+
 Chord::Chord (Array<Musical_pitch> pitch_arr, Musical_pitch* inversion_p, Musical_pitch* bass_p)
 {
   pitch_arr_ = pitch_arr;
-  inversion_p_ = inversion_p;
-  bass_p_ = bass_p;
+  inversion_b_ = false;
+  bass_b_ = false;
+  if (inversion_p)
+    {
+      inversion_pitch_ = *inversion_p;
+      inversion_b_ = true;
+      delete inversion_p;
+    }
+  if (bass_p)
+    {
+      bass_pitch_ = *bass_p;
+      bass_b_ = true;
+      delete bass_p;
+    }
 }
-
+  
 Chord::Chord (Chord const& chord)
 {
   pitch_arr_ = chord.pitch_arr_;
-  inversion_p_ = chord.inversion_p_ ? new Musical_pitch (*chord.inversion_p_) : 0;
-  bass_p_ = chord.bass_p_ ? new Musical_pitch (*chord.bass_p_) : 0;
+  inversion_b_ = chord.inversion_b_;
+  inversion_pitch_ = chord.inversion_pitch_;
+  bass_b_ = chord.bass_b_;
+  bass_pitch_ = chord.bass_pitch_;
 }
+  
 
-Chord::~Chord ()
+Array<Musical_pitch>
+Chord::base_arr (Musical_pitch p)
 {
-  delete inversion_p_;
-  delete bass_p_;
+  Array<Musical_pitch> base;
+  base.push (p);
+  p.transpose (Musical_pitch (2));
+  base.push (p);
+  p.transpose (Musical_pitch (2, -1));
+  base.push (p);
+  return base;
 }
 
 void
-Chord::rebuild_transpose (Array<Musical_pitch>* pitch_arr_p, Musical_pitch tonic)
+Chord::rebuild_transpose (Array<Musical_pitch>* pitch_arr_p, Musical_pitch tonic, bool fix7_b)
 {
   for (int i = 0; i < pitch_arr_p->size (); i++)
     {
       Musical_pitch p = tonic;
       Musical_pitch q = (*pitch_arr_p)[i];
-      // duh, c7 should mean <c bes>
-      if (q.notename_i_ == 6)
-        q.accidental_i_--;
       p.transpose (q);
+      // duh, c7 should mean <c bes>
+      if (fix7_b && (step_i (tonic, p) == 7))
+        p.accidental_i_--;
       (*pitch_arr_p)[i] = p;
     }
   pitch_arr_p->sort (Musical_pitch::compare);
@@ -264,6 +295,10 @@ Chord::step_i (Musical_pitch tonic, Musical_pitch p)
   return i;
 }
 
+/*
+  JUNKME. 
+  do something smarter.
+ */
 Array<Musical_pitch>
 Chord::missing_thirds_pitch_arr (Array<Musical_pitch> const* pitch_arr_p)
 {
@@ -320,225 +355,38 @@ Array<Musical_pitch>
 Chord::to_pitch_arr () const
 {
   Array<Musical_pitch> pitch_arr = pitch_arr_;
-  if (inversion_p_)
+  if (inversion_b_)
     {
       int i = 0;
       for (; i < pitch_arr.size (); i++)
        {
-         if ((pitch_arr[i].notename_i_ == inversion_p_->notename_i_)
-             && (pitch_arr[i].accidental_i_ == inversion_p_->accidental_i_))
+         if ((pitch_arr[i].notename_i_ == inversion_pitch_.notename_i_)
+             && (pitch_arr[i].accidental_i_ == inversion_pitch_.accidental_i_))
            break;
        }
       if (i == pitch_arr.size ())
        {
          warning (_f ("invalid inversion pitch: not part of chord: %s",
-                      inversion_p_->str ()));
+                      inversion_pitch_.str ()));
        }
       else
        rebuild_with_bass (&pitch_arr, i);
     }
 
-  if (bass_p_)
+  if (bass_b_)
     {
-      pitch_arr.insert (*bass_p_, 0);
+      pitch_arr.insert (bass_pitch_, 0);
       rebuild_with_bass (&pitch_arr, 0);
     }
   return pitch_arr;
 }
 
-void
-Chord::find_additions_and_subtractions (Array<Musical_pitch>* add_arr_p, Array<Musical_pitch>* sub_arr_p) const
-{
-  Musical_pitch tonic = pitch_arr_[0];
-  /*
-    construct an array of thirds for a normal chord
-   */
-  Array<Musical_pitch> all_arr;
-  all_arr.push (tonic);
-  all_arr.push (pitch_arr_.top ());
-  all_arr.concat (missing_thirds_pitch_arr (&all_arr));
-  all_arr.sort (Musical_pitch::compare);
-  
-  int i = 0;
-  int j = 0;
-  while ((i < all_arr.size ()) || (j < pitch_arr_.size ()))
-    {
-      Musical_pitch a = all_arr [i <? all_arr.size () - 1];
-      Musical_pitch p = pitch_arr_ [j <? pitch_arr_.size () - 1];
-      /*
-        this pitch is present: do nothing, check next
-       */
-      if (a == p)
-       {
-         i++;
-         j++;
-       }
-      /*
-        found an extra pitch: chord addition
-       */
-      else if ((p < a) || (p.notename_i_ == a.notename_i_))
-       {
-         add_arr_p->push (p);
-         (j < pitch_arr_.size ()) ? j++ : i++;
-       }
-      /*
-        a third is missing: chord subtraction
-       */
-      else
-       {
-         sub_arr_p->push (a);
-         (i < all_arr.size ()) ? i++ : j++;
-       }
-    }
-      
-  /*
-    add highest addition, because it names chord
-    (1, 3 and) 5 not an addition: part of normal chord
-   */
-  if (step_i (tonic, pitch_arr_.top () > 5))
-    add_arr_p->push (pitch_arr_.top ());
-}
-
 /*
-  TODO:
-   reduce guess work: dim chord
-   other naming conventions `American'?
-   don't use TeX constructs
-   user defined chords-names for specific chords:
-      tonic, additions, subtractions, inversion, bass -> "my-chord-name"
+  This routine tries to guess tonic in a possibly inversed chord, ie
+  <e g c'> should produce: C.
+  This is only used for chords that are entered as simultaneous notes,
+  chords entered in \chord mode are fully defined.
  */
-String
-Chord::banter_str () const
-{
-  Musical_pitch tonic = pitch_arr_[0];
-
-  //urg, should do translation in scheme.
-  char const *acc[] = {"\\textflat\\textflat ", "\\textflat ", "", "\\textsharp " , "\\textsharp\\textsharp "};
-  String tonic_str = tonic.str ();
-  tonic_str = tonic_str.left_str (1).upper_str ()
-    + acc[tonic.accidental_i_ + 2];
-
-  Array<Musical_pitch> add_arr;
-  Array<Musical_pitch> sub_arr;
-  find_additions_and_subtractions (&add_arr, &sub_arr);
-                          
-
-  Array<Musical_pitch> scale;
-  for (int i=0; i < 7; i++)
-    scale.push (Musical_pitch (i));
-
-  // 7 always means 7-...
-  //  scale.push (Musical_pitch (6, -1)); // b
-
-  rebuild_transpose (&scale, tonic);
-  
-  bool has3m_b = false;
-  bool has4_b = false;
-  bool has5m_b = false;
-  String str;
-  String minor_str;
-  String sep_str;
-  for (int i = 0; i < add_arr.size (); i++)
-    {
-      Musical_pitch p = add_arr[i];
-      int step = step_i (tonic, p);
-      if (step == 4)
-       has4_b = true;
-      int accidental = p.accidental_i_ - scale[(step - 1) % 7].accidental_i_;
-      if ((step == 3) && (accidental == -1))
-       {
-         minor_str = "m";
-         has3m_b = true;
-       }
-      /*
-       have Cdim rather than Cm5-, even if it's a prefix
-       */
-      else if ((step == 5) && (accidental == -1) && has3m_b)
-       {
-         minor_str = "dim";
-         has5m_b = true;
-       }
-      else if (accidental
-              || (!(step % 2) || ((i + 1 == add_arr.size ()) && (step > 5))))
-        {
-         str += sep_str;
-         sep_str = "/";
-          if ((step == 7) && (accidental == 1))
-           {
-              str += "maj7";
-           }
-         else
-            {
-             /* 
-               if has3m_b and has5m_b, assume dim
-               don't mention dim-addition, except for chord-namer
-              */
-              if (((step/2) && (accidental == -1))
-                 && has3m_b && has5m_b)
-               {
-                 if (i == add_arr.size () - 1)
-                    str += to_str (step);
-                 else
-                   sep_str = "";
-               }
-             else
-               {
-                  str += to_str (step);
-                  if (accidental)
-                    str += accidental < 0 ? "-" : "+";
-               }
-            }
-       }
-    }
-
-  for (int i = 0; i < sub_arr.size (); i++)
-    {
-      Musical_pitch p = sub_arr[i];
-      int step = step_i (tonic, p);
-      /*
-       if chord has 3-, assume minor and don't display 'no3'
-       if additions include 4, assume sus4 and don't display 'no3'
-       if has3m_b and has5m_b, assume 'dim' chord
-      */
-      if (!((step == 3) && (has3m_b || has4_b))
-         && !((step/2) && (step !=3) && (step !=7 ) && (p.accidental_i_ == 0) && has3m_b && has5m_b)
-         && !((step == 7) && (p.accidental_i_ == -1) && has3m_b && has5m_b))
-       {
-         str += sep_str + "no" + to_str (step);
-         sep_str = "/";
-       }
-    }
-
-  /*
-   have Co rather than Cdim7
-   */
-  if (minor_str + str == "dim7")
-    {
-      minor_str = "";
-      str = "o";
-    }
-    
-
-  String inversion_str;
-  if (inversion_p_)
-    {
-      inversion_str = inversion_p_->str ();
-      inversion_str = "/" + inversion_str.left_str (1).upper_str ()
-       + acc[inversion_p_->accidental_i_ + 2];
-    }
-
-  String bass_str;
-  if (bass_p_)
-    {
-      bass_str = bass_p_->str ();
-      bass_str = "/" + bass_str.left_str (1).upper_str ()
-       + acc[bass_p_->accidental_i_ + 2];
-
-    }
-
-  return tonic_str + minor_str + "$^{" + str + "}$" + inversion_str + bass_str;
-}
-
 int
 Chord::find_tonic_i (Array<Musical_pitch> const* pitch_arr_p)
 {
@@ -648,3 +496,4 @@ Chord::rebuild_with_bass (Array<Musical_pitch>* pitch_arr_p, int bass_i)
       bass.octave_i_--;
   pitch_arr_p->insert (bass, 0);
 }
+