\version "2.14.2" % Thanks to David Nalesnik #(set-global-staff-size 20) #(define (sort-by-X-coord sys grob-lst) "Arranges a list of grobs in ascending order by their X-coordinates" (let* ((X-coord (lambda (x) (ly:grob-relative-coordinate x sys X))) (comparator (lambda (p q) (< (X-coord p) (X-coord q))))) (sort grob-lst comparator))) #(define (find-bounding-grobs bar-line grob-lst) (let* ((sys (ly:grob-system bar-line)) (X-coord (lambda (n) (ly:grob-relative-coordinate n sys X))) (bar-line-X (X-coord bar-line))) (define (helper lst) (if (and (< (X-coord (car lst)) bar-line-X) (> (X-coord (cadr lst)) bar-line-X)) (cons (car lst) (cadr lst)) (if (null? (cddr lst)) (cons bar-line bar-line) (helper (cdr lst))))) (helper grob-lst))) #(define (read-out ls1 ls2 ls3 symbol) "Filters all elements of ls1 from ls2 and appends it to ls3" (set! ls3 (append ls3 (filter (lambda (x) (eq? (car ls1) (symbol x))) ls2))) (if (null? (cdr ls1)) ls3 (read-out (cdr ls1) ls2 ls3 symbol))) #(define ((center-text-script x-offs) grob) (let* ((sys (ly:grob-system grob)) (elements-lst (ly:grob-array->list (ly:grob-object sys 'all-elements))) (grob-name (lambda (x) (assq-ref (ly:grob-property x 'meta) 'name))) (X-extent (lambda (q) (ly:grob-extent q sys X))) (lst-1 (filter (lambda (x) (eq? 'BarLine (grob-name x))) elements-lst)) (add (cdr (ly:grob-property (car lst-1) 'X-extent))) ;; Grobs to center between (args (list 'BarLine 'TimeSignature 'KeySignature 'KeyCancellation 'Clef)) (grob-lst (read-out args elements-lst '() grob-name)) (new-grob-lst (remove (lambda (x) (interval-empty? (X-extent x))) grob-lst)) (sorted-grob-lst (sort-by-X-coord sys new-grob-lst)) ;; Bounds (bounds (find-bounding-grobs grob sorted-grob-lst)) (left (cdr (X-extent (car bounds)))) (right (car (X-extent (cdr bounds)))) (basic-offset (- (average left right) (* -1 add) (interval-center (X-extent grob)) (* -1 x-offs)))) ;; End of Defs in let* ;; Calculation (ly:grob-translate-axis! grob basic-offset X))) centerTextScriptOn = { \override TextScript #'after-line-breaking = #(center-text-script 0) } centerTextScriptOff = { \revert TextScript #'after-line-breaking } onceCenterTextScript = #(define-music-function (parser location x-offs)(number?) #{ \once \override TextScript #'after-line-breaking = #(center-text-script $x-offs) #}) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #(define (number->integer-list integer) (define (helper number ls) (set! ls (cons number ls)) (if (= (- number 1) 0) ls (helper (- number 1) ls))) (if (and (integer? integer) (> integer 0)) (helper integer '()) (begin (newline) (display "__________Argument is not integer or not greater than 0__________") (newline)))) #(define (list-helper ls1 ls2 ls3) (let ((text (make-music 'TextScriptEvent 'direction 1 'text (markup #:fontsize -5 #:number (number->string (car ls2)));(string-append " " (number->string (car ls2)))) ))) (set! ls3 (cons (car ls1) (cons text ls3))) (if (null? (cdr ls2)) (reverse ls3) (list-helper ls1 (cdr ls2) ls3)))) barCount = #(define-music-function (parser location music) (ly:music?) (let* ((repeat-count (if (eq? 'UnfoldedRepeatedMusic (ly:music-property music 'name)) (ly:music-property music 'repeat-count) (display "no 'UnfoldedRepeatedMusic"))) (mus-len (ly:music-length music)) (num (ly:moment-main-numerator mus-len)) (denom (ly:moment-main-denominator mus-len)) (skip (list #{ \scaleDurations #(cons (/ $num $repeat-count) $denom) s1 #} )) (lst (list-helper skip (number->integer-list repeat-count) '())) (skip-music (make-sequential-music lst))) (make-sequential-music (list (make-music 'SimultaneousMusic 'elements (list music skip-music)))))) centerCountRepeatUnfold = #(define-music-function (parser location center? music)(boolean? ly:music?) (if center? #{ \override TextScript #'padding = #1 \centerTextScriptOn \barCount $music \centerTextScriptOff #} #{ \override TextScript #'padding = #1 \override TextScript #'X-offset = #ly:self-alignment-interface::aligned-on-x-parent \override TextScript #'self-alignment-X = #CENTER \barCount $music \centerTextScriptOff #})) #(define (Text_align_engraver ctx) (let ((scripts '()) (note-column #f)) `((acknowledgers (note-column-interface . ,(lambda (trans grob source) ;; cache NoteColumn in this Voice context (set! note-column grob))) (text-script-interface . ,(lambda (trans grob source) ;; whenever a TextScript is acknowledged, ;; add it to `scripts' list (set! scripts (cons grob scripts))))) (stop-translation-timestep . ,(lambda (trans) ;; if any TextScript grobs exist, ;; set NoteColumn as X-parent (and (pair? scripts) (for-each (lambda (script) (set! (ly:grob-parent script X) note-column)) scripts)) ;; clear scripts ready for next timestep (set! scripts '())))))) %----------- test % \drums { % \time 5/8 % \set Staff.instrumentName = "Example 1 " % \centerCountRepeatUnfold ##f % \repeat unfold 3 { hh2 r8 } % } % \drums { % \time 4/4 % \set Staff.instrumentName = "Example 2 " % bd2 bd % \centerCountRepeatUnfold ##t % \repeat unfold 10 { hh4 r bd16 bd bd bd r4 } % bd2 r % } % \relative c' { % \set Staff.instrumentName = "Example 3 " % \centerCountRepeatUnfold ##f % \repeat unfold 10 { c1 } % \key cis\major % \time 8/8 % \centerCountRepeatUnfold ##t % \repeat unfold 4 { <<{ a''8 [a a a] a [a a a]}\\{a,,2 a}>> \noBreak } % \break % \key ces\major % \time 4/4 % \centerCountRepeatUnfold ##f % \repeat unfold 10 { ees'1 } % } % \layout { % \context { % \Score % \consists #Text_align_engraver % } % } { \set Staff.instrumentName = \markup \column { \line {Without} \line {markup} } R1 | R1 | R1 | R1 | } { \set Staff.instrumentName = \markup \column { \line {With} \line {markup} } R1*1^\markup \huge \bold "1" | R1*1^\markup \huge \bold "1" | R1*1^\markup \huge \bold "1" } { a,-.\pp r a-. r \centerCountRepeatUnfold ##t \repeat unfold 2 { a-. r a-. r } } { a,-.\pp r a-. r \centerCountRepeatUnfold ##t \repeat unfold 5 { a-. } }