1 ;;;; This file is part of LilyPond, the GNU music typesetter.
3 ;;;; Copyright (C) 2003--2011 Jan Nieuwenhuizen <janneke@gnu.org>
5 ;;;; LilyPond is free software: you can redistribute it and/or modify
6 ;;;; it under the terms of the GNU General Public License as published by
7 ;;;; the Free Software Foundation, either version 3 of the License, or
8 ;;;; (at your option) any later version.
10 ;;;; LilyPond is distributed in the hope that it will be useful,
11 ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ;;;; GNU General Public License for more details.
15 ;;;; You should have received a copy of the GNU General Public License
16 ;;;; along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
19 ;;;; NOTE: this is experimental code
20 ;;;; Base and inversion are ignored.
21 ;;;; Naming of the base chord (steps 1-5) is handled by exceptions only
22 ;;;; see input/test/chord-names-dpnj.ly
25 (define (default-note-namer pitch)
26 (note-name->markup pitch #f))
28 (define (markup-or-empty-markup markup)
29 "Return MARKUP if markup, else empty-markup"
30 (if (markup? markup) markup empty-markup))
32 (define (conditional-kern-before markup bool amount)
33 "Add AMOUNT of space before MARKUP if BOOL is true."
36 (list (make-hspace-markup amount)
40 (define-public (banter-chord-names pitches bass inversion context)
41 (ugh-compat-double-plus-new-chord->markup
42 'banter pitches bass inversion context '()))
44 (define-public (jazz-chord-names pitches bass inversion context)
45 (ugh-compat-double-plus-new-chord->markup
46 'jazz pitches bass inversion context '()))
48 (define-public (ugh-compat-double-plus-new-chord->markup
49 style pitches bass inversion context options)
50 "Entry point for @code{New_chord_name_engraver}.
52 FIXME: func, options/context have changed
54 See @file{double-plus-new-chord-name.scm} for the signature of @var{style}.
55 @var{pitches}, @var{bass}, and @var{inversion} are lily pitches.
56 @var{options} is an alist-alist (see @file{input/test/dpncnt.ly})."
58 (define (step-nr pitch)
59 (let* ((pitch-nr (+ (* 7 (ly:pitch-octave pitch))
60 (ly:pitch-notename pitch)))
61 (root-nr (+ (* 7 (ly:pitch-octave (car pitches)))
62 (ly:pitch-notename (car pitches)))))
63 (+ 1 (- pitch-nr root-nr))))
65 (define (next-third pitch)
66 (ly:pitch-transpose pitch
67 (ly:make-pitch 0 2 (if (or (= (step-nr pitch) 3)
68 (= (step-nr pitch) 5))
71 (define (step-alteration pitch)
72 (let* ((diff (ly:pitch-diff (ly:make-pitch 0 0 0) (car pitches)))
73 (normalized-pitch (ly:pitch-transpose pitch diff))
74 (alteration (ly:pitch-alteration normalized-pitch)))
75 (if (= (step-nr pitch) 7) (+ alteration SEMI-TONE) alteration)))
77 (define (pitch-unalter pitch)
78 (let ((alteration (step-alteration pitch)))
81 (ly:make-pitch (ly:pitch-octave pitch) (ly:pitch-notename pitch)
82 (- (ly:pitch-alteration pitch) alteration)))))
84 (define (step-even-or-altered? pitch)
85 (let ((nr (step-nr pitch)))
86 (if (!= (modulo nr 2) 0)
87 (!= (step-alteration pitch) 0)
90 (define (step->markup-plusminus pitch)
93 (make-simple-markup (number->string (step-nr pitch)))
95 (case (step-alteration pitch)
100 ((DOUBLE-SHARP) "++"))))))
102 (define (step->markup-accidental pitch)
104 (list (accidental->markup (step-alteration pitch))
105 (make-simple-markup (number->string (step-nr pitch))))))
107 (define (step->markup-ignatzek pitch)
109 (if (and (= (step-nr pitch) 7)
110 (= (step-alteration pitch) 1))
111 (list (ly:context-property context 'majorSevenSymbol))
112 (list (accidental->markup (step-alteration pitch))
113 (make-simple-markup (number->string (step-nr pitch)))))))
116 (define (make-sub->markup step->markup)
118 (make-line-markup (list (make-simple-markup "no")
119 (step->markup pitch)))))
121 (define (step-based-sub->markup step->markup pitch)
122 (make-line-markup (list (make-simple-markup "no") (step->markup pitch))))
124 (define (get-full-list pitch)
125 (if (<= (step-nr pitch) (step-nr (last pitches)))
126 (cons pitch (get-full-list (next-third pitch)))
129 (define (get-consecutive nr pitches)
131 (let* ((pitch-nr (step-nr (car pitches)))
132 (next-nr (if (!= (modulo pitch-nr 2) 0) (+ pitch-nr 2) nr)))
134 (cons (car pitches) (get-consecutive next-nr (cdr pitches)))
138 (define (full-match exceptions)
139 (if (pair? exceptions)
140 (let* ((e (car exceptions))
142 (if (equal? e-pitches pitches)
144 (full-match (cdr exceptions))))
147 (define (partial-match exceptions)
148 (if (pair? exceptions)
149 (let* ((e (car exceptions))
151 (if (equal? e-pitches (take pitches (length e-pitches)))
153 (partial-match (cdr exceptions))))
157 (write-me "pitches: " pitches)))
158 (let* ((full-exceptions
159 (ly:context-property context 'chordNameExceptionsFull))
160 (full-exception (full-match full-exceptions))
161 (full-markup (if full-exception (cadr full-exception) '()))
163 (ly:context-property context 'chordNameExceptionsPartial))
164 (partial-exception (partial-match partial-exceptions))
165 (partial-pitches (if partial-exception (car partial-exception) '()))
166 (partial-markup-prefix
167 (if partial-exception (markup-or-empty-markup
168 (cadr partial-exception)) empty-markup))
169 (partial-markup-suffix
170 (if (and partial-exception (pair? (cddr partial-exception)))
171 (markup-or-empty-markup (caddr partial-exception)) empty-markup))
173 (full (get-full-list root))
174 ;; kludge alert: replace partial matched lower part of all with
175 ;; 'normal' pitches from full
177 (all (append (take full (length partial-pitches))
178 (drop pitches (length partial-pitches))))
181 (missing (list-minus full (map pitch-unalter all)))
182 (consecutive (get-consecutive 1 all))
183 (rest (list-minus all consecutive))
184 (altered (filter step-even-or-altered? all))
185 (cons-alt (filter step-even-or-altered? consecutive))
186 (base (list-minus consecutive altered)))
190 (write-me "full:" full)
191 ;; (write-me "partial-pitches:" partial-pitches)
192 (write-me "full-markup:" full-markup)
193 (write-me "partial-markup-perfix:" partial-markup-prefix)
194 (write-me "partial-markup-suffix:" partial-markup-suffix)
195 (write-me "all:" all)
196 (write-me "altered:" altered)
197 (write-me "missing:" missing)
198 (write-me "consecutive:" consecutive)
199 (write-me "rest:" rest)
200 (write-me "base:" base)))
205 ;; + steps:altered + (highest all -- if not altered)
208 (let* ((root->markup (assoc-get
209 'root->markup options default-note-namer))
210 (step->markup (assoc-get
211 'step->markup options step->markup-plusminus))
212 (sub->markup (assoc-get
215 (step-based-sub->markup step->markup x))))
217 'separator options (make-simple-markup "/"))))
221 (make-line-markup (list (root->markup root) full-markup))
226 partial-markup-prefix
227 (make-normal-size-super-markup
232 (if (and (> (step-nr highest) 5)
234 (step-even-or-altered? highest)))
235 (list highest) '())))
236 (list partial-markup-suffix)
237 (list (map sub->markup missing)))
243 ;; + steps:(highest base) + cons-alt
246 (let* ((root->markup (assoc-get
247 'root->markup options default-note-namer))
251 ;;'step->markup options step->markup-accidental))
252 'step->markup options step->markup-ignatzek))
254 'separator options (make-simple-markup " ")))
255 (add-prefix (assoc-get 'add-prefix options
256 (make-simple-markup " add"))))
260 (make-line-markup (list (root->markup root) full-markup))
265 partial-markup-prefix
266 (make-normal-size-super-markup
270 ;; kludge alert: omit <= 5
271 ;;(markup-join (map step->markup
272 ;; (cons (last base) cons-alt)) sep)
278 ;; c:6.9 C5 6add9 -> C6 add 9 (add?)
279 ;; ch = \chords { c c:2 c:3- c:6.9^7 }
280 (markup-join (map step->markup
281 (let ((tb (last base)))
282 (if (> (step-nr tb) 5)
289 (markup-join (map step->markup rest) sep)
290 partial-markup-suffix))))))))
292 (else empty-markup))))