From 080d6ab968012d491c7fa70fa962d2001ace1ecc Mon Sep 17 00:00:00 2001 From: David Kastrup Date: Wed, 9 Jul 2014 17:31:11 +0200 Subject: [PATCH] Issue 2617: simple chord inversions take 2 octaves With this change, chord inversions transpose all notes following the inversion from the original chord down along with the inversion, as long as the result ends up below the root note of the uninverted chord. So with \chordmode { c:11 } => < c' e' g' bes' d'' f'' > we get \chordmode { c:11/e } => < e g bes c' d'' f'' > In order to have the Chord_name_engraver reconstruct the correct uninverted chord, all the additionally octavated note events are given an octavation property like the inversion event itself. An "inversion" on the chord root just transposes the chord root one octave down, leaving the rest in place. --- lily/chord-name-engraver.cc | 36 ++++++++++------------- scm/chord-entry.scm | 58 +++++++++++++++++++++++-------------- 2 files changed, 52 insertions(+), 42 deletions(-) diff --git a/lily/chord-name-engraver.cc b/lily/chord-name-engraver.cc index 0ca322716f..0cb0a7d8e4 100644 --- a/lily/chord-name-engraver.cc +++ b/lily/chord-name-engraver.cc @@ -92,7 +92,6 @@ Chord_name_engraver::process_music () markup = chord_name->get_property ("text"); if (!Text_interface::is_markup (markup)) { - Stream_event *inversion_event = 0; for (vsize i = 0; i < notes_.size (); i++) { Stream_event *n = notes_[i]; @@ -100,30 +99,25 @@ Chord_name_engraver::process_music () if (!unsmob_pitch (p)) continue; - if (n->get_property ("inversion") == SCM_BOOL_T) - { - inversion_event = n; - inversion = p; - } - else if (n->get_property ("bass") == SCM_BOOL_T) + if (n->get_property ("bass") == SCM_BOOL_T) bass = p; else - pitches = scm_cons (p, pitches); - } - - if (inversion_event) - { - SCM oct = inversion_event->get_property ("octavation"); - if (scm_is_number (oct)) { - Pitch *p = unsmob_pitch (inversion_event->get_property ("pitch")); - int octavation = scm_to_int (oct); - Pitch orig = p->transposed (Pitch (-octavation, 0, 0)); - - pitches = scm_cons (orig.smobbed_copy (), pitches); + SCM oct = n->get_property ("octavation"); + if (scm_is_number (oct)) + { + Pitch orig = unsmob_pitch (p)->transposed (Pitch (-scm_to_int (oct), 0, 0)); + pitches = scm_cons (orig.smobbed_copy (), pitches); + } + else + pitches = scm_cons (p, pitches); + if (n->get_property ("inversion") == SCM_BOOL_T) + { + inversion = p; + if (!scm_is_number (oct)) + programming_error ("inversion does not have original pitch"); + } } - else - programming_error ("inversion does not have original pitch"); } pitches = scm_sort_list (pitches, Pitch::less_p_proc); diff --git a/scm/chord-entry.scm b/scm/chord-entry.scm index 0ea8e032a0..ae649700ae 100644 --- a/scm/chord-entry.scm +++ b/scm/chord-entry.scm @@ -16,7 +16,7 @@ ;;;; along with LilyPond. If not, see . ;; for define-safe-public when byte-compiling using Guile V2 -(use-modules (scm safe-utility-defs)) +(use-modules (scm safe-utility-defs) (ice-9 receive)) (define-public (construct-chord-elements root duration modifications) "Build a chord on root using modifiers in @var{modifications}. @@ -174,26 +174,42 @@ the bass specified. (define (make-chord-elements pitches bass duration inversion original-inv-pitch) "Make EventChord with notes corresponding to PITCHES, BASS and -DURATION, and INVERSION." - (define (make-note-ev pitch) - (make-music 'NoteEvent - 'duration duration - 'pitch pitch)) - (let ((nots (map make-note-ev pitches)) - (bass-note (if bass (make-note-ev bass) #f)) - (inv-note (if inversion (make-note-ev inversion) #f))) - (if bass-note - (begin - (set! (ly:music-property bass-note 'bass) #t) - (set! nots (cons bass-note nots)))) - (if inv-note - (begin - (set! (ly:music-property inv-note 'inversion) #t) - (set! (ly:music-property inv-note 'octavation) - (- (ly:pitch-octave inversion) - (ly:pitch-octave original-inv-pitch))) - (set! nots (cons inv-note nots)))) - nots)) +DURATION, and INVERSION. Notes above INVERSION are transposed downward +along with the inversion as long as they end up below at least one +non-inverted note." + (define (make-note-ev pitch . rest) + (apply make-music 'NoteEvent + 'duration duration + 'pitch pitch + rest)) + (cond (inversion + (let* ((octavation (- (ly:pitch-octave inversion) + (ly:pitch-octave original-inv-pitch))) + (down (ly:make-pitch octavation 0 0))) + (define (invert p) (ly:pitch-transpose down p)) + (define (make-inverted p . rest) + (apply make-note-ev (invert p) 'octavation octavation rest)) + (receive (uninverted high) + (span (lambda (p) (ly:pitch rather than + ;; or + (values '() high) + (span (lambda (p) + (ly:pitch