]> git.donarmstrong.com Git - lilypond.git/commitdiff
patch::: 1.1.10.jcn1: koorden
authorJan Nieuwenhuizen <janneke@gnu.org>
Fri, 4 Dec 1998 01:57:43 +0000 (02:57 +0100)
committerJan Nieuwenhuizen <janneke@gnu.org>
Fri, 4 Dec 1998 01:57:43 +0000 (02:57 +0100)
pl 10.jcn1
- input/test/chords.ly
- \type ChordNames and chord-name-engraver.*
- chords mode: \chords { <c e g> @c; @d7; }

15 files changed:
NEWS
VERSION
init/engraver.ly
input/test/chords.ly [new file with mode: 0644]
lily/chord-name-engraver.cc [new file with mode: 0644]
lily/include/chord-name-engraver.hh [new file with mode: 0644]
lily/include/lily-proto.hh
lily/include/lyric-engraver.hh
lily/include/my-lily-lexer.hh
lily/include/my-lily-parser.hh
lily/lexer.ll
lily/lyric-engraver.cc
lily/my-lily-lexer.cc
lily/my-lily-parser.cc
lily/parser.yy

diff --git a/NEWS b/NEWS
index 11db1ed873048c2cc58f91cf5570ce091e359f26..236d384bbce0730a7186283f97c57a8acfecbd0d 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,8 @@
+pl 10.jcn1
+       - input/test/chords.ly
+       - \type ChordNames and chord-name-engraver.*
+       - chords mode: \chords { <c e g> @c; @d7; }
+
 pl 10
 
 pl 9.jcn3
diff --git a/VERSION b/VERSION
index 39690bc759972be74583e6ef52facb6e32983322..11d2f10b15e571923f43cb28422d36b0591289c5 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -2,7 +2,7 @@ PACKAGE_NAME=LilyPond
 MAJOR_VERSION=1
 MINOR_VERSION=1
 PATCH_LEVEL=10
-MY_PATCH_LEVEL=
+MY_PATCH_LEVEL=jcn1
 
 # use the above to send patches: MY_PATCH_LEVEL is always empty for a
 # released version.
index a2c9db5990218e42a3f290174420dd401f83e93f..ff73fab9e569029f66afc8ed3d15412c52877ffb 100644 (file)
@@ -68,6 +68,7 @@ StaffContext=\translator {
        \accepts "RhythmicStaff";
        \accepts "GrandStaff";
        \accepts "Lyrics";
+       \accepts "ChordNames";
 }
 
 
@@ -132,6 +133,7 @@ GrandStaffContext=\translator{
        \accepts "RhythmicStaff";
        \accepts "GrandStaff";
        \accepts "Lyrics";
+       \accepts "ChordNames";
 }
 
 \translator{
@@ -152,6 +154,21 @@ GrandStaffContext=\translator{
        \accepts "LyricVoice";
 }
 
+\translator{
+       \type "Line_group_engraver_group";
+
+       \name ChordNameVoice ;
+       \consists "Separating_line_group_engraver";
+       \consists "Chord_name_engraver";
+}
+
+\translator {
+       \type "Line_group_engraver_group";
+       \name ChordNames;
+       \consists "Vertical_align_engraver";
+       \accepts "ChordNameVoice";
+}
+
 ScoreContext = \translator {
        \type Score_engraver;
        \name Score;
@@ -169,6 +186,7 @@ ScoreContext = \translator {
        \accepts "Staff";
        \accepts "RhythmicStaff";       
        \accepts "Lyrics";
+       \accepts "ChordNames";
        \accepts "GrandStaff";
        \accepts "ChoirStaff";
 };
@@ -259,5 +277,6 @@ OrchestralScoreContext= \translator {
        \accepts "Staff";
        \accepts "RhythmicStaff";       
        \accepts "Lyrics";
+       \accepts "ChordNames";
        \accepts "GrandStaff";
 };
diff --git a/input/test/chords.ly b/input/test/chords.ly
new file mode 100644 (file)
index 0000000..31ef252
--- /dev/null
@@ -0,0 +1,27 @@
+%{
+Would this be acceptable/good enough/convenient for entry?
+
+   Convention/Standard    Logical/Lily(?)
+   
+   C#                     cis
+   Cb                     ces
+   Cm/Cmin                c3-     
+   Caug                   c5+
+   Cdim                   c5-
+   Cmaj7                  c7
+   C7                     c7-
+   Csus/Csus4             c4^3
+%}
+
+scales = \notes\transpose c''\chords{
+               @c; @g; @d; @a; @e; @b; @fis;
+               @c; @f; @bes; @es; @as; @des; @ges;
+               @c6; @c7; @c9; @c11; @c13;
+       }
+
+\score{
+       <
+               \type ChordNames \scales
+               \type Staff \scales
+       >
+}
diff --git a/lily/chord-name-engraver.cc b/lily/chord-name-engraver.cc
new file mode 100644 (file)
index 0000000..ba4fe38
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+  chord-name-engraver.cc -- implement Chord_name_engraver
+
+  source file of the GNU LilyPond music typesetter
+
+  (c) 1998 Jan Nieuwenhuizen <janneke@gnu.org>
+*/
+
+#include "chord-name-engraver.hh"
+#include "musical-request.hh"
+#include "text-item.hh"
+#include "paper-def.hh"
+#include "lookup.hh"
+#include "paper-def.hh"
+#include "main.hh"
+#include "dimensions.hh"
+
+ADD_THIS_TRANSLATOR (Chord_name_engraver);
+
+Chord_name_engraver::Chord_name_engraver ()
+{
+}
+
+void
+Chord_name_engraver::acknowledge_element (Score_element_info i)
+{
+  if (Note_req* n = dynamic_cast<Note_req*> (i.req_l_))
+    pitch_arr_.push (n->pitch_);
+}
+
+bool
+Chord_name_engraver::do_try_music (Music* m)
+{
+  if (Note_req* n = dynamic_cast<Note_req*> (m))
+    {
+      pitch_arr_.push (n->pitch_);
+      return true;
+    }
+  return false;
+}
+
+void
+Chord_name_engraver::do_process_requests ()
+{
+  if (text_p_arr_.size ())
+    return;
+  if (!pitch_arr_.size ())
+    return;
+
+  Scalar style = get_property ("textstyle");
+  Scalar alignment = get_property ("textalignment");
+  Text_def* text_p = new Text_def;
+  text_p->align_dir_ = LEFT;
+  if (style.length_i ())
+    text_p->style_str_ = style;
+  if (alignment.isnum_b())
+    text_p->align_dir_= (Direction)(int)alignment;
+
+  Musical_pitch tonic = pitch_arr_[0];
+  text_p->text_str_ = tonic.str ();
+  for (int i=1; i < pitch_arr_.size (); i++)
+    {
+      Musical_pitch p = pitch_arr_[i];
+      int trap = (p.notename_i_ - tonic.notename_i_ + 8) % 8 + 1;
+      if (((trap != 3) && (trap != 5)) || (p.accidental_i_))
+        {
+         text_p->text_str_ += to_str ((p.notename_i_ - tonic.notename_i_ + 8) % 8 + 1);
+         if (p.accidental_i_)
+           text_p->text_str_ += p.accidental_i_ < 0 ? "-" : "+";
+         if (i + 1 < pitch_arr_.size ())
+           text_p->text_str_ += "/";
+       }
+    }
+
+  Text_item* item_p =  new Text_item (text_p);
+  item_p->dir_ = DOWN;
+  item_p->fat_b_ = true;
+  text_p_arr_.push (item_p);
+  announce_element (Score_element_info (item_p, 0));
+}
+
+void
+Chord_name_engraver::do_pre_move_processing ()
+{
+  for (int i=0; i < text_p_arr_.size (); i++)
+    {
+      typeset_element (text_p_arr_[i]);
+    }
+  text_p_arr_.clear ();
+  pitch_arr_.clear ();
+}
+
diff --git a/lily/include/chord-name-engraver.hh b/lily/include/chord-name-engraver.hh
new file mode 100644 (file)
index 0000000..f7b44b5
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+  chord-name-engraver.hh -- declare Chord_name_engraver
+
+  source file of the GNU LilyPond music typesetter
+
+  (c) 1998 Jan Nieuwenhuizen <janneke@gnu.org>
+*/
+
+#ifndef CHORD_NAME_ENGRAVER_HH
+#define CHORD_NAME_ENGRAVER_HH
+
+#include "engraver.hh"
+#include "array.hh"
+#include "musical-pitch.hh"
+
+#include "lily-proto.hh"
+
+class Chord_name_engraver : public Engraver 
+{
+protected:
+  virtual void do_pre_move_processing ();
+  virtual void acknowledge_element (Score_element_info i);
+  virtual void do_process_requests ();
+  virtual bool do_try_music (Music* m);
+
+public:
+  Chord_name_engraver ();
+  VIRTUAL_COPY_CONS (Translator);
+
+private:
+  Array<Musical_pitch> pitch_arr_;
+  Link_array<Text_item> text_p_arr_;
+};
+
+#endif // CHORD_NAME_ENGRAVER_HH
index 20a49da261ce2ca8fa1c3915439a49e4cb4edf02..3bd510b23118e3580a581604dee98a8c47c82d7a 100644 (file)
@@ -46,7 +46,7 @@ struct Break_req;
 struct Cadenza_req;
 struct Change_iterator;
 struct Change_translator;
-struct Simultaneous_music;
+struct Chord_name_engraver;
 struct Clef_change_req;
 struct Clef_item;
 struct Clef_engraver;
@@ -186,7 +186,6 @@ struct Rhythmic_grouping;
 struct Rhythmic_head;
 struct Rhythmic_grouping_req;
 struct Rhythmic_req;
-struct Single_malt_grouping_item;
 struct Scope;
 struct Separating_group_spanner;
 struct Score;
@@ -200,6 +199,8 @@ struct Script_def;
 struct Script_engraver;
 struct Script_req;
 struct Simple_music;
+struct Simultaneous_music;
+struct Single_malt_grouping_item;
 struct Skip_req;
 struct Slur;
 struct Slur_engraver;
index 15b5f510e04b345e904921edd027366371a51dcf..0087e21e5e7e20de9fe5f76370d27107bdf2046f 100644 (file)
@@ -20,7 +20,6 @@ protected:
   virtual void do_pre_move_processing();
   virtual bool do_try_music (Music*);
   virtual void do_process_requests();
-  virtual void do_post_move_processing();
 
 public:
   Lyric_engraver();
index 3030a09eb45871a36e5981af2fdddd8f161697a8..423a77127885d8837709f694271f492f04391c1c 100644 (file)
@@ -50,6 +50,7 @@ public:
   Identifier*lookup_identifier (String s);
   Musical_pitch lookup_pitch (String s);
   void push_note_state();
+  void push_chord_state();
   void push_lyric_state();
   void pop_state();
   void LexerError (char const *);
@@ -60,6 +61,7 @@ public:
   void print_declarations (bool init_b) const;
   void add_notename (String, Musical_pitch);
   bool note_state_b() const;
+  bool chord_state_b() const;
   bool lyric_state_b() const;
 };
 
index 4e82dc909e19c1bdbd5fb6123ac047ae371b7d43..7a414b4614b4f28ef26f199b307e258bb2b1d881 100644 (file)
@@ -27,6 +27,7 @@ class My_lily_parser {
   void add_requests (Simultaneous_music*v);
 
   Simultaneous_music * get_note_element (Note_req * ,Duration *);
+  Simultaneous_music * get_chord (Musical_pitch, Array<Musical_pitch>*, Array<Musical_pitch>*, Duration);
   Simultaneous_music* get_rest_element (String, Duration *);
   Simultaneous_music* get_word_element (String, Duration*);
   Melodic_req* get_melodic_req (Melodic_req* melodic, int quotes);
index 551cf48aec682c7a4f755e35fae5912a76c05bf6..514096c078a268a614a26f11cef24645145661da 100644 (file)
@@ -62,6 +62,7 @@ LYRICS                ({AA}|{TEX})[^0-9 \t\n\f]*
 %option never-interactive 
 %option warn
 
+%x chords
 %x incl
 %x lyrics
 %x notes
@@ -102,7 +103,7 @@ EXTENDER    [_][_]
        // windows-suck-suck-suck
 }
 
-<notes,incl,INITIAL,lyrics>{
+<INITIAL,chords,incl,lyrics,notes>{
   "%{" {
        yy_push_state (longcomment);
   }
@@ -136,11 +137,11 @@ EXTENDER  [_][_]
 }
 
 
-<notes,INITIAL,lyrics>\\maininput           {
+<INITIAL,chords,lyrics,notes>\\maininput           {
        start_main_input ();
 }
 
-<notes,INITIAL,lyrics>\\include           {
+<INITIAL,chords,lyrics,notes>\\include           {
        yy_push_state (incl);
 }
 <incl>\"[^"]*\";?   { /* got the include file name */
@@ -184,29 +185,27 @@ EXTENDER  [_][_]
 <notes>R               {
        return MEASURES;
 }
-<INITIAL,lyrics,notes>\\\${BLACK}*{WHITE}      {
+<INITIAL,chords,lyrics,notes>\\\${BLACK}*{WHITE}       {
        String s=YYText () + 2;
        s=s.left_str (s.length_i () - 1);
        return scan_escaped_word (s); 
 }
-<INITIAL,lyrics,notes>\${BLACK}*{WHITE}                {
+<INITIAL,chords,lyrics,notes>\${BLACK}*{WHITE}         {
        String s=YYText () + 1;
        s=s.left_str (s.length_i () - 1);
        return scan_bare_word (s);
 }
-<INITIAL,lyrics,notes>\\\${BLACK}*             { // backup rule
+<INITIAL,chords,lyrics,notes>\\\${BLACK}*              { // backup rule
        cerr << _ ("white expected") << endl;
        exit (1);
 }
-<INITIAL,lyrics,notes>\${BLACK}*               { // backup rule
+<INITIAL,chords,lyrics,notes>\${BLACK}*                { // backup rule
        cerr << _ ("white expected") << endl;
        exit (1);
 }
 <notes>{
-
        {ALPHAWORD}     {
                return scan_bare_word (YYText ());
-
        }
 
        {NOTECOMMAND}   {
@@ -249,7 +248,6 @@ EXTENDER    [_][_]
 }
 
 <lyrics>{
-
        \" {
                start_quote ();
        }
@@ -281,6 +279,18 @@ EXTENDER   [_][_]
                return yylval.c = YYText ()[0];
        }
 }
+<chords>{
+       {ALPHAWORD}     {
+               return scan_bare_word (YYText ());
+       }
+       {UNSIGNED}              {
+               yylval.i = String_convert::dec2_i (String (YYText ()));
+               return UNSIGNED;
+       }
+       . {
+               return yylval.c = YYText ()[0];
+       }
+}
 
 <<EOF>> {
        DOUT << "<<eof>>";
@@ -363,11 +373,18 @@ My_lily_lexer::push_note_state ()
        yy_push_state (notes);
 }
 
+void
+My_lily_lexer::push_chord_state ()
+{
+       yy_push_state (chords);
+}
+
 void
 My_lily_lexer::push_lyric_state ()
 {
        yy_push_state (lyrics);
 }
+
 void
 My_lily_lexer::pop_state ()
 {
@@ -389,7 +406,7 @@ My_lily_lexer::scan_escaped_word (String str)
                yylval.id = id;
                return id->token_code_i_;
        }
-       if (YYSTATE != notes) {
+       if ((YYSTATE != notes) && (YYSTATE != chords)) {
                if (notename_b (str))
                        {
                        yylval.pitch = new Musical_pitch (lookup_pitch (str));
@@ -412,7 +429,7 @@ int
 My_lily_lexer::scan_bare_word (String str)
 {
        DOUT << "word: `" << str<< "'\n";       
-       if (YYSTATE == notes){
+       if ((YYSTATE == notes) || (YYSTATE == chords)) {
                if (notename_b (str)) {
                    DOUT << "(notename)\n";
                    yylval.pitch = new Musical_pitch (lookup_pitch (str));
@@ -432,6 +449,12 @@ My_lily_lexer::note_state_b () const
        return YY_START == notes;
 }
 
+bool
+My_lily_lexer::chord_state_b () const
+{
+       return YY_START == chords;
+}
+
 bool
 My_lily_lexer::lyric_state_b () const
 {
index bac629b38578ea4fb4b76bb4551a6aacc30aa9f1..9fb403f2da0d2c264553e05c6f687017515f0bf5 100644 (file)
@@ -65,11 +65,6 @@ Lyric_engraver::do_process_requests()
     }
 }
 
-void
-Lyric_engraver::do_post_move_processing()
-{
-}
-
 void
 Lyric_engraver::do_pre_move_processing()
 {
index b87694b7294e746e3543190a37d7bfb153b371b0..1e0b06c06a5768c8d590f3749a120e3bb7c5a017 100644 (file)
@@ -28,6 +28,7 @@ static Keyword_ent the_key_tab[]={
   {"alternative", ALTERNATIVE},
   {"bar", BAR},
   {"cadenza", CADENZA},
+  {"chords", CHORDS},
   {"clef", CLEF},
   {"cm", CM_T},
   {"consists", CONSISTS},
index 86270bf7c38fc8b368f448da97e6a9c9ecb134cd..a411b3f9a1ab5b1c24cd17ad2aeb309f8c136fd7 100644 (file)
@@ -157,6 +157,108 @@ My_lily_parser::get_rest_element (String s,  Duration * duration_p)
   return velt_p;
 }
 
+Simultaneous_music *
+My_lily_parser::get_chord (Musical_pitch tonic, Array<Musical_pitch>* add_arr_p, Array<Musical_pitch>* sub_arr_p, Duration d)
+{
+  Simultaneous_music*v = new Request_chord;
+  v->set_spot (here_input ());
+
+  Note_req* n = new Note_req;
+  n->pitch_ = tonic;
+  n->duration_ = d;
+  v->add_music (n);
+
+  for (int i = 0; i < add_arr_p->size (); i++)
+    {
+      Musical_pitch p = tonic;
+      p.transpose ((*add_arr_p)[i]);
+      (*add_arr_p)[i] = p;
+    }
+  add_arr_p->sort (Musical_pitch::compare);
+  for (int i = 0; i < sub_arr_p->size (); i++)
+    {
+      Musical_pitch p = tonic;
+      p.transpose ((*sub_arr_p)[i]);
+      (*sub_arr_p)[i] = p;
+    }
+  sub_arr_p->sort (Musical_pitch::compare);
+
+  Musical_pitch third;
+  third.notename_i_ = 2;
+
+  Musical_pitch mthird;
+  mthird.notename_i_ = 2;
+  mthird.accidental_i_ = -1;
+
+  Musical_pitch missing;
+  missing = tonic;
+  missing.transpose (third);
+
+  Musical_pitch p;
+  p = tonic;
+  p.transpose (third);
+  p.transpose (mthird);
+
+  /*
+   must have minimum at 5 (3 is added automatically as missing)
+   */
+  if (!add_arr_p->size () 
+    || ((add_arr_p->size () == 1) && 
+         ((add_arr_p->top ().notename_i_ != p.notename_i_)
+           || (add_arr_p->top () < p))))
+    add_arr_p->push (p);
+
+  Array<Musical_pitch> triads;
+  triads.push (third);   // c e 
+  triads.push (mthird);  // d f 
+  triads.push (mthird);  // e g 
+  triads.push (third);   // f a 
+  triads.push (third);   // g b 
+  triads.push (mthird);  // a c 
+  triads.push (mthird);  // b d 
+
+  /*
+   add missing triads
+   */
+  for (int i = 0; i < add_arr_p->size (); i++)
+    {
+      Musical_pitch p = (*add_arr_p)[i];
+      if ((p > missing) && (p.notename_i_ != missing.notename_i_))
+        while ((p > missing) && (p.notename_i_ != missing.notename_i_))
+         {
+           add_arr_p->insert (missing, i++);
+           missing.transpose (triads[(missing.notename_i_ - tonic.notename_i_ + 8) % 8]);
+         }
+       else
+         i++;
+    }
+
+  /*
+   add all that aren't subtracted
+   */
+  for (int i = 0; i < add_arr_p->size (); i++)
+    {
+      Musical_pitch p = (*add_arr_p)[i];
+      Note_req* n = new Note_req;
+      n->pitch_ = p;
+      n->duration_ = d;
+      for (int j = 0; j < sub_arr_p->size (); j++)
+        {
+         if (p == (*sub_arr_p)[j])
+           {
+             delete n;
+             n = 0;
+             break;
+           }
+       }
+      if (n)
+       v->add_music (n);
+    }
+
+  v->set_spot (here_input ());
+  return v;
+}
+
 Simultaneous_music *
 My_lily_parser::get_note_element (Note_req *rq, Duration * duration_p)
 {
index b2b807ac8f76a50beb2f6525a8f71dc4b051e638..e035a19450593362fc3bb8e8b19fa5a6324e6baa 100644 (file)
@@ -163,6 +163,7 @@ yylex (YYSTYPE *s,  void * v_l)
 %token BAR
 %token BEAMPLET
 %token CADENZA
+%token CHORDS
 %token CLEF
 %token CM_T
 %token CONSISTS
@@ -264,6 +265,9 @@ yylex (YYSTYPE *s,  void * v_l)
 %type <pitch>   explicit_musical_pitch steno_musical_pitch musical_pitch absolute_musical_pitch
 %type <notereq>        steno_notepitch
 %type <pitch_arr>      pitch_list
+%type <music>  chord
+%type <pitch_arr>       chord_additions chord_subtractions
+%type <pitch>           chord_note
 %type <midi>   midi_block midi_body
 %type <duration>       duration_length
 
@@ -807,7 +811,13 @@ Composite_music:
                { $$ = $3;
                  THIS->lexer_p_->pop_state ();
                }
-
+       | CHORDS
+               { THIS->lexer_p_->push_chord_state (); }
+       Music
+               {
+                 $$ = $3;
+                 THIS->lexer_p_->pop_state ();
+       }
        | LYRICS
                { THIS->lexer_p_->push_lyric_state (); }
        Music
@@ -1400,7 +1410,8 @@ abbrev_type:
 
 simple_element:
        steno_notepitch notemode_duration  {
-               if (!THIS->lexer_p_->note_state_b ())
+               if (!THIS->lexer_p_->note_state_b ()
+                 && !THIS->lexer_p_->chord_state_b ())
                        THIS->parser_error (_ ("have to be in Note mode for notes"));
                $1->duration_ = *$2;
                $$ = THIS->get_note_element ($1, $2);
@@ -1425,8 +1436,61 @@ simple_element:
                $$ = THIS->get_word_element (*$1, $2);
                delete $1;
        }
+       | '@' chord ';' {
+               if (!THIS->lexer_p_->chord_state_b ())
+                       THIS->parser_error (_ ("have to be in Chord mode for chords"));
+               $$ = $2;
+       }
+       ;
+
+
+chord:
+        NOTENAME_PITCH chord_additions chord_subtractions {
+               Duration d;
+               d.durlog_i_ = 0;
+                $$ = THIS->get_chord (*$1, $2, $3, d);
+        };
+
+chord_additions:
+       {
+               $$ = new Array<Musical_pitch>;
+       } 
+       | chord_additions chord_note {
+               $1->push (*$2);
+               $$ = $1;
+       }
        ;
 
+chord_note:
+        UNSIGNED {
+               $$ = new Musical_pitch;
+               $$->notename_i_ = ($1 - 1) % 8;
+               $$->octave_i_ = $1 > 7 ? 1 : 0;
+               $$->accidental_i_ = 0;
+        } 
+       | UNSIGNED '+' {
+               $$ = new Musical_pitch;
+               $$->notename_i_ = ($1 - 1) % 8;
+               $$->octave_i_ = $1 > 7 ? 1 : 0;
+               $$->accidental_i_ = 1;
+       }
+       | UNSIGNED '-' {
+               $$ = new Musical_pitch;
+               $$->notename_i_ = ($1 - 1) % 8;
+               $$->octave_i_ = $1 > 7 ? 1 : 0;
+               $$->accidental_i_ = -1;
+       }
+        ;
+
+chord_subtractions:
+       {
+               $$ = new Array<Musical_pitch>;
+       }
+       | '^' chord_subtractions chord_note {
+               $2->push (*$3);
+               $$ = $2;
+       }
+       ;
 
 /*
        UTILITIES