1 (define (natural-chord-alteration p)
2 "Return the natural alteration for step P."
3 (if (= (ly:pitch-steps p) 6)
8 (define-public (alteration->text-accidental-markup alteration)
14 (make-musicglyph-markup
15 (string-append "accidentals-" (number->string alteration))))))
17 (define (accidental->markup alteration)
18 "Return accidental markup for ALTERATION."
20 (make-line-markup (list empty-markup))
21 (conditional-kern-before
22 (alteration->text-accidental-markup alteration)
27 (define-public (note-name->markup pitch)
28 "Return pitch markup for PITCH."
32 (vector-ref #("C" "D" "E" "F" "G" "A" "B") (ly:pitch-notename pitch)))
33 (make-normal-size-super-markup
34 (accidental->markup (ly:pitch-alteration pitch))))))
37 (define-public ((chord-name->german-markup B-instead-of-Bb) pitch)
38 "Return pitch markup for PITCH, using german note names.
39 If B-instead-of-Bb is set to #t real german names are returned.
40 Otherwise semi-german names (with Bb and below keeping the british names)
42 (let* ((name (ly:pitch-notename pitch))
43 (alt (ly:pitch-alteration pitch))
44 (n-a (if (member (cons name alt) '((6 . -1) (6 . -2)))
45 (cons 7 (+ (if B-instead-of-Bb 1 0) alt))
50 (vector-ref #("C" "D" "E" "F" "G" "A" "H" "B") (car n-a)))
51 (make-normal-size-super-markup
52 (accidental->markup (cdr n-a)))))))
55 (define-public (note-name->german-markup pitch)
56 (let* ((name (ly:pitch-notename pitch))
57 (alt (ly:pitch-alteration pitch))
58 (n-a (if (member (cons name alt) '((6 . -1) (6 . -2)))
64 (list-ref '("c" "d" "e" "f" "g" "a" "h" "b") (car n-a))
65 (if (or (equal? (car n-a) 2) (equal? (car n-a) 5))
66 (list-ref '( "ses" "s" "" "is" "isis") (+ 2 (cdr n-a)))
67 (list-ref '("eses" "es" "" "is" "isis") (+ 2 (cdr n-a)))))))))
69 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
72 (define-public (sequential-music-to-chord-exceptions seq)
73 "Transform sequential music of <<a b c>>-\markup{ foobar } type to
74 (cons ABC-PITCHES FOOBAR-MARKUP)
77 (define (is-req-chord? m)
79 (memq 'event-chord (ly:get-mus-property m 'types))
80 (not (equal? (ly:make-moment 0 1) (ly:get-music-length m)))
83 (define (chord-to-exception-entry m)
86 (elts (ly:get-mus-property m 'elements))
89 (ly:get-mus-property x 'pitch)
92 (lambda (y) (memq 'note-event (ly:get-mus-property y 'types)))
94 (sorted (sort pitches ly:pitch<? ))
96 (non-root (map (lambda (x) (ly:pitch-diff x root)) (cdr sorted)))
99 (ly:get-mus-property x 'text)
104 (memq 'text-script-event
105 (ly:get-mus-property y 'types))) elts)
107 (text (if (null? texts)
117 (elts (filter-list is-req-chord? (ly:get-mus-property seq 'elements)))
118 (alist (map chord-to-exception-entry elts))
120 (filter-list (lambda (x) (cdr x)) alist)
124 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
125 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
129 ;; after Klaus Ignatzek, Die Jazzmethode fuer Klavier 1.
131 ;; The idea is: split chords into
133 ;; ROOT PREFIXES MAIN-NAME ALTERATIONS SUFFIXES ADDITIONS
135 ;; and put that through a layout routine.
137 ;; the split is a procedural process, with lots of set!.
141 ;; todo: naming is confusing: steps (0 based) vs. steps (1 based).
142 (define (pitch-step p)
143 "Musicological notation for an interval. Eg. C to D is 2."
144 (+ 1 (ly:pitch-steps p)))
146 (define (get-step x ps)
147 "Does PS have the X step? Return that step if it does."
150 (if (= (- x 1) (ly:pitch-steps (car ps)))
152 (get-step x (cdr ps)))
155 (define (replace-step p ps)
156 "Copy PS, but replace the step of P in PS."
161 (t (replace-step p (cdr ps)))
164 (if (= (ly:pitch-steps p) (ly:pitch-steps (car ps)))
171 (define (remove-step x ps)
172 "Copy PS, but leave out the Xth step."
177 (t (remove-step x (cdr ps)))
180 (if (= (- x 1) (ly:pitch-steps (car ps)))
187 (define-public (ignatzek-chord-names
188 in-pitches bass inversion
191 (define (remove-uptil-step x ps)
192 "Copy PS, but leave out everything below the Xth step."
195 (if (< (ly:pitch-steps (car ps)) (- x 1))
196 (remove-uptil-step x (cdr ps))
200 (define name-root (ly:get-context-property context 'chordRootNamer))
202 (let ((nn (ly:get-context-property context 'chordNoteNamer)))
204 ; replacing the next line with name-root gives guile-error...? -rz
206 ;; apparently sequence of defines is equivalent to let, not let* ? -hwn
207 (ly:get-context-property context 'chordRootNamer)
211 (define (is-natural-alteration? p)
212 (= (natural-chord-alteration p) (ly:pitch-alteration p))
216 (define (ignatzek-format-chord-name
226 "Format for the given (lists of) pitches. This is actually more
227 work than classifying the pitches."
229 (define (filter-main-name p)
230 "The main name: don't print anything for natural 5 or 3."
232 (or (not (ly:pitch? p))
233 (and (is-natural-alteration? p)
234 (or (= (pitch-step p) 5)
235 (= (pitch-step p) 3))))
240 (define (glue-word-to-step word x)
243 (make-simple-markup word)
247 (define (suffix-modifier->markup mod)
248 (if (or (= 4 (pitch-step mod))
249 (= 2 (pitch-step mod)))
250 (glue-word-to-step "sus" mod)
251 (glue-word-to-step "huh" mod)
254 (define (prefix-modifier->markup mod)
255 (if (and (= 3 (pitch-step mod))
256 (= -1 (ly:pitch-alteration mod)))
257 (make-simple-markup "m")
258 (make-simple-markup "huh")
261 (define (filter-alterations alters)
262 "Filter out uninteresting (natural) pitches from ALTERS."
265 (not (is-natural-alteration? p)))
272 (l (filter-list altered? alters))
273 (lp (last-pair alters))
276 ;; we want the highest also if unaltered
277 (if (and (not (altered? (car lp)))
278 (> (pitch-step (car lp)) 5))
279 (append l (last-pair alters))
283 (define (name-step pitch)
284 (define (step-alteration pitch)
285 (- (ly:pitch-alteration pitch)
286 (natural-chord-alteration pitch)
291 (num-markup (make-simple-markup
292 (number->string (pitch-step pitch))))
293 (args (list num-markup))
294 (total (if (= (ly:pitch-alteration pitch) 0)
295 (if (= (pitch-step pitch) 7)
296 (list (ly:get-context-property context 'majorSevenSymbol))
298 (cons (accidental->markup (step-alteration pitch)) args)
302 (make-line-markup total)))
306 (sep (ly:get-context-property context 'chordNameSeparator))
307 (root-markup (name-root root))
308 (add-markups (map (lambda (x)
309 (glue-word-to-step "add" x))
311 (filtered-alterations (filter-alterations alteration-pitches))
312 (alterations (map name-step filtered-alterations))
313 (suffixes (map suffix-modifier->markup suffix-modifiers))
314 (prefixes (map prefix-modifier->markup prefix-modifiers))
315 (main-markups (filter-main-name main-name))
316 (to-be-raised-stuff (markup-join
322 (base-stuff (if bass-pitch
323 (list sep (name-note bass-pitch))
330 (markup-join prefixes sep)
331 (make-super-markup to-be-raised-stuff))
333 (make-line-markup base-stuff)
339 (root (car in-pitches))
340 (pitches (map (lambda (x) (ly:pitch-diff x root)) (cdr in-pitches)))
341 (exceptions (ly:get-context-property context 'chordNameExceptions))
342 (exception (assoc-get-default pitches exceptions #f))
354 (list (name-root root) exception))
356 (begin ; no exception.
358 ; handle sus4 and sus2 suffix: if there is a 3 together with
359 ; sus2 or sus4, then we explicitly say add3.
362 (if (get-step j pitches)
364 (if (get-step 3 pitches)
366 (set! add-steps (cons (get-step 3 pitches) add-steps))
367 (set! pitches (remove-step 3 pitches))
369 (set! suffixes (cons (get-step j pitches) suffixes))
374 ;; do minor-3rd modifier.
375 (if (and (get-step 3 pitches)
376 (= (ly:pitch-alteration (get-step 3 pitches)) -1))
377 (set! prefixes (cons (get-step 3 pitches) prefixes))
380 ;; lazy bum. Should write loop.
382 ((get-step 7 pitches) (set! main-name (get-step 7 pitches)))
383 ((get-step 6 pitches) (set! main-name (get-step 6 pitches)))
384 ((get-step 5 pitches) (set! main-name (get-step 5 pitches)))
385 ((get-step 4 pitches) (set! main-name (get-step 4 pitches)))
386 ((get-step 3 pitches) (set! main-name (get-step 3 pitches)))
391 (3-diff? (lambda (x y)
392 (= (- (pitch-step y) (pitch-step x)) 2)))
393 (split (split-at 3-diff? (remove-uptil-step 5 pitches)))
395 (set! alterations (append alterations (car split)))
396 (set! add-steps (append add-steps (cdr split)))
397 (set! alterations (delq main-name alterations))
398 (set! add-steps (delq main-name add-steps))
400 (if (ly:pitch? inversion)
401 (set! bass-note inversion)
405 (set! bass-note bass)
408 ;; chords with natural (5 7 9 11 13) or leading subsequence.
409 ;; etc. are named by the top pitch, without any further
412 (ly:pitch? main-name)
413 (= 7 (pitch-step main-name))
414 (is-natural-alteration? main-name)
415 (pair? (remove-uptil-step 7 alterations))
416 (reduce (lambda (x y) (and x y))
417 (map is-natural-alteration? alterations)))
419 (set! main-name (tail alterations))
420 (set! alterations '())
423 (ignatzek-format-chord-name root prefixes main-name alterations add-steps suffixes bass-note)