From 7ee3fdda44c06c44a3fbb88cd9e2d5bb3813b533 Mon Sep 17 00:00:00 2001 From: hanwen Date: Tue, 28 May 2002 23:04:46 +0000 Subject: [PATCH] jiba tab --- ChangeLog | 7 ++ Documentation/topdocs/AUTHORS.texi | 5 +- input/test/tablature.ly | 16 +++ lily/include/stem.hh | 1 + lily/pitch.cc | 11 +- lily/stem.cc | 34 ++++++- lily/tab-note-heads-engraver.cc | 158 +++++++++++++++++++++++++++++ ly/engraver-init.ly | 37 ++++++- ly/params-init.ly | 3 +- scm/grob-description.scm | 12 +++ scm/grob-property-description.scm | 4 + scm/output-lib.scm | 30 ++++++ 12 files changed, 312 insertions(+), 6 deletions(-) create mode 100644 input/test/tablature.ly create mode 100644 lily/tab-note-heads-engraver.cc diff --git a/ChangeLog b/ChangeLog index 085232038d..78e5a84452 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2002-05-29 Han-Wen + + * ly/engraver-init.ly (TabStaffContext): + enable TabStaff by default. + + * Tablature support by Jean-Baptiste Lamy + 2002-05-28 Jan Nieuwenhuizen * config.hh.in: Remove duplicate DIR_DATADIR entry. diff --git a/Documentation/topdocs/AUTHORS.texi b/Documentation/topdocs/AUTHORS.texi index e57ae509ac..ac1a013920 100644 --- a/Documentation/topdocs/AUTHORS.texi +++ b/Documentation/topdocs/AUTHORS.texi @@ -21,7 +21,10 @@ list is alphabetically ordered. @itemize @bullet @item @email{tca@@gnu.org, Tom Cato Amundsen}, - cembalo-partita in lilypond, accordion symbols, some lilypond-book.py + cembalo-partita in lilypond, accordion symbols, some +lilypond-book.py +@item @email{jiba@@tuxfamily.org,Jean-Baptiste Lamy } + Tablature support @item @email{matsb@@s3.kth.se, Mats Bengtsson}, @uref{http://www.s3.kth.se/~matsb/} lots of testing, fixes, general comments and contributions. diff --git a/input/test/tablature.ly b/input/test/tablature.ly new file mode 100644 index 0000000000..7f12df0131 --- /dev/null +++ b/input/test/tablature.ly @@ -0,0 +1,16 @@ +\version "1.3.146" + +%{ + +A sample tablature. + +Tablature is done by overriding the note-head formatting function, and +putting it on a 6-line staff. A special engraver takes care of going +from string-number + pitch to number. + +%} + +\score { + \notes \context TabStaff { ces'16-2 d'-2 e'8-2 g'2.-3 c'4-1 c''8-5 b'-5 } + + } diff --git a/lily/include/stem.hh b/lily/include/stem.hh index c48bade0cc..0e93750714 100644 --- a/lily/include/stem.hh +++ b/lily/include/stem.hh @@ -23,6 +23,7 @@ public: static void set_beaming (Grob*,int, Direction d); static Grob * beam_l (Grob*); static Grob * first_head (Grob*) ; + static Grob * last_head (Grob*) ; static Drul_array extremal_heads (Grob*); static Grob * support_head (Grob*) ; static void add_head (Grob*me, Grob*n); diff --git a/lily/pitch.cc b/lily/pitch.cc index 79a1b66635..fa06546afe 100644 --- a/lily/pitch.cc +++ b/lily/pitch.cc @@ -348,9 +348,16 @@ LY_DEFINE(pitch_semitones, "pitch-semitones", 1, 0, 0, "calculate the number of semitones of @var{p} from central C.") { Pitch *p = unsmob_pitch (pp); - SCM_ASSERT_TYPE(p, pp, SCM_ARG1, __FUNCTION__, "Pitch"); + SCM_ASSERT_TYPE(p, pp, SCM_ARG1, __FUNCTION__, "Pitch"); - int q = p->steps (); + int q = p->semitone_pitch (); + + // Was : + // + //int q = p->steps (); + // + // As the function is called "pitch_semitones", I assume it was a mistake ! + // Jiba return gh_int2scm (q); } diff --git a/lily/stem.cc b/lily/stem.cc index d0efe954f8..9d38d54d7d 100644 --- a/lily/stem.cc +++ b/lily/stem.cc @@ -165,6 +165,18 @@ Stem::first_head (Grob*me) return extremal_heads (me)[-d]; } +/* + The note head opposite to the first head. + */ +Grob* +Stem::last_head (Grob*me) +{ + Direction d = get_direction (me); + if (!d) + return 0; + return extremal_heads (me)[d]; +} + /* START is part where stem reaches `last' head. */ @@ -610,7 +622,27 @@ Stem::brew_molecule (SCM smob) Direction d = get_direction (me); - Real y1 = Staff_symbol_referencer::position_f (first_head (me)); + + Real y1; + + /* + This is required to avoid stems passing in tablature chords... + */ + + + /* + TODO: make the stem start a direction ? + + */ + if (to_boolean (me->get_grob_property ("avoid-note-head"))) + { + y1 = Staff_symbol_referencer::position_f (last_head (me)); + } + else + { + y1 = Staff_symbol_referencer::position_f (first_head (me)); + } + Real y2 = stem_end_position (me); Interval stem_y (y1 ? y1); diff --git a/lily/tab-note-heads-engraver.cc b/lily/tab-note-heads-engraver.cc new file mode 100644 index 0000000000..3d426a0d08 --- /dev/null +++ b/lily/tab-note-heads-engraver.cc @@ -0,0 +1,158 @@ +/* + head-grav.cc -- part of GNU LilyPond + + (c) 1997--2002 Han-Wen Nienhuys +*/ +#include +#include + +#include "rhythmic-head.hh" +#include "paper-def.hh" +#include "musical-request.hh" +#include "dots.hh" +#include "dot-column.hh" +#include "staff-symbol-referencer.hh" +#include "item.hh" +#include "score-engraver.hh" +#include "warn.hh" + +/** + make (guitar-like) tablature note + */ +class Tab_note_heads_engraver : public Engraver +{ + Link_array note_p_arr_; + + Link_array dot_p_arr_; + Link_array note_req_l_arr_; + + Link_array tabstring_req_arr_; + +public: + TRANSLATOR_DECLARATIONS(Tab_note_heads_engraver); + +protected: + virtual void start_translation_timestep (); + virtual bool try_music (Music *req_l) ; + virtual void process_music (); + + virtual void stop_translation_timestep (); +}; + + +Tab_note_heads_engraver::Tab_note_heads_engraver() +{ +} + +bool +Tab_note_heads_engraver::try_music (Music *m) +{ + if (Note_req * n =dynamic_cast (m)) + { + note_req_l_arr_.push (n); + return true; + } + else if (Text_script_req * ts = dynamic_cast (m)) + { + if (m->get_mus_property ("text-type") != ly_symbol2scm ("finger")) return false; + + //if (tabstring_req_arr_.size () < note_req_l_arr_.size ()) { + tabstring_req_arr_.push (ts); + //} + return true; + } + else if (dynamic_cast (m)) + { + return note_req_l_arr_.size (); + } + + return false; +} + + +void +Tab_note_heads_engraver::process_music () +{ + /* + for (int i=0; i < tabstring_req_arr_.size (); i++) { + Music * tabstring_req = tabstring_req_arr_[i]; + + size_t lenp; + char* tab_string_as_str = gh_scm2newstr(tabstring_req->get_mus_property ("text"), &lenp); + } + */ + + for (int i=0; i < note_req_l_arr_.size (); i++) + { + Item * note_p = new Item (get_property ("TabNoteHead")); + + Music * req = note_req_l_arr_[i]; + + Music * tabstring_req = tabstring_req_arr_[i]; + + size_t lenp; + char* tab_string_as_str = gh_scm2newstr(tabstring_req->get_mus_property ("text"), &lenp); + int tab_string = atoi(tab_string_as_str); + + Duration dur = *unsmob_duration (req->get_mus_property ("duration")); + + note_p->set_grob_property ("duration-log", gh_int2scm (dur.duration_log ())); + + if (dur.dot_count ()) + { + Item * d = new Item (get_property ("Dots")); + Rhythmic_head::set_dots (note_p, d); + + if (dur.dot_count () + != gh_scm2int (d->get_grob_property ("dot-count"))) + d->set_grob_property ("dot-count", gh_int2scm (dur.dot_count ())); + + d->set_parent (note_p, Y_AXIS); + announce_grob (d, SCM_EOL); + dot_p_arr_.push (d); + } + + int pos = 2 * tab_string - 2; // No tab-note between the string !!! + SCM c0 = get_property ("centralCPosition"); + if (gh_number_p (c0)) pos += gh_scm2int (c0); + + note_p->set_grob_property ("tab-string", gh_int2scm (tab_string)); + + note_p->set_grob_property ("staff-position", gh_int2scm (pos)); + announce_grob (note_p, req->self_scm()); + note_p_arr_.push (note_p); + } +} + +void +Tab_note_heads_engraver::stop_translation_timestep () +{ + for (int i=0; i < note_p_arr_.size (); i++) + { + typeset_grob (note_p_arr_[i]); + } + + note_p_arr_.clear (); + for (int i=0; i < dot_p_arr_.size (); i++) + { + typeset_grob (dot_p_arr_[i]); + } + dot_p_arr_.clear (); + + note_req_l_arr_.clear (); + + tabstring_req_arr_.clear (); +} + +void +Tab_note_heads_engraver::start_translation_timestep () +{ +} + + +ENTER_DESCRIPTION(Tab_note_heads_engraver, +/* descr */ "Generate one or more tablature noteheads from Music of type Note_req.", +/* creats*/ "TabNoteHead Dots", +/* acks */ "", +/* reads */ "centralCPosition", +/* write */ ""); diff --git a/ly/engraver-init.ly b/ly/engraver-init.ly index c22a99c9e8..aeed2f96e5 100644 --- a/ly/engraver-init.ly +++ b/ly/engraver-init.ly @@ -223,7 +223,7 @@ InnerStaffGroupContext= \translator { \accepts "RhythmicStaff" \accepts "GrandStaff" \accepts "PianoStaff" - + \accepts "TabStaff" \accepts "Lyrics" \accepts "ChordNames" } @@ -347,6 +347,7 @@ ScoreContext = \translator { \consists "Span_arpeggio_engraver" \accepts "Staff" + \accepts "TabStaff" \accepts "StaffContainer" \accepts "StaffGroup" \accepts "RhythmicStaff" @@ -442,3 +443,37 @@ FiguredBassContext = \translator { \consists "Figured_bass_engraver" \consistsend "Axis_group_engraver" } + +TabVoiceContext = \translator { + \VoiceContext + \name "TabVoice" + \denies "Thread" + \consists "Tab_note_heads_engraver" +} + +TabStaffContext = \translator { + \StaffContext + \alias "Staff" + \name "TabStaff" + \denies "Voice" + \accepts "TabVoice" + + % 6 strings + StaffSymbol \override #'line-count = #6 + StaffSymbol \override #'staff-space = #1.5 + + % One may change the strings tuning as following : + % The lenght of the list must be equal to the number of string + %TabNoteHead \override #'string-tunings = #'(10 10 10 10 10 10) + + % Special "TAB" clef + clefGlyph = #"clefs-tab" + clefPosition = #0 + + % Don't draw stems over the tabature figures ! + Stem \override #'avoid-note-head = ##t + + % No accidental in tablature ! + Accidental = \turnOff +} + diff --git a/ly/params-init.ly b/ly/params-init.ly index 5dd3aa44e2..104f7d0cf4 100644 --- a/ly/params-init.ly +++ b/ly/params-init.ly @@ -49,7 +49,8 @@ interscoreline = 4. \mm \translator { \LyricsVoiceContext } \translator { \StaffContainerContext } \translator { \FiguredBassContext } - +\translator { \TabStaffContext } +\translator { \TabVoiceContext } diff --git a/scm/grob-description.scm b/scm/grob-description.scm index 647551589a..b6c95fd76b 100644 --- a/scm/grob-description.scm +++ b/scm/grob-description.scm @@ -505,6 +505,17 @@ (meta . ((interfaces . (rhythmic-head-interface font-interface note-head-interface staff-symbol-referencer-interface)))) )) + (TabNoteHead + . ( + (font-family . roman) + (style . default) + (molecule-callback . ,tablature-molecule-callback) + (Y-offset-callbacks . (,Staff_symbol_referencer::callback)) + (stem-attachment-function . ,tablature-stem-attachment-function) + (string-tunings . (-8 -3 2 7 11 16)) + (meta . ((interfaces . (rhythmic-head-interface font-interface note-head-interface staff-symbol-referencer-interface)))) + )) + (Glissando . ( (type . line) @@ -799,6 +810,7 @@ (Y-offset-callbacks . (,Staff_symbol_referencer::callback)) (adjust-if-on-staffline . #t) (font-family . music) + (avoid-note-head . #f) (meta . ((interfaces . (stem-interface font-interface)))) )) diff --git a/scm/grob-property-description.scm b/scm/grob-property-description.scm index ba025764cb..67e97366f4 100644 --- a/scm/grob-property-description.scm +++ b/scm/grob-property-description.scm @@ -464,3 +464,7 @@ functions set spanner positions.") (grob-property-description 'chord-name-function procedure? "DOCME") (grob-property-description 'minimum-beam-collision-distance number? "Minimum distance to beam for a rest collision.") + +(grob-property-description 'tab-string number? "The tablature string of a TabNoteHead.") +(grob-property-description 'avoid-note-head boolean? "if set, the stem of a chord does not pass through all note head, but start at the last note head. Used by tablature.") +(grob-property-description 'string-tunings list? "The strings tuning, in semi-tons from the middle C. Used by tablature.") diff --git a/scm/output-lib.scm b/scm/output-lib.scm index 8ae4df7790..d4374a5974 100644 --- a/scm/output-lib.scm +++ b/scm/output-lib.scm @@ -5,6 +5,36 @@ ;;;; (c) 1998--2001 Jan Nieuwenhuizen ;;;; Han-Wen Nienhuys +; Tablature functions, by Jiba (jiba@tuxfamily.org) + +; The TabNoteHead stem attachment function. +(define (tablature-stem-attachment-function style) + (cons 0.0 1.0) +) + +; The TabNoteHead molecule callback. +; Create a text molecule +(define (tablature-molecule-callback grob) + (let ((molecule (fontify-text + (ly-get-default-font grob) + (string-append + (number->string + (- (pitch-semitones (ly-get-mus-property (ly-get-grob-property grob 'cause) 'pitch)) + (list-ref + (ly-get-grob-property grob 'string-tunings) + (- (ly-get-grob-property grob 'tab-string) + 1 ; remove 1 because list index starts at 0 and guitar string at 1. + )) + ) + ) + ) + ))) + molecule ; return the molecule. + ) + ) + +; end of tablature functions + (define (arg->string arg) (cond ((number? arg) (inexact->string arg 10)) -- 2.39.5