lilypond-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Byzantine singing


From: Лысов Дмитрий
Subject: Re: Byzantine singing
Date: Tue, 09 Aug 2022 00:42:13 +0300

Based on a group of byzantine fonts, I made my own ByzLily.otf. In LilyPond, there is no way to combine characters from different fonts qualitatively. A single font allows you to use different elements of byzantine notation in one text. The music is entered as a text string under the note carrier.
Font "ByzLily.otf": https://disk.yandex.ru/d/jW8aScwbZvgzgA
Font "Ponomar Unicode": https://sci.ponomar.net/fonts.html
Font "Mezenets Unicode": https://sci.ponomar.net/music.html
Tell me, how can text syllables of byzantine notation be aligned in the center of the notes?
 
Program text
%%%%%%%%%%%%%%%%%%%%%%%%
 
\version "2.22.1"  
 
\header 
        copyright = "Вѧ́тка, ҂вк҃в"
} %header
 
\paper 
{
  (set-paper-size "a4") 
  %page-count = # 1
  tagline=##f 
  ragged-last = ##t
  myStaffSize = #21
  #(define fonts (make-pango-font-tree 
    "Ponomar Unicode"
    "Ponomar Unicode"
    "Ponomar Unicode"
    (/ myStaffSize 21)))
  system-system-spacing = #'((padding . 3.9)) %расстояние между нотоносцами
}
 
\layout 
{
  indent = 0.0 
  \context 
  {
    \Lyrics 
    \remove Time_signature_engraver
    \remove "Forbid_line_break_engraver"
  } 
  \context 
  {
    \Score
    \override SpacingSpanner.spacing-increment = 0.5
    \Staff
  }
  \context 
  {
    \KievanVoice
    \stemDown
    fontSize = 1.0
  }
 
\midi 
{
  \context 
  {
    \Score
    tempoWholesPerMinute = #(ly:make-moment 110 2)
  }
  \context 
  {
    \Staff
    \remove Staff_performer
  }
  \context 
  {
    \Voice
    \consists Staff_performer
  }
}
 
% Declare head prefix shortcuts.
recitative = #(ly:make-duration -1 0)
final = #(ly:make-duration -2 0)
 
% The number next to "th" in (th 0.2) controls thickness of the brackets. 
#(define-markup-command (left-bracket layout props) ()
  "Draw left hand bracket"
  (let* ((th 0.2) ;; todo: take from GROB
  (width (* 2.5 th)) ;; todo: take from GROB
  (ext '(-2.8 . 2.8))) ;; todo: take line-count into account
  (ly:bracket Y ext th width)))
 
leftBracket = 
{
  \once \override BreathingSign.text = #(make-left-bracket-markup)
  \once \override BreathingSign.break-visibility = #end-of-line-invisible
  \once \override BreathingSign.Y-offset = ##f
  % Trick to print it after barlines and signatures:
  \once \override BreathingSign.break-align-symbol = #'staff-bar
  \breathe 
} %leftBracket
 
#(define-markup-command (right-bracket layout props) ()
  "Draw right hand bracket"
  (let* ((th .2);;todo: take from GROB
  (width (* 2.5 th)) ;; todo: take from GROB
  (ext '(-2.8 . 2.8))) ;; todo: take line-count into account
  (ly:bracket Y ext th (- width))))
 
rightBracket = 
{
  \once \override BreathingSign.text = #(make-right-bracket-markup)
  \once \override BreathingSign.Y-offset = ##f
  \breathe
} %rightBracket
 
%%%%%%%%%%%%%%%%%%%%%%
 
#(define (define-grob-property symbol type? description)
  (if (not (equal? (object-property symbol 'backend-doc) #f))
      (ly:error (_ "symbol ~S redefined") symbol))
 
  (set-object-property! symbol 'backend-type? type?)
  (set-object-property! symbol 'backend-doc description)
  symbol)
 
#(map
  (lambda (x)
    (apply define-grob-property x))
 
  `(
    (tagged ,boolean? "is this grob marked?")
    (syllables ,array? "the lyric syllables at a timestep")
  ))
 
%%%%%%%%%%%%%%%%%%%%%%%%
 
#(define (Lyric_text_align_engraver ctx)
"If the property 'tagged is set, collect all lyric syllables at that
timestep in the grob-array `syllables'"
  (let ((syl '()))
    (make-engraver
     (acknowledgers
      ((lyric-syllable-interface trans grob source)
       (set! syl (cons grob syl))))
     ((stop-translation-timestep trans)
      (if (any (lambda (x) (eq? #t (ly:grob-property x 'tagged)))
               syl)
          (for-each
            (lambda (x)
               (for-each
                 (lambda (y)
                   (ly:pointer-group-interface::add-grob x 'syllables y))
                 syl))
            syl))
      (set! syl '())))))
 
#(define (X-offset-callback grob)
  (let* ((target (ly:grob-object grob 'syllables))
         (target
           (if (ly:grob-array? target)
               (ly:grob-array->list target)
               '())))
    (if (pair? target)
        (let ((longest
                (car
                  (sort target
                        (lambda (x y)
                          (> (interval-length
                               (ly:stencil-extent
                                 (grob-interpret-markup
                                   grob (ly:grob-property x 'text))
                                 X))
                             (interval-length
                               (ly:stencil-extent
     
 
%Change color for some symbols in a sylable
#(define characters-to-color 
  '("𜼁" "𜼂" "𜼃" "𜼄" "𜼅" "𜼆" "𜼇" "𜼈" "𜼉" "𜼊" "𜼋" "𜼌" "𜼍" "𜼎" "𜼏" "𜼐" 
  "𜼑" "𜼒" "𜼓" "𜼔" "𜼕" "𜼖" "𜼗" "𜼘" "𜼙" "𜼚" "𜼛" "𜼜" "𜼝" "𜼞" "𜼟" 
  "𜼠" "𜼡" "𜼢" "𜼣" "𜼤" "𜼥" "𜼦" "𜼧" "𜼨" "𜼩" "𜼪" "𜼫" "𜼬" "𜼭" ))
 
#(define (symbol-location str symb)
;; search text for the specified character and store its location in an alist
;; --> '((start . end) (start . end) ...)
  (let ((result '())
    (counter 0))
      (define (helper str)
        (let ((pos (string-contains str symb)))
          (if pos
            (let ((dpos (+ pos (string-length symb))))
              (set! result (append result (cons (cons (+ pos counter)
                (+ pos counter (string-length symb)))
                  '())))
              (set! counter (+ counter dpos))
                (helper (string-drop str dpos))))))
      (helper str)
    result))
 
#(define (all-symbol-locations str)
  (let ((result '()))
    (for-each
      (lambda (sym)
        (let ((pos-length (symbol-location str sym)))
          (if (pair? pos-length)
            (set! result (append result pos-length)))))
      characters-to-color)
    result))
 
#(define (sort-alist alist)
;; sort alist by keys
  (sort alist (lambda (p q) (< (car p) (car q)))))
 
#(define red-and-black-markup
  (lambda (grob)
    (let* ((text (ly:grob-property grob 'text))
      (positions (sort-alist (all-symbol-locations text)))
      (range (cons 0 (string-length text)))
      (result '())) ; build markup here
 
      (define (helper positions range)
      ;; positions values --> red markups; gaps --> black
      (let* ((left (cons (car range) (car (first positions))))
        (right (cons (cdr (first positions)) (cdr range)))
          (segment (lambda (x) (substring text (car x) (cdr x)))))
 
          (set! result
            (append result
              (if (> (interval-length left) 0)
                (list (markup (segment left)))
                '())
              (list (markup #:with-color red (segment (first positions))))))
 
            (if (null? (cdr positions))
              (if (> (interval-length right) 0)
                (set! result (append result (list (markup (segment right))))))
              (helper (cdr positions) right))))
 
      (if (null? positions)
        (set! result (list (markup text)))
        (helper positions range))
 
      (set! result (make-concat-markup result))
      (set! (ly:grob-property grob 'text) result))))
 
colorSymbols =
  #(define-music-function
    (parser location) ()
  #{ \override Lyrics . LyricText #'before-line-breaking = #red-and-black-markup #})
 
melody = 
{
  %\break
  %\bar "k"
  %\set Staff.instrumentName = "Tenor"
  %\leftBracket
  %\rightBracket
  %\recitative
  %\final*1/64
  %\longa
  %\bar ""
  %\bar "|"
  %\[(  )\]
        
  \[(d4 c)\] \[(d e)\] f1 \[(e4 d)\] f2 e d1\bar "|" %удоль (нач.)
}
 
text = \lyricmode
{
  \override LyricText.font-name = #"ByzLily" 
  \override LyricText.font-size = #5 
  \override LyricSpace.minimum-distance = #0.8 %расстояние между словами 
  
  󰁉󰁧 󰁆 󰀅󰃠 󰀜󰁧󰁧 󰀌󰀘 󰀜󰁧󰀢 󰁧󰃡
 
znamen = \lyricmode
{
  \override LyricText.font-name = #"Mezenets Unicode"
  \override LyricText.font-size = #9
  \override LyricSpace.minimum-distance = #2
  %\colorSymbols %включить для раскрашивания помет
  
  𜽗 𜽞 𜾒 𜽗 𜽐𜼱 𜽜 𜾆
 
\markup { \huge { "Гла́съ д҃: ᲂу҆до́ль" }}
\score
  <<
    \new KievanStaff  = slavonic 
    <<
      \new KievanVoice = "one" 
      \relative c'
      {
        \cadenzaOn 
        \melody
        \bar "k"
        \cadenzaOff
      }
    >>
    
    \new Lyrics 
    \lyricsto "one" 
    \text
    
    \new Lyrics \with {alignAboveContext = slavonic} 
    \lyricsto "one" 
    \znamen            
  >>
  \layout{}
  \midi{}
} %score
 
03.08.2022, 16:28, "Eef Weenink" <h.e.weenink@de-erve.nl>:
One of them is https://www.ctan.org/pkg/byzantinemusic. In xelatex.  
Eef 
 
Verstuurd vanaf mijn iPad
 
Op 31 jul. 2022 om 21:56 heeft Лысов Дмитрий <siitop@yandex.ru> het volgende geschreven:
 

Hi! I am studying Byzantine singing, which uses neumes to record melodies. Have you ever met a player or a converter of this notation into a five-line one in the lilypond program? Are there any developments on this topic at all?
Например посмотрите книгу по византийскому пению:
Langue N. "A guide to the music of the eastern orthodox church", 1984.
https://www.newbyz.org/guide_to_music_of_eoa.pdf

reply via email to

[Prev in Thread] Current Thread [Next in Thread]