]> git.donarmstrong.com Git - lilypond.git/commitdiff
patch::: 1.3.2.jcn1
authorJan Nieuwenhuizen <janneke@gnu.org>
Mon, 1 Nov 1999 22:12:31 +0000 (23:12 +0100)
committerJan Nieuwenhuizen <janneke@gnu.org>
Mon, 1 Nov 1999 22:12:31 +0000 (23:12 +0100)
pl 2.jcn1
- chord fixes:
   * inversion request: no inversion guessing for chord entry
   * bass request: c/+b to add bass note not part of chord
   * -dim modifier works on all thirds
   * colon iso dash as tonic/modifier-additions separator
   * C:m5- displays as "Cdim"
   * C:m5-7- displays as "Co"

27 files changed:
CHANGES
Documentation/user/refman.itely
Documentation/user/tutorial.itely
TODO
VERSION
input/bugs/barline.ly
input/bugs/monstrous.ly
input/just-friends.ly
input/test/chord-inversion.ly
input/test/chord-table.ly
input/test/chords.ly
input/test/gmsusd.ly
input/test/notemode-chords.ly
input/tutorial/flowing.ly
input/twinkle-pop.ly
lily/chord-name-engraver.cc
lily/chord.cc
lily/include/chord-name-engraver.hh
lily/include/chord.hh
lily/include/lily-proto.hh
lily/include/musical-request.hh
lily/include/my-lily-parser.hh
lily/lexer.ll
lily/my-lily-parser.cc
lily/note-heads-engraver.cc
lily/parser.yy
ly/chord-modifiers.ly

diff --git a/CHANGES b/CHANGES
index 8cae195f22be815c278972de9ffb03f3e467e59c..e618029ba594db38a02358b9733d9c91de6d7298 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,12 @@
+pl 2.jcn1
+       - chord fixes: 
+          * inversion request: no inversion guessing for chord entry
+          * bass request: c/+b to add bass note not part of chord
+          * -dim modifier works on all thirds
+          * colon iso dash as tonic/modifier-additions separator
+          * C:m5- displays as "Cdim"
+          * C:m5-7- displays as "Co"
+
 pl 3.jcn1
        - moved bracket vars to params
        - reverted broken lilypond-devel
index bea07dc13d6fd503e9134ccede855e2b9e6eb285..b772f4b7a7a9471e1b3a5d3b93b2ab0dd9e58ee4 100644 (file)
@@ -1475,7 +1475,7 @@ Chord mode (see section XREF-modes [FIXME]).
 
 @example
 
-  @var{tonic}[@var{duration}][@code{-}@var{modifiers}][@code{^}@var{subtractions}][@code{/}@var{inversion}].
+  @var{tonic}[@var{duration}][@code{-}@var{modifiers}][@code{^}@var{subtractions}][@code{/}@var{inversion}][@code{/+}@var{bass}].
 @end example
 
 @var{tonic} should be the tonic note of the chord, and @var{duration}
@@ -1493,15 +1493,15 @@ must be separated by a dot (`@code{.}').
 @mudela[fragment,verbatim]
 \transpose c'' {
   \chords {
-    c1  c-3-       c-7     c-8
-    c-9 c-9-.5+.7+ c-3-.5- c-4.6.8
+    c1  c:3-       c:7     c:8
+    c:9 c:9-.5+.7+ c:3-.5- c:4.6.8
   }
 }
 
 @end mudela
 @end quotation
 
-The second type of modifier that may appear after the `@code{-}' is a
+The second type of modifier that may appear after the `@code{:}' is a
 named modifier.  Named modifiers are listed in the file
 @file{chord-modifiers.ly}.  The available modifiers are `@code{m}' and
 `@code{min}' which lower the 3rd half a step, `@code{aug}@indexcode{aug}' which
@@ -1514,7 +1514,7 @@ which replaces the 5th with a 4th.
 @mudela[fragment,verbatim]
 \transpose c'' {
   \chords {
-    c1-m c-min7 c-maj c-aug c-dim c-sus
+    c1:m c:min7 c:maj c:aug c:dim c:sus
   }
 }
 
@@ -1529,7 +1529,7 @@ separated by dots.
 @mudela[fragment,verbatim,center]
   \transpose c'' {
     \chords {
-      c1^3 c-7^5.3 c-8^7
+      c1^3 c:7^5.3 c:8^7
     }
   }
 @end mudela 
@@ -1543,7 +1543,21 @@ warning will be printed.
 @mudela[fragment,verbatim,center]
   \transpose c''' {
     \chords {
-      c1 c/e c/g c-7/e
+      c1 c/e c/g c:7/e
+    }
+  }
+
+@end mudela 
+
+Bass notes can be added by `@code{/+}@indexcode{/+}' and
+the name of a single note to a chord.  This has the effect of
+adding the specified note to the chord, lowered by an octave,
+so it becomes the lowest note in the chord.
+
+@mudela[fragment,verbatim,center]
+  \transpose c''' {
+    \chords {
+      c1 c/+c c/+g c:7/+b
     }
   }
 
index 5029f7fa34185614951b1b28d9d15d6dfd0d4482..a5d540afc566468c6b5f7bf17d190647219463c3 100644 (file)
@@ -346,8 +346,8 @@ text = \lyrics @{
 
 accompaniment =\chords @{
         r8
-        c2-3- f-3-.7 d-min es4 c8-min r8
-        c2-min f-min7 g-7^3.5 c-min @}
+        c2:3- f:3-.7 d:min es4 c8:min r8
+        c2:min f:min7 g:7^3.5 c:min @}
 
 \score @{
         \simultaneous @{
@@ -397,8 +397,8 @@ text = \lyrics {
 
 accompaniment =\chords {
         r8
-        c2-3- f-3-.7 d-min es4 c8-min r8
-        c2-min f-min7 g-7^3.5 c-min }
+        c2:3- f:3-.7 d:min es4 c8:min r8
+        c2:min f:min7 g:7^3.5 c:min }
 
 \score {
         \simultaneous {
@@ -513,7 +513,7 @@ of the chords you want, instead of the notes comprising the chord.
 @end example 
 There is no accompaniment during the anacrusis.@example 
 
-        c2-3- f-3-.7
+        c2:3- f:3-.7
  
 @end example 
 A chord is started by  the tonic of the chord. The
@@ -523,19 +523,19 @@ be small. @code{7} modifies (adds) a seventh, which is small by default
 to create the @code{f a c es} chord.  Multiple modifiers must be
 separated by a dot.@example 
 
-        d-min es4 c8-min r8
+        d:min es4 c8:min r8
  
 @end example 
 Some modifiers have predefined names, eg. @code{min} is  the same as
 @code{3-}, so @code{d-min} is a minor @code{d} chord.@example 
 
-        c2-min f-min7 g-7^3.5 c-min @}
+        c2:min f:min7 g:7^3.5 c:min @}
  
 @end example 
 A named modifier @code{min} and a normal modifier @code{7} do not have
 to be separated by a dot.  Tones from a chord are removed with chord
 subtractions.  Subtractions are started with a caret, and they are
-also separated by dots.  In this example, @code{g-7^3.5} produces a
+also separated by dots.  In this example, @code{g:7^3.5} produces a
 minor seventh.  The brace ends the sequential music. @example 
 
         \score @{
diff --git a/TODO b/TODO
index 813dcad6e050ed99338e91f73e6e22db06c1a470..07f05fc75b2091ffbc2a5d3b6431192d28b0787d 100644 (file)
--- a/TODO
+++ b/TODO
@@ -36,28 +36,6 @@ John
 . * fix or replace feta-accordion.mf
 . * script engraver
 . * bracket pdf hack
-. * Chords:
-.  * Bass/inversion pitch when not part of Chord
-Sometimes a series of changing chords will be blocked out over a static tone
-in the bass, usually this was referred to as a pedal tone (and it's been
-continued to be used, even in contemporary music).  Another less frequently
-used practice is putting a non-chordal tone in the bass (that is not acting
-as a pedal tone) in order to create tension or make a more colorful sound.
-There are examples of this in the classsical literature, but its use is much
-more prevalent today.  For example, the chord sequence Dm7 - Dm7/G is such a
-sequence, and the Dm7/G defies easy classification.  Is it a G7(no 3rd)add
-9/11?  Or is it a G7(no 3rd)add2/4?  Or perhaps Dm7 add11?  It's a heck of a
-lot easier to read to just leave it as Dm7/G!
-.  * Diminished does not mean 5-
-When speaking of a chord, dimished can mean one of two things:  A diminished
-triad or a dimished seventh chord (which is distinctly different from what's
-known as the 'half-diminished' chord).  The triad is a root with a flat
-third and flat fifth, and is notated (at least in America, someone else will
-have to fill me in on other countries) as (using C as the root) Cdim, or Co.
-The diminished seventh has a root with a flat third, flat fifth, and a
-doubly flatted seventh (which is enharmonically equivalent to a sixth, and
-from which comes tons of confusion).  It is usually notated as (again, using
-C as the root) Cdim7 or Co7.
 
 . * Mondrup:
 - I would like the possibility of forcing clef- and key- changes to be
diff --git a/VERSION b/VERSION
index af709f691860b2ab9b32abda71ba35c72fa22102..ad6cafe6de7efc137d648d9e17db7c67a78d5019 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -2,7 +2,7 @@ PACKAGE_NAME=LilyPond
 MAJOR_VERSION=1
 MINOR_VERSION=3
 PATCH_LEVEL=2
-MY_PATCH_LEVEL=
+MY_PATCH_LEVEL=jcn1
 
 # use the above to send patches: MY_PATCH_LEVEL is always empty for a
 # released version.
index c9c96999065e521b40bf3c36cdef8d61e5987d31..97ac88ac613547db03e981d0afeebb9912bfda59 100644 (file)
@@ -15,7 +15,7 @@ melody = \notes \relative c' {
 
 accompaniment =\chords  \sequential {
        r8
-       c2-min f-min 7 
+       c2:min f:min 7 
 }
 
 \score {
index 52ca68966fbb9dd94926ba069aa4eff79467b0df..e25ea236e57b43a98a3bddc7c78d73366ac6baf0 100644 (file)
@@ -1,12 +1,14 @@
 
+%% Chord gurus, is this ok now??
+
 monstrous= \chords{
     \property Score.chordInversion = "1"
 
-    % /c is missing:
-    bes-6/c
+    % /c is/was missing:
+    bes:6/+c
 
-    % Cdim7 ??
-    cis-3-.5-.6 
+    % Cdim7
+    c:dim7
 }
 
 \score{
index a6cc637cb3f092b39a18be8ddd2d0ef1124d266e..3b273123c7efe0fc0f6f8df2850fd554e40f7c8d 100644 (file)
@@ -31,18 +31,17 @@ of a certain tune (Jazz, Real Book, for example), like
 
 \score{
        \context ChordNames \chords{
-               \property Score.chordInversion = 1
                \property Score.barAtLineStart = 1
                \repeat semi 2 {
-                       f1-maj f-maj f-7 bes-7
-                       c-maj c-maj es es
-                       d-7 g-7 b2-7/fis e-7 a1-7\break
-                       d-7 d-7 d-7 g2-7 ges-7
-
-                       f1-maj f1-maj f-7 bes-7
-                       c-maj c-maj es es
-                       d-7 g-7 b2-7/fis e-7 a1-7\break
-                       d-7 d2-7 g-7 c1-6 g2-7 c-7
+                       f1:maj f:maj f:7 bes:7
+                       c:maj c:maj es es
+                       d:7 g:7 b2:7/fis e:7 a1:7\break
+                       d:7 d:7 d:7 g2:7 ges:7
+
+                       f1:maj f1:maj f:7 bes:7
+                       c:maj c:maj es es
+                       d:7 g:7 b2:7/fis e:7 a1:7\break
+                       d:7 d2:7 g:7 c1:6 g2:7 c:7
                }
        }
        \paper{
index 315561dbca705eea5559339cd18005800ee44eb1..c54281fa6d528579911bef895d7db79199fb93c7 100644 (file)
@@ -5,14 +5,12 @@ TestedFeatures =       "chord inversions";
 }
 
 inversions = \notes\transpose c''\chords{
-       % inversions ignored here
-       c1 c-sus c-6 c/e c/g c/d
-       % now try to find chords with inversions
-       \property Score.chordInversion = 1 
-       c1 c-sus c-6 
-       c/e
-       c/g
+       % inversions
+       c1 c:sus c:6 c/e c/g
        c/d % this triggers a warning: no 'd' in chord of c
+
+       % added bass 
+       c/+e c/+c c/+b
 }
 
 \score{
index 40e599521ac4dc1ce8e73487f3db04b439d8bc0a..94df658308521e5aaaaec3e0fe3b677c3a5e382a 100644 (file)
@@ -5,7 +5,7 @@ enteredby =     "jcn";
 }
 
 tab = \notes\transpose c'''\chords{
-       c1 c-m c-4 c-m4 c-5+ c-5- c-m5- c-5-.5+ c-6\break %c-m6\break
+       c1 c:m c:4 c:m4 c:5+ c:5- c:dim c:5-.5+ c:6\break %c:m6\break
 }
 
 \score{
index e4e3e756ce3694750126e299cd0e15d8cdc22bf5..c74d5024304f974f5f42f14fb7c90d8d143e89e6 100644 (file)
@@ -7,26 +7,27 @@ Would this be acceptable/good enough/convenient for entry?
    
    C#                     cis
    Cb                     ces
-   Cm; Cmin               c-3-; c-m; c-min
-   Caug                   c-5+; c-aug;
-   Cdim                   c-5-; c-dim
-   Cmaj7                  c-7+; c-maj
-   C7                     c-7
-   Csus; Csus4            c-4; c-sus
+   Cm; Cmin               c:3-; c:m; c:min
+   Caug                   c:5+; c:aug;
+   Cdim                   c:3-:5-; c:dim
+   Cmaj7                  c:7+; c:maj
+   C7                     c:7
+   Csus; Csus4            c:4; c:sus
 
 %}
 
 scales = \notes \transpose c'' \chords{
                %<c1 e g>
-               c1-m c-min c4-dim c-aug c-sus c-maj
-                c1-6 c4-7 c-9 c-11 c-13
-               c-m7 c-m.sus c-m7.sus
-               c1-7^5 c-13^5.7.9.11
-               % c1-7^5 c-13^5
+               c1:m c:min c4:dim c:aug c:sus c:maj
+                c1:6 c4:7 c:9 c:11 c:13
+               c:m7 c:m.sus c:m7.sus
+               c4:dim7 c:dim9 c2:7^5 
+               c:13^5.7.9.11
+               % c1:7^5 c:13^5
                c1 g d a e b fis
                 c1 f bes es as des ges
-               % wierd, multiple -add, ^sub
-               c-7+.9-^3.5
+               % wierd, multiple :add, ^sub
+               c:7+.9-^3.5
                % long
                c\breve c\longa
        }
index 6217946830af7f848401c9de61a449471e2079a7..9ba7522e20c82841d299ca6524a0a19dff1246e9 100644 (file)
@@ -8,20 +8,19 @@
 gmsus=\notes\relative c \chords{ 
        g1
        % Gm7sus4: the hard way
-       g1-3-.4.7
+       g1:3-.4.7
 
        % another hard way:
        \notes< g'1 bes c d f >
 
        % bit easier:
-       g1-m.4.7
+       g1:m.4.7
 
-       g1-m7.sus
-       g1-m7.sus4
+       g1:m7.sus
+       g1:m7.sus4
 
        % and finally:
-       \property Score.chordInversion = 1 
-       g1-m7.sus/d
+       g1:m7.sus/d
 }
 
 \score{
index ed0c1549027ac375a3438da9810cb112e73db86d..5652aa1f0d4f85e8acf81510772da32a9c118b1c 100644 (file)
@@ -5,7 +5,7 @@
 % 1.1.53: @x@ syntax dropped
 % if you want fingering, write chord explicitily; eg < c1-1 e-2 g-3 >
 %              @c1@ @c-7@ @c-7^5@-1-3
-               \chords { c1 c-7 c-7^5 }
+               \chords { c1 c:7 c:7^5 }
        }
 
 }
index 74339f3ceb1219f5269008f9414f92d025e76546..597dd2bed8d840263dfafba4ad4989f0aa6944fe 100644 (file)
@@ -18,8 +18,8 @@ text = \lyrics {
 
 accompaniment =\chords {
         r8
-        c2-3- f-3-.7 d-min es4 c8-min r8
-        c2-min f-min7 g-7^3.5 c-min }
+        c2:3- f:3-.7 d:min es4 c8:min r8
+        c2:min f:min7 g:7^3.5 c:min }
 
 \score {
         \simultaneous {
index eb4cc83b2fa30ec35548a6785dccce07ebc9d88a..9df29ef6de54c9d8e666d91fd451e19ad0236773 100644 (file)
@@ -25,12 +25,12 @@ melodie = \notes\relative c'' {
 acc = \chords {
        % why don't \skip, s4 work?
         c2 c f c
-        f c g-7 c
-       g f c  g-7 % urg, bug!
-        g f c  g-7
+        f c g:7 c
+       g f c  g:7 % urg, bug!
+        g f c  g:7
        % copy 1-8
         c2 c f c
-        f c g-7 c
+        f c g:7 c
 }
 
 text = \lyrics{ 
index 4c57efac7ed3628ef990829fa371b6c795b67b32..ef0744d627219e1092001232021a8c859d383043 100644 (file)
@@ -21,7 +21,8 @@ ADD_THIS_TRANSLATOR (Chord_name_engraver);
 Chord_name_engraver::Chord_name_engraver ()
 {
   tonic_req_ = 0;
-  //  bass_req_ = 0;
+  inversion_req_ = 0;
+  bass_req_ = 0;
 }
 
 void
@@ -44,14 +45,16 @@ Chord_name_engraver::do_try_music (Music* m)
       tonic_req_ = t;
       return true;
     }
-#if 0
+  if (Inversion_req* i = dynamic_cast<Inversion_req*> (m))
+    {
+      inversion_req_ = i;
+      return true;
+    }
   if (Bass_req* b = dynamic_cast<Bass_req*> (m))
     {
       bass_req_ = b;
       return true;
     }
-#endif
-  
   return false;
 }
 
@@ -63,20 +66,13 @@ Chord_name_engraver::do_process_requests ()
   if (!pitch_arr_.size ())
     return;
 
-  Chord chord (pitch_arr_);
-  Musical_pitch* inversion = 0;
+  bool find_inversion_b = false;
   SCM chord_inversion = get_property ("chordInversion", 0);
-  if (gh_boolean_p (chord_inversion) && gh_scm2bool (chord_inversion))
-    {
-      int tonic_i = tonic_req_
-       ? chord.find_notename_i (tonic_req_->pitch_) : chord.find_tonic_i ();
-       
-      if (tonic_i)
-       {
-         inversion = &pitch_arr_[0];
-         chord.rebuild_insert_inversion (tonic_i);
-       }
-    }
+  if (gh_boolean_p (chord_inversion))
+    find_inversion_b = gh_scm2bool (chord_inversion);
+
+  Chord chord = to_chord (pitch_arr_, tonic_req_, inversion_req_, bass_req_, 
+    find_inversion_b);
     
   Text_item* item_p =  new Text_item;
 
@@ -90,7 +86,7 @@ Chord_name_engraver::do_process_requests ()
     item_p->text_str_ = chord.banter_str (inversion);
    */
 
-  item_p->text_str_ = chord.banter_str (inversion);
+  item_p->text_str_ = chord.banter_str ();
   
   text_p_arr_.push (item_p);
   announce_element (Score_element_info (item_p, 0));
@@ -106,4 +102,7 @@ Chord_name_engraver::do_pre_move_processing ()
   text_p_arr_.clear ();
   pitch_arr_.clear ();
   tonic_req_ = 0;
+  inversion_req_ = 0;
+  bass_req_ = 0;
 }
+
index b0b081e2173f7f1d5c9f56ae3ab20f3229f7033a..adef8d4991c5e2f35ab1edd645515c788a6b3212 100644 (file)
   (c)  1999 Jan Nieuwenhuizen <janneke@gnu.org>
 */
 
+#include "chord.hh"
+#include "musical-request.hh"
+#include "warn.hh"
+
+
 /*
-  FIXME:
+  construct from parser output
+*/
+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
+  bool dim_b = false;
+  for (int i=0; i < add_arr_p->size (); i++)
+    {
+      Musical_pitch* p = &(*add_arr_p)[i];
+      if (p->octave_i_ == -100)
+        {
+          p->octave_i_ = 0;
+         dim_b = true;
+       }
+    }
+  Chord::rebuild_transpose (add_arr_p, tonic);
+  Chord::rebuild_transpose (sub_arr_p, tonic);
+
+  Musical_pitch fifth = tonic;
+  fifth.transpose (Musical_pitch (2));
+  fifth.transpose (Musical_pitch (2, -1));
+
+  /*
+    remove double adds (urg: sus4)
+   */
+  for (int i = add_arr_p->size () - 1; i >= 0 ; i--)
+    {
+      int j = Chord::find_pitch_i (add_arr_p, (*add_arr_p)[i]);
+      if ((j != -1) && (i != j))
+        {
+           add_arr_p->get (i);
+       } 
+    }
+
+  /*
+    default chord includes upto 5: <1, 3, 5>
+   */
+  add_arr_p->insert (tonic, 0);
+  Array<Musical_pitch> tmp = *add_arr_p;
+  int highest_step = Chord::step_i (tonic, tmp.top ());
+  if (highest_step < 5)
+    tmp.push (fifth);
+  else if (dim_b)
+    {
+      Musical_pitch* p = &add_arr_p->top ();
+      p->accidental_i_--;
+    }
+
+  /*
+    find missing thirds
+   */
+  Array<Musical_pitch> missing_arr = Chord::missing_thirds_pitch_arr (&tmp);
+  if (highest_step < 5)
+    missing_arr.push (fifth);
+
+  if (dim_b)
+    {
+      for (int i=0; i < missing_arr.size (); i++)
+        {
+          missing_arr[i].accidental_i_--;
+       }
+    }
+
+  /*
+    if additions include some 3, don't add third
+   */
+  Musical_pitch third = tonic;
+  third.transpose (Musical_pitch (2));
+  if (Chord::find_notename_i (add_arr_p, third) != -1)
+    {
+      int i = Chord::find_pitch_i (&missing_arr, third);
+      if (i != -1)
+       missing_arr.get (i);
+    }
+  
+  /*
+    if additions include 4, assume sus4 and don't add third implicitely
+     C-sus (4) = c f g (1 4 5)
+   */
+  Musical_pitch sus = tonic;
+  sus.transpose (Musical_pitch (3));
+  if (Chord::find_pitch_i (add_arr_p, sus) != -1)
+    {
+      int i = Chord::find_pitch_i (&missing_arr, third);
+      if (i != -1)
+       missing_arr.get (i);
+    }
 
-  A triad is a chord of three tones, and not an interval of a third.
+  /*
+    if additions include some 5, don't add fifth
+   */
+  if (Chord::find_notename_i (add_arr_p, fifth) != -1)
+    {
+      int i = Chord::find_pitch_i (&missing_arr, fifth);
+      if (i != -1)
+       missing_arr.get (i);
+    }
+  
+  
+  /*
+    complete the list of thirds to be added
+   */
+  add_arr_p->concat (missing_arr);
+  add_arr_p->sort (Musical_pitch::compare);
+
+  Array<Musical_pitch> pitch_arr;
+  /*
+   add all that aren't subtracted
+   */
+  for (int i = 0; i < add_arr_p->size (); i++)
+    {
+      Musical_pitch p = (*add_arr_p)[i];
+      int j = 0;
+      for (; j < sub_arr_p->size (); j++)
+       if (p == (*sub_arr_p)[j])
+         {
+           sub_arr_p->del (j);
+           j = -1;
+           break;
+         }
+      if (j == sub_arr_p->size ())
+       pitch_arr.push (p);
+    }
+
+  pitch_arr.sort (Musical_pitch::compare);
+
+  for (int i = 0; i < sub_arr_p->size (); i++)
+    warning (_f ("invalid subtraction: not part of chord: %s",
+                (*sub_arr_p)[i].str ()));
+  return Chord (pitch_arr, inversion_p, bass_p);
+}
+
+/*
+  Construct from list of pitches and requests
  */
+Chord
+to_chord (Array<Musical_pitch> pitch_arr, Tonic_req* tonic_req, Inversion_req* inversion_req, Bass_req* bass_req, bool find_inversion_b)
+{
+  Musical_pitch* inversion_p = 0;
+  Musical_pitch* bass_p = 0;
 
-#include "chord.hh"
-#include "warn.hh"
+  if (bass_req)
+    {
+      assert (pitch_arr[0].notename_i_ == bass_req->pitch_.notename_i_);
+      bass_p = new Musical_pitch (pitch_arr.get (0));
+    }
+    
+  if (inversion_req)
+    {
+      assert (pitch_arr[0].notename_i_ == inversion_req->pitch_.notename_i_);
+      inversion_p = new Musical_pitch (inversion_req->pitch_);
+      assert (tonic_req);
+      int tonic_i = Chord::find_notename_i (&pitch_arr, tonic_req->pitch_);
+      if (tonic_i)
+       Chord::rebuild_insert_inversion (&pitch_arr, tonic_i);
+    }
+    
+  if (find_inversion_b && !inversion_p)
+    {
+      int tonic_i = tonic_req
+       ? Chord::find_notename_i (&pitch_arr, tonic_req->pitch_) 
+       : Chord::find_tonic_i (&pitch_arr);
+       
+      if (tonic_i)
+       {
+         inversion_p = &pitch_arr[0];
+         Chord::rebuild_insert_inversion (&pitch_arr, tonic_i);
+       }
+    }
+
+  if (tonic_req)
+    {
+      assert (pitch_arr[0].notename_i_ == tonic_req->pitch_.notename_i_);
+    }
 
-// doesn't seem common, and we should know about this during parsing
-// #define INVERSION_ADDED_AS_BASE 1
+  return Chord (pitch_arr, inversion_p, bass_p);
+}
 
-Chord::Chord (Array<Musical_pitch> pitch_arr)
+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;
+}
+
+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;
+}
+
+Chord::~Chord ()
+{
+  delete inversion_p_;
+  delete bass_p_;
 }
 
-static void
-rebuild_transpose (Musical_pitch tonic, Array<Musical_pitch>* pitch_arr_p)
+void
+Chord::rebuild_transpose (Array<Musical_pitch>* pitch_arr_p, Musical_pitch tonic)
 {
   for (int i = 0; i < pitch_arr_p->size (); i++)
     {
@@ -39,8 +228,8 @@ rebuild_transpose (Musical_pitch tonic, Array<Musical_pitch>* pitch_arr_p)
   pitch_arr_p->sort (Musical_pitch::compare);
 }
 
-static int
-find_pitch_i (Array<Musical_pitch> const* pitch_arr_p, Musical_pitch p)
+int
+Chord::find_pitch_i (Array<Musical_pitch> const* pitch_arr_p, Musical_pitch p)
 {
   for (int i = 0; i < pitch_arr_p->size (); i++)
     if (p == (*pitch_arr_p)[i])
@@ -48,8 +237,8 @@ find_pitch_i (Array<Musical_pitch> const* pitch_arr_p, Musical_pitch p)
   return -1;
 }
 
-static int
-find_notename_i (Array<Musical_pitch> const* pitch_arr_p, Musical_pitch p)
+int
+Chord::find_notename_i (Array<Musical_pitch> const* pitch_arr_p, Musical_pitch p)
 {
   int i = find_pitch_i (pitch_arr_p, p);
   if (i == -1)
@@ -64,11 +253,8 @@ find_notename_i (Array<Musical_pitch> const* pitch_arr_p, Musical_pitch p)
   return i;
 }
 
-/*
-  trap (NL) != trap(english)
- */
-static int
-trap_i (Musical_pitch tonic, Musical_pitch p)
+int
+Chord::step_i (Musical_pitch tonic, Musical_pitch p)
 {
   int i = p.notename_i_ - tonic.notename_i_
     + (p.octave_i_ - tonic.octave_i_) * 7;
@@ -78,15 +264,15 @@ trap_i (Musical_pitch tonic, Musical_pitch p)
   return i;
 }
 
-static Array<Musical_pitch>
-missing_triads_pitch_arr (Array<Musical_pitch>const* pitch_arr_p)
+Array<Musical_pitch>
+Chord::missing_thirds_pitch_arr (Array<Musical_pitch> const* pitch_arr_p)
 {
-  Array<Musical_pitch> triads;
+  Array<Musical_pitch> thirds;
 
   /* is the third c-e, d-f, etc. small or large? */
   int minormajor_a[] = {0, -1, -1, 0,0,-1,-1};
   for (int i=0; i < 7; i++)
-    triads.push (Musical_pitch( 2, minormajor_a[i]));
+    thirds.push (Musical_pitch( 2, minormajor_a[i]));
 
   Musical_pitch tonic = (*pitch_arr_p)[0];
   Musical_pitch last = tonic;
@@ -95,12 +281,12 @@ missing_triads_pitch_arr (Array<Musical_pitch>const* pitch_arr_p)
   for (int i = 0; i < pitch_arr_p->size ();)
     {
       Musical_pitch p = (*pitch_arr_p)[i];
-      int trap = trap_i (tonic, p);
+      int step = step_i (tonic, p);
       if (last.notename_i_ == p.notename_i_)
-       last.transpose (triads[(last.notename_i_ - tonic.notename_i_ + 7) % 7]);
-      if (trap > trap_i (tonic, last))
+       last.transpose (thirds[(last.notename_i_ - tonic.notename_i_ + 7) % 7]);
+      if (step > step_i (tonic, last))
        {
-         while (trap > trap_i (tonic, last))
+         while (step > step_i (tonic, last))
            {
              if ((last.notename_i_ - tonic.notename_i_ + 7) % 7 == 6)
                {
@@ -113,7 +299,7 @@ missing_triads_pitch_arr (Array<Musical_pitch>const* pitch_arr_p)
                {
                  missing_arr.push (last);
                }
-             last.transpose (triads[(last.notename_i_ - tonic.notename_i_ + 7) % 7]);
+             last.transpose (thirds[(last.notename_i_ - tonic.notename_i_ + 7) % 7]);
            }
        }
       else
@@ -126,150 +312,51 @@ missing_triads_pitch_arr (Array<Musical_pitch>const* pitch_arr_p)
 
 
 /*
-  construct from parser output
-*/
-Chord::Chord (Musical_pitch tonic, Array<Musical_pitch>* add_arr_p, Array<Musical_pitch>* sub_arr_p, Musical_pitch* inversion_p)
+ Mangle into list of pitches.
+ For normal chord entry, inversion and bass pitches are retained in
+ specific *_requests
+ */
+Array<Musical_pitch>
+Chord::to_pitch_arr () const
 {
-  rebuild_transpose (tonic, add_arr_p);
-  rebuild_transpose (tonic, sub_arr_p);
-
-  Musical_pitch fifth = tonic;
-  fifth.transpose (Musical_pitch (2));
-  fifth.transpose (Musical_pitch (2, -1));
-
-  /*
-    remove double adds (urg: sus4)
-   */
-  for (int i = add_arr_p->size () - 1; i >= 0 ; i--)
-    {
-      int j = ::find_pitch_i (add_arr_p, (*add_arr_p)[i]);
-      if ((j != -1) && (i != j))
-        {
-           add_arr_p->get (i);
-       } 
-    }
-
-  /*
-    default chord includes upto 5: <1, 3, 5>
-   */
-  add_arr_p->insert (tonic, 0);
-  Array<Musical_pitch> tmp = *add_arr_p;
-  int highest_trap = trap_i (tonic, tmp.top ());
-  if (highest_trap < 5)
-    tmp.push (fifth);
-
-  /*
-    find missing triads
-   */
-  Array<Musical_pitch> missing_arr = missing_triads_pitch_arr (&tmp);
-  if (highest_trap < 5)
-    missing_arr.push (fifth);
-
-  /*
-    if additions include some 3, don't add third
-   */
-  Musical_pitch third = tonic;
-  third.transpose (Musical_pitch (2));
-  if (::find_notename_i (add_arr_p, third) != -1)
-    {
-      int i = ::find_pitch_i (&missing_arr, third);
-      if (i != -1)
-       missing_arr.get (i);
-    }
-  
-  /*
-    if additions include 4, assume sus4 and don't add third implicitely
-     C-sus (4) = c f g (1 4 5)
-   */
-  Musical_pitch sus = tonic;
-  sus.transpose (Musical_pitch (3));
-  if (::find_pitch_i (add_arr_p, sus) != -1)
-    {
-      int i = ::find_pitch_i (&missing_arr, third);
-      if (i != -1)
-       missing_arr.get (i);
-    }
-
-  /*
-    if additions include some 5, don't add fifth
-   */
-  if (::find_notename_i (add_arr_p, fifth) != -1)
-    {
-      int i = ::find_pitch_i (&missing_arr, fifth);
-      if (i != -1)
-       missing_arr.get (i);
-    }
-  
-  
-  /*
-    complete the list of triads to be added
-   */
-  add_arr_p->concat (missing_arr);
-  add_arr_p->sort (Musical_pitch::compare);
-
-  /*
-   add all that aren't subtracted
-   */
-  for (int i = 0; i < add_arr_p->size (); i++)
-    {
-      Musical_pitch p = (*add_arr_p)[i];
-      int j = 0;
-      for (; j < sub_arr_p->size (); j++)
-       if (p == (*sub_arr_p)[j])
-         {
-           sub_arr_p->del (j);
-           j = -1;
-           break;
-         }
-      if (j == sub_arr_p->size ())
-       pitch_arr_.push (p);
-    }
-
-  pitch_arr_.sort (Musical_pitch::compare);
-
-  for (int i = 0; i < sub_arr_p->size (); i++)
-    warning (_f ("invalid subtraction: not part of chord: %s",
-                (*sub_arr_p)[i].str ()));
-
-  if (inversion_p)
+  Array<Musical_pitch> pitch_arr = pitch_arr_;
+  if (inversion_p_)
     {
       int i = 0;
-      for (; i < pitch_arr_.size (); i++)
+      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_p_->notename_i_)
+             && (pitch_arr[i].accidental_i_ == inversion_p_->accidental_i_))
            break;
        }
-      if (i == pitch_arr_.size ())
+      if (i == pitch_arr.size ())
        {
          warning (_f ("invalid inversion pitch: not part of chord: %s",
-                      inversion_p->str ()));
+                      inversion_p_->str ()));
        }
       else
-       {
-#if INVERSION_ADDED_AS_BASE
-         pitch_arr_.insert (pitch_arr_[i], 0);
-         rebuild_with_bass (0);
-#else
-         rebuild_with_bass (i);
-#endif
-         
-       }
-      delete inversion_p;
+       rebuild_with_bass (&pitch_arr, i);
     }
+
+  if (bass_p_)
+    {
+      pitch_arr.insert (*bass_p_, 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
+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 triads for a normal chord
+    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_triads_pitch_arr (&all_arr));
+  all_arr.concat (missing_thirds_pitch_arr (&all_arr));
   all_arr.sort (Musical_pitch::compare);
   
   int i = 0;
@@ -295,7 +382,7 @@ Chord::find_additions_and_subtractions(Array<Musical_pitch>* add_arr_p, Array<Mu
          (j < pitch_arr_.size ()) ? j++ : i++;
        }
       /*
-        a triad is missing: chord subtraction
+        a third is missing: chord subtraction
        */
       else
        {
@@ -308,12 +395,20 @@ Chord::find_additions_and_subtractions(Array<Musical_pitch>* add_arr_p, Array<Mu
     add highest addition, because it names chord
     (1, 3 and) 5 not an addition: part of normal chord
    */
-  if (trap_i (tonic, pitch_arr_.top () > 5))
+  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"
+ */
 String
-Chord::banter_str (Musical_pitch* inversion) const
+Chord::banter_str () const
 {
   Musical_pitch tonic = pitch_arr_[0];
 
@@ -335,97 +430,133 @@ Chord::banter_str (Musical_pitch* inversion) const
   // 7 always means 7-...
   //  scale.push (Musical_pitch (6, -1)); // b
 
-  rebuild_transpose (tonic, &scale);
+  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 trap = trap_i (tonic, p);
-      if (trap == 4)
+      int step = step_i (tonic, p);
+      if (step == 4)
        has4_b = true;
-      int accidental = p.accidental_i_ - scale[(trap - 1) % 7].accidental_i_;
-      if ((trap == 3) && (accidental == -1))
+      int accidental = p.accidental_i_ - scale[(step - 1) % 7].accidental_i_;
+      if ((step == 3) && (accidental == -1))
        {
-         tonic_str += "m";
+         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
-              || (!(trap % 2) || ((i + 1 == add_arr.size ()) && (trap > 5))))
+              || (!(step % 2) || ((i + 1 == add_arr.size ()) && (step > 5))))
         {
          str += sep_str;
-          if ((trap == 7) && (accidental == 1))
-            str += "maj7";
-          else
+         sep_str = "/";
+          if ((step == 7) && (accidental == 1))
+           {
+              str += "maj7";
+           }
+         else
             {
-              str += to_str (trap);
-              if (accidental)
-                str += accidental < 0 ? "-" : "+";
+             /* 
+               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 ? "-" : "+";
+               }
             }
-         sep_str = "/";
        }
     }
 
   for (int i = 0; i < sub_arr.size (); i++)
     {
       Musical_pitch p = sub_arr[i];
-      int trap = trap_i (tonic, p);
+      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 (!((trap == 3) && (has3m_b || has4_b)))
+      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 (trap);
+         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)
+  if (inversion_p_)
     {
-      inversion_str = inversion->str ();
+      inversion_str = inversion_p_->str ();
       inversion_str = "/" + inversion_str.left_str (1).upper_str ()
-       + acc[inversion->accidental_i_ + 2];
-
+       + acc[inversion_p_->accidental_i_ + 2];
     }
 
-  return tonic_str + "$^{" + str + "}$" + inversion_str;
-}
+  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];
 
-int
-Chord::find_notename_i (Musical_pitch p) const
-{
-  return ::find_notename_i (&pitch_arr_, p);
-}
+    }
 
-int
-Chord::find_pitch_i (Musical_pitch p) const
-{
-  return ::find_pitch_i (&pitch_arr_, p);
+  return tonic_str + minor_str + "$^{" + str + "}$" + inversion_str + bass_str;
 }
 
 int
-Chord::find_tonic_i () const
+Chord::find_tonic_i (Array<Musical_pitch> const* pitch_arr_p)
 {
   /*
     find tonic
     
-    first try: base of longest line of triads
+    first try: base of longest line of thirds
    */
   int tonic_i = 0;
   int longest_i = 0;
-  for (int i = 0; i < pitch_arr_.size (); i++)
+  for (int i = 0; i < pitch_arr_p->size (); i++)
     {
-      int no_triad_i = 0;
-      int last_i = pitch_arr_[i % pitch_arr_.size ()].notename_i_;
+      int no_third_i = 0;
+      int last_i = (*pitch_arr_p)[i % pitch_arr_p->size ()].notename_i_;
       int j = 0;
-      for (; j < pitch_arr_.size (); j++)
+      for (; j < pitch_arr_p->size (); j++)
        {
-         int cur_i = pitch_arr_[(i + j + 1) % pitch_arr_.size ()].notename_i_;
+         int cur_i = (*pitch_arr_p)[(i + j + 1) % pitch_arr_p->size ()].notename_i_;
          int gap = cur_i - last_i;
          while (gap < 0)
            gap += 7;
@@ -433,11 +564,11 @@ Chord::find_tonic_i () const
          if (gap == 2)
            last_i = cur_i;
          else
-           no_triad_i++;
+           no_third_i++;
        }
-      if (j - no_triad_i > longest_i)
+      if (j - no_third_i > longest_i)
        {
-         longest_i = j - no_triad_i;
+         longest_i = j - no_third_i;
          tonic_i = i;
        }
     }
@@ -448,11 +579,11 @@ Chord::find_tonic_i () const
   int biggest_i = 0;
   //  if (longest_i)
   if (longest_i <= 1)
-    for (int i = 0; i < pitch_arr_.size (); i++)
+    for (int i = 0; i < pitch_arr_p->size (); i++)
       {
-       int gap = pitch_arr_[i].notename_i_
-         - pitch_arr_[(i - 1 + pitch_arr_.size ()) 
-         % pitch_arr_.size ()].notename_i_;
+       int gap = (*pitch_arr_p)[i].notename_i_
+         - (*pitch_arr_p)[(i - 1 + pitch_arr_p->size ()) 
+         % pitch_arr_p->size ()].notename_i_;
        while (gap < 0)
          gap += 7;
        gap %= 7;
@@ -466,14 +597,14 @@ Chord::find_tonic_i () const
 }
 
 void
-Chord::rebuild_from_base (int base_i)
+Chord::rebuild_from_base (Array<Musical_pitch>* pitch_arr_p, int base_i)
 {
   assert (base_i >= 0);
   Musical_pitch last (0, 0, -5);
   Array<Musical_pitch> new_arr;
-  for (int i = 0; i < pitch_arr_.size (); i++)
+  for (int i = 0; i < pitch_arr_p->size (); i++)
     {
-      Musical_pitch p = pitch_arr_[(base_i + i) % pitch_arr_.size ()];
+      Musical_pitch p = (*pitch_arr_p)[(base_i + i) % pitch_arr_p->size ()];
       if (p < last)
        {
          p.octave_i_ = last.octave_i_;
@@ -483,43 +614,37 @@ Chord::rebuild_from_base (int base_i)
       new_arr.push (p);
       last = p;
     }
-  pitch_arr_ = new_arr;
+  *pitch_arr_p = new_arr;
 }
 
 void
-Chord::rebuild_insert_inversion (int tonic_i)
+Chord::rebuild_insert_inversion (Array<Musical_pitch>* pitch_arr_p, int tonic_i)
 {
   assert (tonic_i > 0);
-#if INVERSION_ADDED_AS_BASE
-  // inversion was added; don't insert
-  Musical_pitch inversion = pitch_arr_.get (0);
-  (void)inversion;
-#else
-  Musical_pitch inversion = pitch_arr_.get (0);
-  rebuild_from_base (tonic_i - 1);
-  if (pitch_arr_.size ())
+  Musical_pitch inversion = pitch_arr_p->get (0);
+  rebuild_from_base (pitch_arr_p, tonic_i - 1);
+  if (pitch_arr_p->size ())
     {
-      inversion.octave_i_ = pitch_arr_[0].octave_i_ - 1;
-      while (inversion < pitch_arr_[0])
+      inversion.octave_i_ = (*pitch_arr_p)[0].octave_i_ - 1;
+      while (inversion < (*pitch_arr_p)[0])
        inversion.octave_i_++;
     }
-  for (int i = 0; i < pitch_arr_.size (); i++)
-    if (pitch_arr_[i] > inversion)
+  for (int i = 0; i < pitch_arr_p->size (); i++)
+    if ((*pitch_arr_p)[i] > inversion)
       {
-       pitch_arr_.insert (inversion, i);
+       pitch_arr_p->insert (inversion, i);
        break;
       }
-#endif
 }
 
 void
-Chord::rebuild_with_bass (int bass_i)
+Chord::rebuild_with_bass (Array<Musical_pitch>* pitch_arr_p, int bass_i)
 {
   assert (bass_i >= 0);
-  Musical_pitch inversion = pitch_arr_.get (bass_i);
+  Musical_pitch bass = pitch_arr_p->get (bass_i);
   // is lowering fine, or should others be raised?
-  if (pitch_arr_.size ())
-    while (inversion > pitch_arr_[0])
-      inversion.octave_i_--;
-  pitch_arr_.insert (inversion, 0);
+  if (pitch_arr_p->size ())
+    while (bass > (*pitch_arr_p)[0])
+      bass.octave_i_--;
+  pitch_arr_p->insert (bass, 0);
 }
index 779197f70de681fb40fc6980d1cd82245b846b88..4843fae8e999b32668af8af6fe1660eddc4af931 100644 (file)
@@ -31,6 +31,8 @@ private:
   Link_array<Item> text_p_arr_;
   Array<Musical_pitch> rebuild_pitch_arr (int tonic_i) const;
   Tonic_req* tonic_req_;
+  Inversion_req* inversion_req_;
+  Bass_req* bass_req_;
 };
 
 #endif // CHORD_NAME_ENGRAVER_HH
index 9b38abbb41c41ac5b3f95f7605fba81c005a8532..871189fafc1c958deea2962691daf27cbb1c76a0 100644 (file)
 class Chord
 {
 public:
-  Chord (Array<Musical_pitch> pitch_arr);
-  Chord (Musical_pitch tonic, Array<Musical_pitch>* add_arr_p, Array<Musical_pitch>* sub_arr_p, Musical_pitch* inversion_p);
+  static int find_tonic_i (Array<Musical_pitch> const*);
+  static int find_pitch_i (Array<Musical_pitch> const*, Musical_pitch p);
+  static int find_notename_i (Array<Musical_pitch> const*, Musical_pitch p);
+  static Array<Musical_pitch> missing_thirds_pitch_arr (Array<Musical_pitch> const* pitch_arr_p);
+  static void rebuild_from_base (Array<Musical_pitch>*, int base_i);
+  static void rebuild_insert_inversion (Array<Musical_pitch>*, int tonic_i);
+  static void rebuild_transpose (Array<Musical_pitch>*, Musical_pitch tonic);
+  static void rebuild_with_bass (Array<Musical_pitch>*, int bass_i);
+  static int step_i (Musical_pitch tonic, Musical_pitch p);
 
-  void rebuild_from_base (int base_i);
-  void rebuild_insert_inversion (int tonic_i);
-  void rebuild_with_bass (int bass_i);
+  Chord (Array<Musical_pitch> pitch_arr, Musical_pitch* inversion_p, Musical_pitch* bass_p);
+  Chord (Chord const& chord);
+  ~Chord ();
 
-  String banter_str (Musical_pitch* inversion) const;
-  int find_tonic_i () const;
-  int find_pitch_i (Musical_pitch p) const;
-  int find_notename_i (Musical_pitch p) const;
+
+  Array<Musical_pitch> to_pitch_arr () const;
+
+  String banter_str () const;
   void find_additions_and_subtractions(Array<Musical_pitch>* add_arr_p, Array<Musical_pitch>* sub_arr_p) const;
 
   Array<Musical_pitch> pitch_arr_;
+  Musical_pitch* inversion_p_;
+  Musical_pitch* bass_p_;
 };
 
+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);
+
+Chord to_chord (Array<Musical_pitch> pitch_arr, Tonic_req* tonic_req, Inversion_req* inversion_req, Bass_req* bass_req, bool find_inversion_b);
+
 #endif // CHORD_HH
index 9e397a0ad20da14ee8b3002733c12327deaae64d..8db92ce5c2b49ce7b71567abc8cd79152e5a6bed 100644 (file)
@@ -44,6 +44,7 @@ struct Bar_column_engraver;
 struct Bar_engraver;
 struct Bar_req;
 struct Barcheck_req;
+struct Bass_req;
 struct Beam;
 struct Beam_engraver;
 struct Beaming_info;
@@ -101,6 +102,7 @@ struct Head_column;
 struct Idealspacing;
 struct Identifier;
 struct Input_file;
+struct Inversion_req;
 struct Item;
 struct Key;
 struct Key_change_req;
index b64f5eb65d22c8fa2449ac1387baa70709d109f8..963f6079fadc693ceaa4b546a2ef5f6d25ec1e2c 100644 (file)
@@ -97,7 +97,19 @@ protected:
 /// specify tonic of a chord
 struct Tonic_req : public Melodic_req
 {
-  VIRTUAL_COPY_CONS(Music);
+  VIRTUAL_COPY_CONS (Music);
+};
+
+/// specify inversion of a chord
+struct Inversion_req : public Melodic_req
+{
+  VIRTUAL_COPY_CONS (Music);
+};
+
+/// specify bass of a chord
+struct Bass_req : public Melodic_req
+{
+  VIRTUAL_COPY_CONS (Music);
 };
 
 /// Put a note of specified type, height, and with accidental on the staff.
index 301eb358ee4a4aa3114688725ddb17f528447a89..01944e6e2d6b1769943646c2768b8a7abbae9f76 100644 (file)
@@ -67,7 +67,7 @@ private:
   String init_str_;
 
   Simultaneous_music * get_note_element (Note_req * ,Duration *);
-  Simultaneous_music * get_chord (Musical_pitch, Array<Musical_pitch>*, Array<Musical_pitch>*, Musical_pitch*, Duration);
+  Simultaneous_music * get_chord (Musical_pitch tonic, Array<Musical_pitch>* add_arr_p, Array<Musical_pitch>* sub_arr_p, Musical_pitch* inversion_p, Musical_pitch* bass_p, Duration d);
   Simultaneous_music* get_rest_element (String, Duration *);
   Simultaneous_music* get_word_element (String, Duration*);
   String notename_str (Melodic_req* melodic);
index 7c09d492e9c9cc4494b3cea5cbb4e3a939e813a6..83beb3eb8e048e2b5b8b79910ae072ca1f122346 100644 (file)
@@ -359,6 +359,12 @@ HYPHEN             --
        -  {
                return CHORD_MINUS;
        }
+       :  {
+               return CHORD_COLON;
+       }
+       \/\+ {
+               return CHORD_BASS;
+       }
        \^  {
                return CHORD_CARET;
        }
index 11ae2eeda45ac03929a2b17894f45bf7b3e8e4c8..3444be33839a7ab4aaa78e555040d4ba0ada7646 100644 (file)
@@ -163,20 +163,37 @@ My_lily_parser::get_rest_element (String s,  Duration * duration_p)
 
 // junk me
 Simultaneous_music *
-My_lily_parser::get_chord (Musical_pitch tonic, Array<Musical_pitch>* add_arr_p, Array<Musical_pitch>* sub_arr_p, Musical_pitch* inversion_p, Duration d)
+My_lily_parser::get_chord (Musical_pitch tonic, Array<Musical_pitch>* add_arr_p, Array<Musical_pitch>* sub_arr_p, Musical_pitch* inversion_p, Musical_pitch* bass_p, Duration d)
 {
   Simultaneous_music*v = new Request_chord;
   v->set_spot (here_input ());
 
-  Chord chord (tonic, add_arr_p, sub_arr_p, inversion_p);
+  Chord chord = to_chord (tonic, add_arr_p, sub_arr_p, inversion_p, bass_p);
 
   Tonic_req* t = new Tonic_req;
   t->pitch_ = tonic;
   v->add_music (t);
 
-  for (int i = 0; i < chord.pitch_arr_.size (); i++)
+  //urg
+  if (inversion_p
+      && Chord::find_notename_i (&chord.pitch_arr_, *inversion_p) > 0)
     {
-      Musical_pitch p = chord.pitch_arr_[i];
+      Inversion_req* i = new Inversion_req;
+      i->pitch_ = *inversion_p;
+      v->add_music (i);
+    }
+
+  if (bass_p)
+    {
+      Bass_req* b = new Bass_req;
+      b->pitch_ = *bass_p;
+      v->add_music (b);
+    }
+
+  Array<Musical_pitch> pitch_arr = chord.to_pitch_arr ();
+  for (int i = 0; i < pitch_arr.size (); i++)
+    {
+      Musical_pitch p = pitch_arr[i];
       Note_req* n = new Note_req;
       n->pitch_ = p;
       n->duration_ = d;
index d23ee6e80673032699620e31c63e845c1948dc14..74168092d48e8c50543d6a0c0ce94fd01ee5443f 100644 (file)
@@ -29,6 +29,14 @@ Note_heads_engraver::do_try_music (Music *m)
     {
       return true;
     }
+  else if (Inversion_req* i = dynamic_cast<Inversion_req*> (m))
+    {
+      return true;
+    }
+  else if (Bass_req* b = dynamic_cast<Bass_req*> (m))
+    {
+      return true;
+    }
   else if (Busy_playing_req * p = dynamic_cast<Busy_playing_req*> (m))
     {
       return notes_end_pq_.size ();
index f6c73ca83a1ab183394ce0b60b17d21c07a37941..6c02b4967e569b5d2e283e4dbf467fecb8431343 100644 (file)
@@ -187,7 +187,8 @@ yylex (YYSTYPE *s,  void * v_l)
 %token VERSION
 
 /* escaped */
-%token E_EXCLAMATION E_SMALLER E_BIGGER E_CHAR CHORD_MINUS CHORD_CARET 
+%token E_CHAR E_EXCLAMATION E_SMALLER E_BIGGER 
+%token CHORD_BASS CHORD_COLON CHORD_MINUS CHORD_CARET 
 
 %type <i>      exclamations questions
 %token <i>     DIGIT
@@ -236,7 +237,7 @@ yylex (YYSTYPE *s,  void * v_l)
 %type <pitch_arr>      pitch_list
 %type <music>  chord
 %type <pitch_arr>      chord_additions chord_subtractions chord_notes chord_step
-%type <pitch>  chord_note chord_inversion
+%type <pitch>  chord_note chord_inversion chord_bass
 %type <midi>   midi_block midi_body
 %type <duration>       duration_length
 
@@ -1455,15 +1456,15 @@ simple_element:
        ;
 
 chord:
-       steno_tonic_pitch optional_notemode_duration chord_additions chord_subtractions chord_inversion {
-                $$ = THIS->get_chord (*$1, $3, $4, $5, *$2);
+       steno_tonic_pitch optional_notemode_duration chord_additions chord_subtractions chord_inversion chord_bass {
+                $$ = THIS->get_chord (*$1, $3, $4, $5, $6, *$2);
         };
 
 chord_additions: 
        {
                $$ = new Array<Musical_pitch>;
        } 
-       | CHORD_MINUS chord_notes {
+       | CHORD_COLON chord_notes {
                $$ = $2;
        }
        ;
@@ -1493,7 +1494,18 @@ chord_inversion:
                $$ = 0;
        }
        | '/' steno_tonic_pitch {
-               $$ = $2
+               $$ = $2;
+               $$->set_spot (THIS->here_input ());
+       }
+       ;
+
+chord_bass:
+       {
+               $$ = 0;
+       }
+       | CHORD_BASS steno_tonic_pitch {
+               $$ = $2;
+               $$->set_spot (THIS->here_input ());
        }
        ;
 
index 48cc2f09f413939007c534c26829abc95d946238..ef3942dd66576cf82a7927e22077c095c1b5be33 100644 (file)
@@ -6,7 +6,9 @@
        m       = \musicalpitch { 0 2 -1 }
        min     = \musicalpitch { 0 2 -1 }
        aug     = \musicalpitch { 0 4 1 }
-       dim     = \musicalpitch { 0 4 -1 }
+       % urg!
+       % dim   = \musicalpitch { -100 4 -1 }
+       dim     = \musicalpitch { -100 2 -1 }
        % urg, not actually a chord-modifier, but it works
        % c7 -> <c bes>, c 7+ -> c b
        maj     = \musicalpitch { 0 6 1 }