additional info for jianpu. the output from 7-speech+jianpu_10a_test.ly
From: MING TSANG <tsan...@rogers.com> To: "imj-...@bluewin.ch" <imj-...@bluewin.ch>; Lilypond-usermailinglist <lilypond-user@gnu.org> Sent: Monday, August 21, 2017 9:51 PM Subject: Re: Jianpu music notation question forgot to include lilypond user From: TSANGMING <tsan...@rogers.com> To: "imj-...@bluewin.ch" <imj-...@bluewin.ch> 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 lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user