(define-public (construct-chord-elements root duration modifications) "Build a chord on root using modifiers in @var{modifications}. @code{NoteEvents} have duration @var{duration}. Notes: Natural 11 is left from chord if not explicitly specified. Entry point for the parser." (let* ( ;;;; changed: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (modifications (if (and (member sus-modifier modifications) (null? (cdr (member sus-modifier modifications)))) (append modifications (list (ly:make-pitch 0 3))) modifications)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (flat-mods (flatten-list modifications)) (base-chord (stack-thirds (ly:make-pitch 0 4 0) the-canonical-chord)) (complete-chord '()) (bass #f) (inversion #f) (lead-mod #f) (explicit-11 #f) ;;;; changed: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (explicit-5 #f) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (start-additions #t)) (define (interpret-inversion chord mods) "Read /FOO part. Side effect: INVERSION is set." (if (and (> (length mods) 1) (eq? (car mods) 'chord-slash)) (begin (set! inversion (cadr mods)) (set! mods (cddr mods)))) (interpret-bass chord mods)) (define (interpret-bass chord mods) "Read /+FOO part. Side effect: BASS is set." (if (and (> (length mods) 1) (eq? (car mods) 'chord-bass)) (begin (set! bass (cadr mods)) (set! mods (cddr mods)))) (if (pair? mods) (ly:warning (_ "Spurious garbage following chord: ~A") mods)) chord) (define (interpret-removals chord mods) (define (inner-interpret chord mods) (if (and (pair? mods) (ly:pitch? (car mods))) (inner-interpret (remove-step (+ 1 (ly:pitch-steps (car mods))) chord) (cdr mods)) (interpret-inversion chord mods))) (if (and (pair? mods) (eq? (car mods) 'chord-caret)) (inner-interpret chord (cdr mods)) (interpret-inversion chord mods))) (define (interpret-additions chord mods) "Interpret additions. TODO: should restrict modifier use?" ;;;; TODO reflect explicit-5 here as well? (cond ((null? mods) chord) ((ly:pitch? (car mods)) (if (= (pitch-step (car mods)) 11) (set! explicit-11 #t)) (interpret-additions (cons (car mods) (remove-step (pitch-step (car mods)) chord)) (cdr mods))) ((procedure? (car mods)) (interpret-additions ((car mods) chord) (cdr mods))) (else (interpret-removals chord mods)))) (define (pitch-octavated-strictly-below p root) "return P, but octavated, so it is below ROOT" (ly:make-pitch (+ (ly:pitch-octave root) (if (> (ly:pitch-notename root) (ly:pitch-notename p)) 0 -1)) (ly:pitch-notename p) (ly:pitch-alteration p))) (define (process-inversion complete-chord) "Take out inversion from COMPLETE-CHORD, and put it at the bottom. Return (INVERSION . REST-OF-CHORD). Side effect: put original pitch in INVERSION. If INVERSION is not in COMPLETE-CHORD, it will be set as a BASS, overriding the bass specified. " (let* ((root (car complete-chord)) (inv? (lambda (y) (and (= (ly:pitch-notename y) (ly:pitch-notename inversion)) (= (ly:pitch-alteration y) (ly:pitch-alteration inversion))))) (rest-of-chord (remove inv? complete-chord)) (inversion-candidates (filter inv? complete-chord)) (down-inversion (pitch-octavated-strictly-below inversion root))) (if (pair? inversion-candidates) (set! inversion (car inversion-candidates)) (begin (set! bass inversion) (set! inversion #f))) (if inversion (cons down-inversion rest-of-chord) rest-of-chord))) ;; root is always one octave too low. ;; something weird happens when this is removed, ;; every other chord is octavated. --hwn... hmmm. (set! root (ly:pitch-transpose root (ly:make-pitch 1 0 0))) ;; skip the leading : , we need some of the stuff following it. (if (pair? flat-mods) (if (eq? (car flat-mods) 'chord-colon) (set! flat-mods (cdr flat-mods)) (set! start-additions #f))) ;; remember modifier (if (and (pair? flat-mods) (procedure? (car flat-mods))) (begin (set! lead-mod (car flat-mods)) (set! flat-mods (cdr flat-mods)))) ;; extract first number if present, and build pitch list. (if (and (pair? flat-mods) (ly:pitch? (car flat-mods)) (not (eq? lead-mod sus-modifier))) (begin (if (= (pitch-step (car flat-mods)) 11) (set! explicit-11 #t)) (display-scheme-music (if (ly:pitch? (car flat-mods)) (ly:pitch-alteration (car flat-mods)) ) ) ;;;; changed ;;;;;;;;;;;;;;;;;;;;;;;;;; (if (and (= (pitch-step (car flat-mods)) 5) (= 0 (ly:pitch-alteration (car flat-mods)))) (set! explicit-5 #t)) ;;;;;;;;;;;;;;;;;;;;;;;;;; (set! base-chord (stack-thirds (car flat-mods) the-canonical-chord)) (set! flat-mods (cdr flat-mods)))) ;; apply modifier (if (procedure? lead-mod) (set! base-chord (lead-mod base-chord))) (set! complete-chord (if start-additions (interpret-additions base-chord flat-mods) (interpret-removals base-chord flat-mods))) (set! complete-chord (sort complete-chord ly:pitch