Dear All,

Cipher Music is a variety of notation systems that are used, particularly in 
Asia, by many millions of people. The structure is relatively simple with each 
note having a letter or number identifier and diacritics to indicate octave, 
length, etc.

But, just as with western notation, this stuff is hard to typeset and lilypond, 
being such a power tool should be able to eat it up.

I enclose my first attempt at this. But I would value some help in making it 
look nicer and not requiring raise/lower hackery to get the music lines not to 
clash. So all improvements are welcome.

The approach I have taken is to extend the note-names engraver slightly so that 
it can output duration, and then to reparse the note name to convert it into 
the required output. I enclose the patch and sample document. I propose the 
patch for addition to lilypond in a subsequent version. It's not very big and 
it shouldn't break anything.

Particular questions on the .ly front:

1. How do I get the voices not to smash into each other?
2. How do I get the barlines of the right thickness and height?

Todo.

1. Add key normalisation to CMaj or Am and insert indicative text to that 
effect.
2. Fix Doulos SIL to add better diacritic rendering on numbers
3. Do some user testing

Scary thoughts.

1. People like the - (for time doubling) to spread into the spare space
2. Underlining should act like beaming just like, but completely different to, 
beaming in Western notation.

Yours,
Martin
diff --git a/lily/note-name-engraver.cc b/lily/note-name-engraver.cc
index 1e1e01a..95ffd14 100644
--- a/lily/note-name-engraver.cc
+++ b/lily/note-name-engraver.cc
@@ -9,6 +9,7 @@
 #include "engraver.hh"
 #include "item.hh"
 #include "pitch.hh"
+#include "duration.hh"
 #include "stream-event.hh"
 
 #include "translator.icc"
@@ -46,6 +47,11 @@ Note_name_engraver::process_music ()
 	p = Pitch (-1, p.get_notename (), p.get_alteration ());
 
       s += p.to_string ();
+      if (to_boolean (get_property ("printDurations")))
+        {
+          Duration *d = unsmob_duration (events_[i]->get_property ("duration"));
+          s += d->to_string ();
+        }
     }
   if (s.length ())
     {
@@ -74,6 +80,7 @@ ADD_TRANSLATOR (Note_name_engraver,
 		"NoteName ",
 
 		/* read */
+        "printDurations "
 		"printOctaveNames ",
 
 		/* write */
diff --git a/scm/define-context-properties.scm b/scm/define-context-properties.scm
index 3b18e94..093b696 100644
--- a/scm/define-context-properties.scm
+++ b/scm/define-context-properties.scm
@@ -356,6 +356,7 @@ sustain pedals: @code{text}, @code{bracket} or @code{mixed} (both).")
      (pedalUnaCordaStyle ,symbol? "See @code{pedalSustainStyle}.")
      (predefinedDiagramTable ,hash-table? "The hash table of predefined
 fret diagrams to use in FretBoards.")
+     (printDurations ,boolean? "Print durations for the @code{NoteNames} context.")
      (printKeyCancellation ,boolean? "Print restoration alterations
 before a key signature change.")
      (printOctaveNames ,boolean? "Print octave marks for the
% Version 1.1
% Last edit: March 24, 2006
% The music and words produced by this source code are believed
% to be in the public domain in the United States. The source
% code itself is covered by the Creative Commons Attribution-
% NonCommercial license, 
% http://creativecommons.org/licenses/by-nc/2.5/
% Attribution: Geoff Horton

\version "2.8.0"
\include "english.ly"

#(use-modules (ice-9 regex))
#(define-public (cipher-map) (list '("a" . "6") '("b" . "7") '("c" . "1") '("d" . "2") '("e" . "3") '("f" . "4") '("g" . "5") '("es" . "♭") '("is" . "♯") '("1" . " - -") '("2" . " -") '("4" . "") '("8" . "̲") '("16" . "̲̲") '("\x27" . "̇") '("." . ".") '("," . "̣")))

#(set-default-paper-size "letter")
#(set-global-staff-size 20)

title = "I Need Thee Ev'ry Hour"
composer = "Robert Lowry"
poet = "Annie Sherwood Hawkes"
translator = "Refrain by Robert Lowry"
piece = "Need"
meter = "64.64, with Refrain"
arranger = ""

world = {
  \key g \major
  \time 3/4
  \partial 4*1
}

melody = \relative c'' {
  \world
  \autoBeamOff
  g |
  b4. a8 g fs |
  g2 g4 |
  g4.( a8) g[ fs] |
  d2 d4 |
  a'4. b8 a d, |
  b'2 g4 |
  fs4.( g8) fs[ e] |
  d2 b'4 |
  b4. a8 c b |
  b4 a2 |
  a4. g8 b a |
  a4 g g |
  g4. a8 g e |
  d4 g a |
  b4.( g8) a4 |
  g2 \bar "|."
}


alto = \relative c' {
  \world
  \autoBeamOff
  b4 |
  d4. c8 b a |
  b2 b4 |
  c2 c4 |
  b2 d4 |
  d4. d8 d d |
  d2 d4 |
  d4.( e8) d[ cs] |
  d2 d4 |
  d4. d8 g g |
  g4 fs2 |
  d4. d8 d d |
  d4 d d |
  e4. e8 e c |
  b4 d e |
  d4.( b8) c4 |
  b2 
}

tenor = \relative c {
  \world
  \autoBeamOff
  d4 |
  g4. e8 d d |
  d2 d4 |
  e2 e8[ g] |
  g2 fs4 |
  fs4. g8 fs fs |
  g2 b4 |
  a2 a8[ g] |
  fs2 g4 |
  g4. b8 e d |
  d4 d2 |
  c4. b8 d c |
  c4 b g |
  g4. g8 g g |
  g4 g g |
  g2 fs4 |
  g2
}

bass = \relative c {
  \world
  \autoBeamOff
  g4 |
  g4. c8 d d |
  g,2 g4 |
  c2 c4 |
  g2 d'4 |
  d4. d8 d d |
  g2 g,4 |
  a2 a4 |
  d2 g4 |
  g4. g8 g g |
  d4 d2 |
  d4. d8 d d |
  g,4 g b |
  c4. c8 c c |
  g4 b c |
  d2 d4 |
  g2
}

verseOne = \lyricmode {
  \set stanza = "1. "
  I need thee ev -- 'ry hour,
  Most gra -- cious Lord;
  No ten -- der voice like thine
  Can peace af -- ford.
  I need thee, O I need thee,
  Ev -- 'ry hour I need thee,
  O bless me now, my Sa -- viour,
  I come to thee.
}

verseTwo = \lyricmode {
  \set stanza = "2. "
  I need thee ev -- 'ry hour;
  Stay thou near by;
  Temp -- ta -- tions lose their pow'r
  When thou art nigh.
}

\markup {
  \column {
    \fill-line { \large \bold \title } % title
    \fill-line { \caps \piece               % piece
	         \caps \composer      % composer
	  }
    \fill-line { \meter          % meter
	         \arranger           % arranger
	  }
  }
}

\score {
  \context ChoirStaff
    <<
    \context Staff <<
%      \context Voice = sopranos { << \melody >> } 
      \context Cipher = sopranos { << \melody >> }
%   >> \context Staff <<
      \context CipherTwo = altos { << \alto >> }
      \context Lyrics = one \lyricsto sopranos \verseOne
      \context Lyrics = two \lyricsto sopranos \verseTwo
    >>
    \context Staff = lower <<
%%      \clef bass
      \context Cipher =
        tenors { << \tenor >> }
      \context CipherTwo =
        basses { << \bass >> }
    >>
>>
  \layout {
    \context {
      \Score
      % **** Turns off bar numbering
      \remove "Bar_number_engraver"
    }
    \context {
      \Lyrics
      % **** Prevents lyrics from running too close together
      \override LyricSpace #'minimum-distance = #0.6
      % **** Makes the text of lyrics a little smaller
      \override LyricText #'font-size = #-1
      % **** Moves lines of lyrics closer together
      \override VerticalAxisGroup #'minimum-Y-extent = #'(-1 . 1)
%      \override Barline #'bar-size = #4
    }
    \context {
      \Voice
      \name Cipher
      \alias Voice

      \consists "Rest_swallow_translator" 
      \consists "Skip_event_swallow_translator"
      \consists "Tie_engraver"
      \consists "Note_name_engraver"
      \consists "Separating_line_group_engraver"
%      \override SeparatingLineGroup #'createSpacing = ##t
%      \consists "Bar_engraver"
%     \override Barline #'bar-size = #6
%  \override VerticalAxisGroup #'minimum-Y-extent = #'(-3 . 3)
%  \override VerticalAxisGroup #'remove-empty = ##t
%  \override VerticalAxisGroup #'keep-fixed-while-stretching = ##t
%  \override SeparationItem #'padding = #0.2
      \remove "Note_head_line_engraver"
      \remove "Note_heads_engraver"
      \remove "Stem_engraver"
      \remove "Rest_engraver"
      printOctaveNames= ##t
      printDurations= ##t
      \override NoteName #'stencil = #(lambda (grob) (let*
        ((s (string-match "([a-g])([a-z]*)([',]*)([0-9]*)([.]*)" (ly:grob-property grob 'text)))
         (sa (filter-map (lambda (x) (match:substring s x)) (list 2 1 3 4 5)))
         (sb (filter-map (lambda (x) (assoc-ref (cipher-map) x)) sa))
         (res (apply string-append sb))
        )
        (begin
         (grob-interpret-markup grob (markup #:override '(font-name . "Doulos SIL") #:raise 1 #:text res)))))
    }
    \context {
        \Cipher
        \name CipherTwo
        \alias Cipher
      \override NoteName #'stencil = #(lambda (grob) (let*
        ((s (string-match "([a-g])([a-z]*)([',]*)([0-9]*)([.]*)" (ly:grob-property grob 'text)))
         (sa (filter-map (lambda (x) (match:substring s x)) (list 2 1 3 4 5)))
         (sb (filter-map (lambda (x) (assoc-ref (cipher-map) x)) sa))
         (res (apply string-append sb))
        )
        (begin
         (grob-interpret-markup grob (markup #:override '(font-name "Doulos SIL") #:lower 1.7 #:text res)))))
    }
        
    \context {
      \Staff
      \accepts "Cipher"
      \accepts "CipherTwo"
%      \remove "Staff_symbol_engraver"
      \consists "Font_size_engraver"
%      \consists "Axis_group_engraver"
      \override VerticalAxisGroup #'minimum-Y-extent = #'(0 . 4)
      \override VerticalAxisGroup #'padding = #4
      \override VerticalAxisGroup #'keep-fixed-while-stretching = ##t
      \override SeparationItem #'padding = #4
      \override StaffSymbol #'line-count = #0
      \override StaffSymbol #'Y-extent = #'(-2 . 2)
%      \override StaffSymbol #'staff-space = #0
      \remove "Clef_engraver"
      \remove "Ledger_line_engraver"
      \remove "Key_engraver"
%      \override Script #'staff-space = #4
%      \override VoltaBracket #'staff-padding = #3
    }
    \context
    {
        \ChoirStaff
      \override Barline #'bar-size = #6
    }
  }
}


\markup { 
  \normalsize {
    \fill-line {
      \hspace #3.0
      \hspace #3.0
      \line {
	"3. "
	\column {
	  "I need thee every hour,"
	  "  In joy or in pain;"
	  "Come quickly and abide,"
	  "  Or life is vain."
	  \italic "Refrain"
	}
      }
      \hspace #3.0
      \line {
	"4. "
	\column {
	  "I need thee every hour;"
	  "  Teach me thy will;"
	  "And thy rich promises"
	  "  In me fulfill."
	  \italic "Refrain"
	}
      }
      \hspace #3.0
      \hspace #3.0
    }
  }
}

\markup {
  \fill-line {
    " "
    \column {
      \small \caps \poet % poet
      \small \caps \translator % translator
    }
  }
}

\paper {
  ragged-bottom = ##t
  top-margin = 0.25\in
  bottom-margin = 0.25\in
}

%{
  Per _The Hymnal 1940_, 438 first tune.
  Change log:
  3-24-06 Move to 2.8 and current formatting
%}


_______________________________________________
lilypond-user mailing list
lilypond-user@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-user

Reply via email to