lilypond-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Rootless slash chords, 2017 edition


From: Thomas Morley
Subject: Re: Rootless slash chords, 2017 edition
Date: Thu, 30 Mar 2017 00:06:23 +0200

2017-03-28 19:49 GMT+02:00 Thomas Morley <address@hidden>:
> 2017-03-28 0:39 GMT+02:00 Dmitry <address@hidden>:

>> - in Chord_name_engraver::process_music, track repeating root parts of
>> slash chords and pass NIL pitches to a chordNameFunction in case of
>> repetition. Everything should be similar to handling chordChanges,
>> however this time we should remember and compare whole chord
>> structures, not markup.

>
> %% Tries to compare the relevant parts of the markups for current and previous
> %% chord.
> %%
> %% Probably it would be far easier to compare actual pitches

Below some code actually tracking and comparing pitches.
The bass-only feature can be switched on/off.
One limitation persists, inversions are not recognized, see third example.

\version "2.19.57"

#(define (define-translator-property symbol type? description)
  (if (not (and (symbol? symbol)
    (procedure? type?)
    (string? description)))
      (ly:error "error in call of define-translator-property"))
  (if (not (equal? (object-property symbol 'translation-doc) #f))
      (ly:error (_ "symbol ~S redefined") symbol))

  (set-object-property! symbol 'translation-type? type?)
  (set-object-property! symbol 'translation-doc description)
  symbol)

#(for-each
  (lambda (x)
    (apply define-translator-property x))
    `(
      (dropEqualRoot
       ,boolean?
       "To be used in @code{ChordName}-context.  If set @code{#t}, successive
chords, which differ only in their bass, will have only this bass printed.")
       ))

#(define (test-engraver ctx)
  (let ((prev '())
        (notes '())
        (chord-name-grobs '()))
    (make-engraver
      (listeners
         ((note-event engraver ev)
           (set! notes (cons (ly:prob-property ev 'music-cause) notes))))
      (acknowledgers
         ((chord-name-interface engraver grob source-engraver)
            (set! chord-name-grobs (cons grob chord-name-grobs))))
      ((stop-translation-timestep translator)
         (let* (;; not sure yet, whether 'sorted-notes' is needed and should
                ;; replace 'notes' in 'current-bass+elts'
                ;(sorted-notes
                ;  (sort
                ;    notes
                ;      (lambda (n1 n2)
                ;        (ly:pitch<?
                ;          (ly:music-property n1 'pitch)
                ;          (ly:music-property n2 'pitch)))))
                ;
                (current-bass+elts
                  (call-with-values
                    (lambda ()
                      (partition
                        (lambda (n)
                          (or (boolean? (ly:music-property n 'bass))
                              (boolean? (ly:music-property n 'inversion))))
                        notes))
                    (lambda (a b)
                      (list
                        (map (lambda (n) (ly:music-property n 'pitch)) a)
                        (map (lambda (n) (ly:music-property n 'pitch)) b))))))
         (if (and (pair? prev)
                  (pair? (car current-bass+elts))
                  (not (equal? (car current-bass+elts) (car prev)))
                  (ly:context-property ctx 'dropEqualRoot)
                  (equal? (cdr current-bass+elts) (cdr prev)))
             (ly:grob-set-property! (car chord-name-grobs) 'text
              (make-line-markup
                (list
                  (ly:context-property ctx 'slashChordSeparator)
                  (note-name->markup (caar current-bass+elts) #f)))))
         (set! prev current-bass+elts)
         (set! chord-name-grobs '())
         (set! notes '())))
      ((finalize translator)
         (set! prev '())))))

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% EXAMPLES
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\paper {
  indent = 0
  ragged-right = ##f
}

\layout {
  \context {
      \Score
      \override RehearsalMark.self-alignment-X = #LEFT
  }
  \context {
    \Staff
    \accidentalStyle forget
  }
  \context {
    \ChordNames
    dropEqualRoot = ##t
    \consists \test-engraver
  }
}

%%%%%%%
%% I
%%%%%%%

\markup
\rounded-box \fill-line { "Various tests" }

tstI =
\chordmode {
    c4:m/e c:m c:m/+g c:m/fes c/fes c/d c:7/d c:7/+g d e e:m f:m f:m f
}
<<
  \new ChordNames \tstI
  \new Staff \tstI
>>

%%%%%%%
%% II
%%%%%%%

\markup
\rounded-box \fill-line { "Test switching on/off via \"dropEqualRoot\"" }

tstII =
\chordmode {
    \mark "dropEqualRoot = ##t in \\layout"
    c4
    c/f
    c:m7
    c:m7/+bes
    c:m7
    c:m7/cis
    r2
    \break
    \set dropEqualRoot = ##f
    \mark "\\set dropEqualRoot = ##f"
    c4
    c/f
    c:m7
    c:m7/+bes
    c:m7
    c:m7/cis
    r2
    \break
    \unset dropEqualRoot
    \mark "\\set dropEqualRoot = ##t"
    c4
    c/f
    c:m7
    c:m7/+bes
    c:m7
    c:m7/cis
    r2
}
<<
  \new ChordNames  \tstII
  \new Staff \tstII
>>

%%%%%%%
%% III
%%%%%%%

\markup
\rounded-box \fill-line {
  \column {
    "Limitation:"
     \wordwrap-string
     %% jEdit highlighting is not smart enough, thus the strange line-break ...
     #"Here the \"root
\"-part is never dropped, because the main-chords are always different, which
can't be observed in ChordNames, though.
All chords but the last are inversions!"
  }
}

tstIII =
\chordmode {
    c:m7
    c:m7/bes
    c:m7/g
    c:m7/ees
    c:m7/+bes
}
<<
  \new ChordNames  \tstIII
  \new Staff \tstIII
>>

HTH,
  Harm



reply via email to

[Prev in Thread] Current Thread [Next in Thread]