Spaces:
Sleeping
Sleeping
File size: 8,853 Bytes
f65fe85 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
;;;; This file is part of LilyPond, the GNU music typesetter.
;;;;
;;;; Copyright (C) 2000--2020 Jan Nieuwenhuizen <[email protected]>
;;;; Han-Wen Nienhuys <[email protected]>
;;;;
;;;; LilyPond is free software: you can redistribute it and/or modify
;;;; it under the terms of the GNU General Public License as published by
;;;; the Free Software Foundation, either version 3 of the License, or
;;;; (at your option) any later version.
;;;;
;;;; LilyPond is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;;; GNU General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU General Public License
;;;; along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
;; It is a pity that there is no rassoc in Scheme.
(define*-public (rassoc item alist #:optional (test equal?))
(do ((alist alist (cdr alist))
(result #f result))
((or result (null? alist)) result)
(if (and (car alist) (test item (cdar alist)))
(set! result (car alist)))))
(define (natural-chord-alteration p)
"Return the natural alteration for step P."
(if (= (ly:pitch-steps p) 6)
FLAT
0))
(define (conditional-string-capitalize str condition)
(if condition
str
(string-capitalize str)))
;;
;; TODO: make into markup.
;;
;; flat and flat-based glyphs have a lesser Y-extent than sharps.
(define (short-glyph? alteration)
(< alteration 0))
;; natural, single flat and mirrored flat have a narrower X-extent.
(define (narrow-glyph? alteration)
(member alteration
;; flat-based glyphs in various notation systems.
;; (duplicates come from the input files, for
;; consistency’s sake) -vv
'(0
;; western accidentals
-1/2 -1/4
;; makam
-1/9 -5/18 -6/18 -4/9 -5/9 -8/9
;; turkish makam
-1/12 -3/12 -4/12 -5/12 -6/12 -10/12
;; hel-arabic
-1/4 -3/4 ; -5/2 -> flatflat, ignored
-7/2)))
(define-public (alteration->text-accidental-markup alteration)
(make-smaller-markup
(make-raise-markup
(if (short-glyph? alteration)
0.3
0.6)
(make-musicglyph-markup
;; FIXME -- use current glyph-name-alist here.
(assoc-get alteration standard-alteration-glyph-name-alist "")))))
(define (accidental->markup alteration)
"Return accidental markup for ALTERATION."
(if (= alteration 0)
(make-line-markup (list empty-markup))
(conditional-kern-before
(alteration->text-accidental-markup alteration)
(narrow-glyph? alteration) 0.094725)))
(define (accidental->markup-italian alteration)
"Return accidental markup for ALTERATION, for use after an italian chord root name."
(if (= alteration 0)
(make-hspace-markup 0.2)
(make-line-markup
(list
;; FIXME -- see issue 3330.
(make-hspace-markup (if (= alteration FLAT) 0.57285385 0.5))
(make-raise-markup 0.7 (alteration->text-accidental-markup alteration))
(make-hspace-markup (if (= alteration SHARP) 0.2 0.1))
))))
(define-public (note-name->string pitch . language)
"Return pitch string for @var{pitch}, without accidentals or octaves.
Current input language is used for pitch names, except if an
other @var{language} is specified."
;; See also note-name->lily-string if accidentals are needed.
(let* ((pitch-alist
(if (null? language) pitchnames
(assoc-get (car language)
language-pitch-names '())))
(result (rassoc pitch
(filter (lambda (p)
;; TODO: add exception for German B?
(eq? (ly:pitch-alteration (cdr p)) 0))
pitch-alist)
(lambda (a b)
(= (ly:pitch-notename a)
(ly:pitch-notename b))))))
(if result (symbol->string (car result)))))
(define-public (note-name->markup pitch lowercase?)
"Return pitch markup for @var{pitch}, including accidentals
printed as glyphs. If @var{lowercase?} is set to false, the
note names are capitalized."
(let ((str (note-name->string pitch)))
(make-line-markup
(list
(make-simple-markup
(conditional-string-capitalize str lowercase?))
(accidental->markup (ly:pitch-alteration pitch))))))
(define (pitch-alteration-semitones pitch)
(inexact->exact (round (* (ly:pitch-alteration pitch) 2))))
(define-safe-public ((chord-name->german-markup B-instead-of-Bb)
pitch lowercase?)
"Return pitch markup for PITCH, using german note names.
If B-instead-of-Bb is set to #t real german names are returned.
Otherwise semi-german names (with Bb and below keeping the british names)
"
(let* ((name (ly:pitch-notename pitch))
(alt-semitones (pitch-alteration-semitones pitch))
(n-a (if (member (cons name alt-semitones) `((6 . -1) (6 . -2)))
(cons 7 (+ (if B-instead-of-Bb 1 0) alt-semitones))
(cons name alt-semitones))))
(make-line-markup
(list
(make-simple-markup
(conditional-string-capitalize
;; TODO: use note-name->string with an exception for B.
(vector-ref #("c" "d" "e" "f" "g" "a" "h" "b") (car n-a))
lowercase?))
(accidental->markup (/ (cdr n-a) 2))))))
(define-safe-public (note-name->german-markup pitch lowercase?)
;; TODO: rewrite using note-name->lily-string.
;; FIXME: lowercase? is ignored.
(let* ((name (ly:pitch-notename pitch))
(alt-semitones (pitch-alteration-semitones pitch))
(n-a (if (member (cons name alt-semitones) `((6 . -1) (6 . -2)))
(cons 7 (+ 1 alt-semitones))
(cons name alt-semitones))))
(make-line-markup
(list
(string-append
(list-ref '("c" "d" "e" "f" "g" "a" "h" "b") (car n-a))
(if (or (equal? (car n-a) 2) (equal? (car n-a) 5))
(list-ref '( "ses" "s" "" "is" "isis") (+ 2 (cdr n-a)))
(list-ref '("eses" "es" "" "is" "isis") (+ 2 (cdr n-a)))))))))
(define ((chord-name->italian-markup french?) pitch lowercase?)
"Return pitch markup for @var{pitch}, using Italian/@/French note names.
If @var{re-with-eacute} is set to @code{#t}, french `ré' is returned for
pitch@tie{}D instead of `re'."
(let* ((name (note-name->string pitch
(if french? 'français 'italiano)))
(alt (ly:pitch-alteration pitch)))
(make-line-markup
(list
(make-simple-markup
(conditional-string-capitalize name lowercase?))
(accidental->markup-italian alt)))))
(export chord-name->italian-markup)
;; fixme we should standardize on omit-root (or the other one.)
;; perhaps the default should also be reversed --hwn
(define-safe-public (sequential-music-to-chord-exceptions seq . rest)
"Transform sequential music SEQ of type <<c d e>>-\\markup{ foobar }
to (cons CDE-PITCHES FOOBAR-MARKUP), or to (cons DE-PITCHES
FOOBAR-MARKUP) if OMIT-ROOT is given and non-false.
"
(define (chord-to-exception-entry m)
(let* ((elts (ly:music-property m 'elements))
(omit-root (and (pair? rest) (car rest)))
(pitches (map (lambda (x) (ly:music-property x 'pitch))
(filter
(lambda (y) (memq 'note-event
(ly:music-property y 'types)))
elts)))
(sorted (sort pitches ly:pitch<?))
(root (car sorted))
;; ugh?
;;(diff (ly:pitch-diff root (ly:make-pitch -1 0 0)))
;; FIXME. This results in #<Pitch c> ...,
;; but that is what we need because default octave for
;; \chords has changed to c' too?
(diff (ly:pitch-diff root (ly:make-pitch 0 0 0)))
(normalized (map (lambda (x) (ly:pitch-diff x diff)) sorted))
(texts (map (lambda (x) (ly:music-property x 'text))
(filter
(lambda (y) (memq 'text-script-event
(ly:music-property y 'types)))
elts)))
(text (if (null? texts) #f (if omit-root (car texts) texts))))
(cons (if omit-root (cdr normalized) normalized) text)))
(define (is-event-chord? m)
(and
(memq 'event-chord (ly:music-property m 'types))
(not (equal? ZERO-MOMENT (ly:music-length m)))))
(let* ((elts (filter is-event-chord? (ly:music-property seq 'elements)))
(alist (map chord-to-exception-entry elts)))
(filter cdr alist)))
|