additional info for jianpu.
the output from 7-speech+jianpu_10a_test.ly
From: MING TSANG <[email protected]>
To: "[email protected]" <[email protected]>; Lilypond-usermailinglist
<[email protected]>
Sent: Monday, August 21, 2017 9:51 PM
Subject: Re: Jianpu music notation question
forgot to include lilypond user
From: TSANGMING <[email protected]>
To: "[email protected]" <[email protected]>
Sent: Monday, August 21, 2017 6:28 PM
Subject: Re: Jianpu music notation question
#yiv0949541533 #yiv0949541533 -- filtered {panose-1:2 4 5 3 5 4 6 3 2
4;}#yiv0949541533 filtered {font-family:DengXian;panose-1:2 1 6 0 3 1 1 1 1
1;}#yiv0949541533 filtered {font-family:Calibri;panose-1:2 15 5 2 2 2 4 3 2
4;}#yiv0949541533 filtered {font-family:DengXian;panose-1:2 1 6 0 3 1 1 1 1
1;}#yiv0949541533 p.yiv0949541533MsoNormal, #yiv0949541533
li.yiv0949541533MsoNormal, #yiv0949541533 div.yiv0949541533MsoNormal
{margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:inter-ideograph;font-size:10.5pt;}#yiv0949541533
a:link, #yiv0949541533 span.yiv0949541533MsoHyperlink
{color:blue;text-decoration:underline;}#yiv0949541533 a:visited, #yiv0949541533
span.yiv0949541533MsoHyperlinkFollowed
{color:#954F72;text-decoration:underline;}#yiv0949541533
.yiv0949541533MsoChpDefault {}#yiv0949541533 filtered {margin:72.0pt 72.0pt
72.0pt 72.0pt;}#yiv0949541533 div.yiv0949541533WordSection1 {}#yiv0949541533
The following may be of interest to
youhttps://lists.gnu.org/archive/html/lilypond-user/2015-04/msg01342.html
Ming. 发送自 Windows 10 版邮件应用
\version "2.19"
\language "english"
\include "jianpu10a.ly"
%%%%%%%%%%%%%
% \version "2.18.2"
% also works with 2.19.x and later
#(define (get-keysig-alt-count alt-alist)
"Return number of sharps/flats in key sig, (+) for sharps, (-) for flats."
(if (null? alt-alist)
0
(* (length alt-alist) 2 (cdr (car alt-alist)))))
#(define (get-major-tonic alt-count)
"Return number of the tonic note 0-6, as if the key sig were major."
;; (alt-count major-tonic)
;; (-7 0) (-5 1) (-3 2) (-1 3) (1 4) (3 5) (5 6) (7 0)
;; (-6 4) (-4 5) (-2 6) (0 0) (2 1) (4 2) (6 3)
(if (odd? alt-count)
(modulo (- (/ (+ alt-count 1) 2) 4) 7)
(modulo (/ alt-count 2) 7)))
#(define (get-key-alts context)
"Needed because LilyPond 2.19 and 2.20 has 'keyAlterations
and 2.18 has 'keySignature for the same context property.
No way to test for existence of context property..."
(define key-alts (ly:context-property context 'keyAlterations '()))
(if (equal? key-alts '())
(ly:context-property context 'keySignature '())
key-alts))
#(define (stencil-flip axis stl)
"Flip stencil @var{stl} in the direction of @var{axis}.
@var{axis} is 0 for X, 1 for Y."
(let* (
;; center stl on 0,0 to prepare for flipping,
;; and calculate how far it moved.
(centered-stl (ly:stencil-aligned-to stl axis CENTER))
(original-ext (ly:stencil-extent stl axis))
(centered-ext (ly:stencil-extent centered-stl axis))
(offset (- (car original-ext) (car centered-ext)))
;; scale centered-stl using -1 to flip it
(xy (if (= axis X) '(-1 . 1) '(1 . -1)))
(flipped-stl (ly:stencil-scale centered-stl (car xy) (cdr xy)))
;; restore flipped stl to original position
(replaced-stl (ly:stencil-translate-axis flipped-stl offset axis)))
;; for testing...
;; (display original-ext) (display centered-ext)
;; (display (ly:stencil-extent replaced-stl axis))(newline)
replaced-stl))
jianpuMusic =
#(define-music-function (parser location mus) (ly:music?)
"This music function modifies the music input for better jianpu output."
(let ((major-tonic-pitch (ly:make-pitch 0 0 0))
(prev-pitch (ly:make-pitch 0 0 0)))
(music-map
(lambda (m)
(cond
;; KEY CHANGE
((music-is-of-type? m 'key-change-event)
(let*
((pitch-alist (ly:music-property m 'pitch-alist))
(key-alts (filter (lambda (a) (not (= 0 (cdr a)))) pitch-alist))
(keysig-alt-count (get-keysig-alt-count key-alts))
(major-tonic-number (get-major-tonic keysig-alt-count))
(tonic (ly:music-property m 'tonic))
(tonic-num (ly:pitch-notename tonic))
;; mode 1-7, 1=major 6=minor
(mode (+ 1 (modulo (- tonic-num major-tonic-number) 7))))
(set! major-tonic-pitch
(ly:make-pitch 0
major-tonic-number
(or (assoc-ref key-alts major-tonic-number) 0)))
;; store the actual key of the music for use in jianpu key signatures
(ly:music-set-property! m 'jianpu-key-sig (cons mode tonic))
;; convert the key signature in effect to c major
(ly:music-set-property! m 'pitch-alist '((0 . 0) (1 . 0) (2 . 0) (3 . 0) (4 . 0) (5 . 0) (6 . 0)))
(ly:music-set-property! m 'tonic (ly:make-pitch 0 0 0))
))
;; REST AND MULTI-MEASURE REST
((or (music-is-of-type? m 'rest-event)
(music-is-of-type? m 'multi-measure-rest))
(let ((dur (ly:moment-main (ly:music-duration-length m))))
(if (>= dur 1/2)
;; split whole and half rests into quarter notes
(let ((q (make-music 'NoteEvent
'duration (ly:make-duration 2 0 1)
'jianpu-rest #t)))
;; double dotted half rest is special case
;; TODO: generalize this for triple dots, other durations, etc.?
(if (= dur 7/8)
(let ((q-dotted (ly:music-deep-copy q)))
(ly:music-set-property! q-dotted 'duration (ly:make-duration 2 1 1))
(set! m (make-sequential-music (append (make-list 2 q) (list q-dotted)))))
;; else
(set! m (make-sequential-music (make-list (* 4 dur) q)))))
;; shorter rests are just converted into notes without pitches
;; and with a jianpu-rest property added
(begin
(ly:music-set-property! m 'name 'NoteEvent)
(ly:music-set-property! m 'types
(append
(delete 'rest-event (ly:music-property m 'types))
'(note-event melodic-event)))
(ly:music-set-property! m 'jianpu-rest #t)
))))
;; NOTE
((music-is-of-type? m 'note-event)
;; handle pitchless note events and transpose pitches to c major
;; which gives us correct accidentals and octaves "for free"
(if (ly:pitch? (ly:music-property m 'pitch))
(begin
(ly:music-set-property! m 'pitch
(ly:pitch-transpose (ly:music-property m 'pitch)
(ly:pitch-negate (ly:pitch-diff major-tonic-pitch (ly:make-pitch 0 0 0)))))
(set! prev-pitch (ly:music-property m 'pitch)))
;; else
(ly:music-set-property! m 'pitch prev-pitch))
(let* ((octave (ly:pitch-octave (ly:music-property m 'pitch)))
(octave-dir (if (> octave 0) 1 -1))
(artics (ly:music-property m 'articulations '()))
(dur (ly:moment-main (ly:music-duration-length m)))
(dot (ly:stencil-translate
(make-circle-stencil 0.2 0.001 #t)
(cons 0.6 0)))
(dot-two (ly:stencil-stack dot Y DOWN dot 0.5 0))
(dot-three (ly:stencil-stack dot-two Y DOWN dot 0.5 0))
(dot-four (ly:stencil-stack dot-three Y DOWN dot 0.5 0)))
;; add octave dot markups as articulations
;; from jianpu-ly python script: "-\tweak #'X-offset #0.6 _."
(if (not (= 0 octave))
(ly:music-set-property! m 'articulations
(append artics
(list
(make-music 'TextScriptEvent
'direction octave-dir
'text (markup #:stencil
(case (abs octave)
((1) dot)
((2) dot-two)
((3) dot-three)
((4) dot-four)
(else dot-four)
)))))))
;; split whole and half notes into quarter notes, some dashed
(if (>= dur 1/2)
(let* ((dash-num (+ -1 (* 4 dur)))
(q-dur (ly:make-duration 2 0 1))
(q (make-music 'NoteEvent
'duration q-dur
'pitch (ly:music-property m 'pitch)
'jianpu-dash-note #t)))
(ly:music-set-property! m 'duration q-dur)
(if (= dash-num 5/2)
;; special fix for double-dotted half note
;; TODO: generalize this for triple dots, other durations, etc.?
(let ((q-dotted (ly:music-deep-copy q)))
(ly:music-set-property! q-dotted 'duration (ly:make-duration 2 1 1))
(set! m (make-sequential-music
(append (list m q) (list q-dotted)))))
;; else
(set! m (make-sequential-music
(append (list m) (make-list dash-num q)))))
)))))
m)
mus)))
% Note: when checking custom event properties like jianpu-rest or
% jianpu-key-sig we have to use (if (equal? #t jianpu-rest) ...
% and not (if jianpu-rest ... the latter results in "false positives".
#(define Jianpu_note_head_engraver
(make-engraver
(acknowledgers
((note-head-interface engraver grob source-engraver)
;; make sure \omit is not in effect (stencil is not #f)
(if (ly:grob-property-data grob 'stencil)
(let* ((staff-context (ly:translator-context engraver))
(event (event-cause grob))
(jianpu-dash-note (ly:event-property event 'jianpu-dash-note)))
(if (equal? #t jianpu-dash-note)
(ly:grob-set-property! grob 'stencil
(ly:stencil-translate
(make-connected-path-stencil '((1 0)) 0.3 1 1 #f #f)
(cons 0 1)))
;; else create number stencil based on the scale degree of the note
;; TODO: handle notes without pitches that aren't jianpu-rests
(let*
((grob-pitch (ly:event-property event 'pitch))
(note-number
(if (ly:pitch? grob-pitch)
(ly:pitch-notename grob-pitch) #f))
(jianpu-rest (ly:event-property event 'jianpu-rest))
(glyph-string
;; check jianpu-rest first, because apparently
;; sometimes there is a note-number for rests.
(if (equal? #t jianpu-rest)
"zero"
(if (number? note-number)
(case (+ 1 note-number)
((1) "one")
((2) "two")
((3) "three")
((4) "four")
((5) "five")
((6) "six")
((7) "seven")
(else "zero"))
#f)))
(stl
(if (string? glyph-string)
(grob-interpret-markup grob
(markup #:musicglyph glyph-string)))))
(ly:grob-set-property! grob 'stencil stl)
))))))))
#(define Jianpu_flag_engraver
(make-engraver
(acknowledgers
((flag-interface engraver grob source-engraver)
;; make sure \omit is not in effect (stencil is not #f)
(if (ly:grob-property-data grob 'stencil)
(let* ((glyph-name (ly:grob-property grob 'glyph-name))
(padding 0.35)
;; TODO: width is hard-coded, would be better to match note-head width
;; TODO: stencil creation could be coded better
(flag-one (make-connected-path-stencil '((1.2 0)) 0.15 1 1 #f #f))
(flag-two (ly:stencil-stack flag-one Y DOWN flag-one padding 0))
(flag-three (ly:stencil-stack flag-two Y DOWN flag-one padding 0))
(flag-four (ly:stencil-stack flag-three Y DOWN flag-one padding 0))
(flag-five (ly:stencil-stack flag-four Y DOWN flag-one padding 0))
(new-stl (cond
((string= glyph-name "flags.d3") flag-one)
((string= glyph-name "flags.d4") flag-two)
((string= glyph-name "flags.d5") flag-three)
((string= glyph-name "flags.d6") flag-four)
((string= glyph-name "flags.d7") flag-five)
(else empty-stencil))))
(ly:grob-set-property! grob 'stencil new-stl)
(ly:grob-set-property! grob 'Y-offset -2)
;; TODO: are these needed?
;; (ly:grob-set-property! grob 'X-extent
;; (ly:stencil-extent (ly:grob-property grob 'stencil) X))
;; (ly:grob-set-property! grob 'Y-extent
;; (ly:stencil-extent (ly:grob-property grob 'stencil) Y))
))))))
#(define (jianpu-beam-adjust grob)
"Adjusts the width etc. of beams."
;; We calculate the amount to scale based on width of beam
;; TODO: improve this, maybe by using stems
(let* ((x-ext (interval-length (ly:stencil-extent (ly:grob-property grob 'stencil) X)))
(x-scale (+ 1 (/ 1.4 x-ext))))
;; (display x-ext)(newline)
(ly:grob-set-property! grob 'stencil
;; (ly:stencil-translate
(stencil-flip Y
(ly:stencil-scale
(ly:grob-property grob 'stencil)
x-scale 1))
;; (cons 0 0))
)))
#(define Jianpu_key_engraver
(let ((current-key-sig (cons 1 (ly:make-pitch 0 0 0))))
(make-engraver
(acknowledgers
((key-signature-interface engraver grob source-engraver)
;; make sure \omit is not in effect (stencil is not #f)
(if (ly:grob-property-data grob 'stencil)
(let* ((event (event-cause grob))
(jianpu-key-sig
(if event
(ly:event-property event 'jianpu-key-sig)
current-key-sig))
(tonic-num (car jianpu-key-sig))
(tonic-pitch (cdr jianpu-key-sig))
(key-sig-number-string (ly:number->string tonic-num))
(key-sig-note
(case (ly:pitch-notename tonic-pitch)
((0) "C")
((1) "D")
((2) "E")
((3) "F")
((4) "G")
((5) "A")
((6) "B")
(else "X")))
(key-sig-alt
(case (ly:pitch-alteration tonic-pitch)
((1/2) #{ \markup \sharp #})
((-1/2) #{ \markup \flat #})
(else ""))))
(set! current-key-sig jianpu-key-sig)
(ly:grob-set-property! grob 'stencil
(grob-interpret-markup grob
;; TODO: scale the flat or sharp size, based on current font size
(markup key-sig-number-string "=" key-sig-alt key-sig-note)
)))))))))
% Custom "JianpuStaff" Context
\layout {
\context {
% \Staff lets us start with all standard staff settings
\Staff
% \name gives the custom staff context its name
\name JianpuStaff
% \alias Staff tells LilyPond that commands that work on a standard
% Staff context should also work with this custom context
\alias Staff
% customizations
\consists \Jianpu_note_head_engraver
\consists \Jianpu_flag_engraver
\consists \Jianpu_key_engraver
\override Beam.after-line-breaking = #jianpu-beam-adjust
\override KeySignature.break-visibility = ##(#f #f #f)
\override Accidental.font-size = #-2.5
\override Clef.stencil = ##f
\override StaffSymbol.line-count = #0
\override BarLine.bar-extent = #'(-2 . 2)
\override TimeSignature.style = #'numbered
% \override Stem.transparent = ##t
\override Stem.length = #0
\override Stem.length-fraction = #0
\override NoteHead.Y-offset = #-1
\override Beam.transparent = ##f
\override Stem.direction = #DOWN
\override Beam.beam-thickness = #0.15
\override Beam.length-fraction = #0.5
\override Tie.staff-position = #2.5
\override TupletBracket.bracket-visibility = ##t
\tupletUp
\slurUp
% \hide Stem
\omit Stem
\override Dots.staff-position = #2
}
% define the "parent" contexts that will accept the custom context
\context { \Score \accepts JianpuStaff }
\context { \ChoirStaff \accepts JianpuStaff }
\context { \GrandStaff \accepts JianpuStaff }
\context { \PianoStaff \accepts JianpuStaff }
\context { \StaffGroup \accepts JianpuStaff }
}
% And for MIDI
% to avoid warnings it has to be defined for each type of output desired
% but we actually can't use midi with the jianpu music function, so this
% is rather pointless... leaving it in for now.
\midi {
\context {
\Staff
\name JianpuStaff
\alias Staff
}
% since the customizations are for visual output only,
% there is no need to include them for midi
\context { \Score \accepts JianpuStaff }
\context { \ChoirStaff \accepts JianpuStaff }
\context { \GrandStaff \accepts JianpuStaff }
\context { \PianoStaff \accepts JianpuStaff }
\context { \StaffGroup \accepts JianpuStaff }
}
% }
%%%%%%%%%%%%%%%%%%%
\header {
title = "åæ¶ä¸è¨"
subtitle = "7 speech"
% Remove default LilyPond tagline
tagline = ##f
}
\paper {
#(set-paper-size "letter")
}
\layout {
\context {
\Voice
\consists "Melody_engraver"
\override Stem #'neutral-direction = #'()
}
}
globald = {
\key d \major
\numericTimeSignature
\time 3/4
\tempo 4=100
}
\include "include_lyndon-specific.ly"
melodyd = {
fs'2. | %m01
e'2 a'8. g'16 |%m002
fs'4 fs'2 |%m03
d'4 d''4 cs''8.( b'16) %m04
a'2 b'8. g'16 |\break %m05
fs'2 e'8 fs'8 |%m06
e'8 b8 d'2 |%m07
a'4 fs'2 |%m08
e'4 fs'4 a'8( g'8) |%m09
fs'2 d''4 | \break %m10
cs''8( d''8) e''8( d''8) cs''8( b'8) |%m11
a'2. |%m12
d'4 d''2 |%m13
d''4 cs''4 b'8 a'8 |%m14
fs'2. |\break %m15
d'4 b'2 |%m16
b'4 a'4 g'8 fs'8 |%m17
e'2 a'8( g'8) |%m18
fs'2 fs'8( e'8) |%m19
d'2 d''8( cs''8) |\break %m20
b'2 b'8( a'8) |%m21
g'2 fs'4 |%m22
e'8 d' cs'( e') cs'( d') |%m23
b2. |%m24
b2 cs'8( e'16 d'16) | \break %m25
b2 \tuplet 3/2{g'8( b' g')} |%m26
fs'2 r4 |%m27
fs'8 fs'4~8 r4 |%m28
b'4 a'8( g'8) fs'4 |%m29
e'8 d' cs' e' d' cs' | %m30
b2. \bar"|."
\label #'lastPage
}
verse = \lyricmode {
ç¶ å! 赦 å
ä» å, å çº ä» å æ ä½ ç, ä» å ä¸ æ å¾.
%{æ 實 å¨ å 訴 ä½ , %} ä» æ¥ ä½ è¦ å æ å¨ æ¨ å 裡 äº.
æ¯ è¦ª ç ä½ ç å
å, (é å¾) ç ä½ ç æ¯ 親.
æ ç ç¥ åª! æ ç ç¥ åª! çº ç 麽 é¢ æ£ æ!
æ æ¸´ äº!
æ äº!
ç¶ å! æ å° æ é é 交 å¨ ç¥¢ æ 裡.
}
sk = \tag "SK" {\skip1}
verseSK = \lyricmode {
ç¶ \sk \sk å! \sk 赦 å
ä» å, \sk å çº ä» å \sk æ ä½ ç, \sk ä» å ä¸ æ å¾. \sk
%{æ 實 å¨ å 訴 ä½ , %} ä» æ¥ \sk ä½ è¦ å æ \sk å¨ æ¨ å 裡 äº. \sk \sk
æ¯ è¦ª \sk ç ä½ ç å
å, \sk \sk (é å¾) \sk ç ä½ ç æ¯ 親. \sk
æ ç \sk ç¥ åª! \sk æ ç \sk ç¥ åª! \sk çº ç 麽 é¢ æ£ æ! \sk \sk
æ \sk 渴 äº! \sk
æ äº! \sk \sk
ç¶ å! \sk æ å° æ é é 交 å¨ ç¥¢ æ 裡.
}
verseSolfege = \lyricmode {
ç¶2 å!2 赦8. å
16 ä»4 å,2 å 4 çº4 ä»8.~16 å2 æ8. ä½16 ç,2 ä»8 å8 ä¸8 æ8 å¾.2
%{æ 實 å¨ å 訴 ä½ , %} ä»4 æ¥2 ä½ 4 è¦4 å8~8 æ2 å¨4 æ¨8~8 å8~8 裡8~8 äº.2.
æ¯4 親2 ç4 ä½ 4 ç8 å
8 å.2. (é4 å¾)2 ç4 ä½ 4 ç8 æ¯8 親.2
æ8~8 ç2 ç¥8~8 åª!2 æ8~8 ç2 ç¥8~8 åª!2 çº4 ç8 麽8~8 é¢8~8 æ£8~8 æ2.
æ2 渴8~16~16 äº!2
æ\tuplet3/2{8( 8 8)} äº2 s4
ç¶8 å!4~8 s4 æ4 å°8~8 æ4 é8 é8 交8 å¨8 祢8 æ8 裡2.
}
verseJ = \lyricmode {
ç¶ \skip1 \skip1 å! \skip1 赦 å
ä» å, \skip1 å çº ä» å \skip1 æ ä½ ç, \skip1 ä» å ä¸ æ å¾. \skip1
%{æ 實 å¨ å 訴 ä½ , %} ä» æ¥ \skip1 ä½ è¦ å æ \skip1 å¨ æ¨ å 裡 äº. \skip1 \skip1
æ¯ è¦ª \skip1 ç ä½ ç å
å, \skip1 \skip1 (é å¾) \skip1 ç ä½ ç æ¯ 親. \skip1
æ ç \skip1 ç¥ åª! \skip1 æ ç \skip1 ç¥ åª! \skip1 çº ç 麽 é¢ æ£ æ! \skip1 \skip1
æ \skip1 渴 äº! \skip1
æ äº! \skip1 \skip1
ç¶ å! \skip1 æ å° æ é é 交 å¨ ç¥¢ æ 裡.
}
\score {
<<
\new JianpuStaff \jianpuMusic \new Voice = solfege { \globald \melodyd }
\new Lyrics \keepWithTag "SK" \lyricsto solfege { \verseSK }
\new Staff \new Voice = number { \globald \melodyd }
%\new Lyrics \removeWithTag "SK" \lyricsto number { \verseSK }
>>
\layout { }
%\midi { }
}
\book {
\bookOutputSuffix "midi"
\score {
<<
%\jianpuVoice
%\new JianpuStaff \jianpuMusic { \globald \melodyd }
%\new ChordNames \chordNames
\new Staff { \globald \melodyd }
%\addlyrics { \verse }
>>
%\layout { }
\midi { }
}
}
_______________________________________________
lilypond-user mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/lilypond-user