From 1ecbcc5337a3ea4d347b197c60e9c95ea11ad93e Mon Sep 17 00:00:00 2001 From: Jan Nieuwenhuizen Date: Fri, 4 Dec 1998 02:57:43 +0100 Subject: [PATCH] patch::: 1.1.10.jcn1: koorden pl 10.jcn1 - input/test/chords.ly - \type ChordNames and chord-name-engraver.* - chords mode: \chords { @c; @d7; } --- NEWS | 5 ++ VERSION | 2 +- init/engraver.ly | 19 ++++++ input/test/chords.ly | 27 ++++++++ lily/chord-name-engraver.cc | 92 +++++++++++++++++++++++++ lily/include/chord-name-engraver.hh | 35 ++++++++++ lily/include/lily-proto.hh | 5 +- lily/include/lyric-engraver.hh | 1 - lily/include/my-lily-lexer.hh | 2 + lily/include/my-lily-parser.hh | 1 + lily/lexer.ll | 47 +++++++++---- lily/lyric-engraver.cc | 5 -- lily/my-lily-lexer.cc | 1 + lily/my-lily-parser.cc | 102 ++++++++++++++++++++++++++++ lily/parser.yy | 68 ++++++++++++++++++- 15 files changed, 389 insertions(+), 23 deletions(-) create mode 100644 input/test/chords.ly create mode 100644 lily/chord-name-engraver.cc create mode 100644 lily/include/chord-name-engraver.hh diff --git a/NEWS b/NEWS index 11db1ed873..236d384bbc 100644 --- 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; @d7; } + pl 10 pl 9.jcn3 diff --git a/VERSION b/VERSION index 39690bc759..11d2f10b15 100644 --- 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. diff --git a/init/engraver.ly b/init/engraver.ly index a2c9db5990..ff73fab9e5 100644 --- a/init/engraver.ly +++ b/init/engraver.ly @@ -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 index 0000000000..31ef252e35 --- /dev/null +++ b/input/test/chords.ly @@ -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 index 0000000000..ba4fe386df --- /dev/null +++ b/lily/chord-name-engraver.cc @@ -0,0 +1,92 @@ +/* + chord-name-engraver.cc -- implement Chord_name_engraver + + source file of the GNU LilyPond music typesetter + + (c) 1998 Jan Nieuwenhuizen +*/ + +#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 (i.req_l_)) + pitch_arr_.push (n->pitch_); +} + +bool +Chord_name_engraver::do_try_music (Music* m) +{ + if (Note_req* n = dynamic_cast (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 index 0000000000..f7b44b588f --- /dev/null +++ b/lily/include/chord-name-engraver.hh @@ -0,0 +1,35 @@ +/* + chord-name-engraver.hh -- declare Chord_name_engraver + + source file of the GNU LilyPond music typesetter + + (c) 1998 Jan Nieuwenhuizen +*/ + +#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 pitch_arr_; + Link_array text_p_arr_; +}; + +#endif // CHORD_NAME_ENGRAVER_HH diff --git a/lily/include/lily-proto.hh b/lily/include/lily-proto.hh index 20a49da261..3bd510b231 100644 --- a/lily/include/lily-proto.hh +++ b/lily/include/lily-proto.hh @@ -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; diff --git a/lily/include/lyric-engraver.hh b/lily/include/lyric-engraver.hh index 15b5f510e0..0087e21e5e 100644 --- a/lily/include/lyric-engraver.hh +++ b/lily/include/lyric-engraver.hh @@ -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(); diff --git a/lily/include/my-lily-lexer.hh b/lily/include/my-lily-lexer.hh index 3030a09eb4..423a771278 100644 --- a/lily/include/my-lily-lexer.hh +++ b/lily/include/my-lily-lexer.hh @@ -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; }; diff --git a/lily/include/my-lily-parser.hh b/lily/include/my-lily-parser.hh index 4e82dc909e..7a414b4614 100644 --- a/lily/include/my-lily-parser.hh +++ b/lily/include/my-lily-parser.hh @@ -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*, Array*, 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); diff --git a/lily/lexer.ll b/lily/lexer.ll index 551cf48aec..514096c078 100644 --- a/lily/lexer.ll +++ b/lily/lexer.ll @@ -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 } -{ +{ "%{" { yy_push_state (longcomment); } @@ -136,11 +137,11 @@ EXTENDER [_][_] } -\\maininput { +\\maininput { start_main_input (); } -\\include { +\\include { yy_push_state (incl); } \"[^"]*\";? { /* got the include file name */ @@ -184,29 +185,27 @@ EXTENDER [_][_] R { return MEASURES; } -\\\${BLACK}*{WHITE} { +\\\${BLACK}*{WHITE} { String s=YYText () + 2; s=s.left_str (s.length_i () - 1); return scan_escaped_word (s); } -\${BLACK}*{WHITE} { +\${BLACK}*{WHITE} { String s=YYText () + 1; s=s.left_str (s.length_i () - 1); return scan_bare_word (s); } -\\\${BLACK}* { // backup rule +\\\${BLACK}* { // backup rule cerr << _ ("white expected") << endl; exit (1); } -\${BLACK}* { // backup rule +\${BLACK}* { // backup rule cerr << _ ("white expected") << endl; exit (1); } { - {ALPHAWORD} { return scan_bare_word (YYText ()); - } {NOTECOMMAND} { @@ -249,7 +248,6 @@ EXTENDER [_][_] } { - \" { start_quote (); } @@ -281,6 +279,18 @@ EXTENDER [_][_] return yylval.c = YYText ()[0]; } } +{ + {ALPHAWORD} { + return scan_bare_word (YYText ()); + } + {UNSIGNED} { + yylval.i = String_convert::dec2_i (String (YYText ())); + return UNSIGNED; + } + . { + return yylval.c = YYText ()[0]; + } +} <> { DOUT << "<>"; @@ -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 { diff --git a/lily/lyric-engraver.cc b/lily/lyric-engraver.cc index bac629b385..9fb403f2da 100644 --- a/lily/lyric-engraver.cc +++ b/lily/lyric-engraver.cc @@ -65,11 +65,6 @@ Lyric_engraver::do_process_requests() } } -void -Lyric_engraver::do_post_move_processing() -{ -} - void Lyric_engraver::do_pre_move_processing() { diff --git a/lily/my-lily-lexer.cc b/lily/my-lily-lexer.cc index b87694b729..1e0b06c06a 100644 --- a/lily/my-lily-lexer.cc +++ b/lily/my-lily-lexer.cc @@ -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}, diff --git a/lily/my-lily-parser.cc b/lily/my-lily-parser.cc index 86270bf7c3..a411b3f9a1 100644 --- a/lily/my-lily-parser.cc +++ b/lily/my-lily-parser.cc @@ -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* add_arr_p, Array* 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 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) { diff --git a/lily/parser.yy b/lily/parser.yy index b2b807ac8f..e035a19450 100644 --- a/lily/parser.yy +++ b/lily/parser.yy @@ -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 explicit_musical_pitch steno_musical_pitch musical_pitch absolute_musical_pitch %type steno_notepitch %type pitch_list +%type chord +%type chord_additions chord_subtractions +%type chord_note %type midi_block midi_body %type 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; + } + | 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; + } + | '^' chord_subtractions chord_note { + $2->push (*$3); + $$ = $2; + } + ; /* UTILITIES -- 2.39.5