Hallo,
ich wollte (auch um eine aus Einzelstimmen abgeschriebene Partitur zu kontrollieren - beim Abschreiben sind mir schon einige offensichtliche Fehler, am häufigsten vergessene Versetzungszeichen, aufgefallen) zu einer Partitur eine keine Harmonieanalyse in einer Spezialnotenzeile hinzufügen.
Mein Konzept:
- 5 Linien der Zeilen repräsentieren die schwaren Klaviertasten einer Oktave
- Es werden die jeweils klingenden Töne gezählt, ohne Berücksichtigung der Oktave, und als »Zahlen-Notenköpfe« in diese Notenzeile eingetragen
- Werden Akkordmuster erkannt, dann färbe ich die Notenköpfe entsprechend ein - oder füge einen Kennzeichnungstext unterhalb dieser Notenzeile ein - und der erkannte Grundton wird durch Fettdruck hervorgehoben
- Als »kleine« Harmonieanalyse wird der Baßton (tiefster Klang) weder gesucht noch ausgewertet
Um nicht gleich Score-weit alle Töne einzusammeln und gemäß
\transposition an den
Analyse-Staff zu übergeben, habe ich erst einmal alle melodischen Einzelstimmen richtig transponiert zu einer
Simultanen Musik im
Analyse-Staff zusammengefaßt.
Und, da es wohl nur mit einem Engraver vernünftig zu lösen ist, habe ich versucht solch einen zu programmieren.
Ich scheitere beim Versuch, die Notenköpfe zu erstellen. Lilypond stürzt (unter Win7) ab, Fehlercode = Windows Error Level = -1073741819 = hexadezimal D0000005.
Gleiches Verhalten in den Versionen 2.18.2 und 2.19.82.
Meine Test-Datei (nicht ganz klein):
\version "2.18.2"
% \version "2.19.82"
\include "analysis-engraver.ly"
%%%%% WORKAROUND: (first step)
% \include "analysis-output-engraver.ly"
ClA = {
\key f \major
f4 g a2
bes8 ces' g bes ces' a bes ces'
f1 f'
}
Ve = {
\key d \major
<fis' a'>2.-> a'4-.
b'1\trill
<f' a'>4 <fis' a' c'''> <f' as''> <f' as' b'>
<fis' a' b'>4 <fis' a' c' e'> <fis' a' c' es'> <fis' a' cis'>
}
Musik = <<
\new Staff { \transposition a \ClA }
\new Staff { \transposition c' \Ve }
>>
AnalyseMusik = <<
\transpose c' a \ClA
\Ve
>>
\score {
<< \Musik
\new Staff \with {
\remove Accidental_engraver
\remove Clef_engraver
\remove Key_engraver
\remove Time_signature_engraver
\remove Dot_column_engraver
\remove Dots_engraver
% \remove Script_engraver
\remove Multi_measure_rest_engraver
% \remove Text_engraver
\remove Tie_engraver
%%%%% DOES NOT WORK! Premature exist. (Windows Error Level = -1073741819
% there is a boolean in line 62 of »analysis-engraver.ly«
% to turn off the note head creation, which initiates the problem.
\consists #Analysis_engraver
%%%%% WORKAROUND: first step - export into a file
% \consists #(Analysis_output_engraver "Harmonie_analyse.ily")
} \new Voice \with {
\remove Accidental_engraver
\remove Dynamic_engraver
\remove Dot_column_engraver
\remove Dots_engraver
\remove Beam_engraver
\remove Multi_measure_rest_engraver
\remove Note_head_line_engraver
\remove Phrasing_slur_engraver
\remove Repeat_tie_engraver
\remove Rest_engraver
\remove Slur_engraver
\remove Stem_engraver
\remove Text_engraver
\remove Tie_engraver
\remove Script_engraver % scheint nicht zu funktionieren!
\remove Script_column_engraver
\remove Script_row_engraver
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\remove Note_heads_engraver
} {
% die fünf Linien entsprechen den schwarzen Tasten einer Klaviatur
\stopStaff
\override Staff.StaffSymbol.line-positions = #'(0 4 10 14 18)
\startStaff
\AnalyseMusik
}
%%%%% WORKAROUND (second step): include the generated ILY file as a new Staff
% \include "Harmonie_analyse.ily"
>>
}
und die angegeben Inlcude-Datei »analysis-engraver.ly« (noch weniger gekürzt):
%{
analysis-engraver.ly
%}
#(define (Analysis_engraver ctx)
(let ((pitch-list (list '() '() '() '() '() '() '() '() '() '() '() '()))
; c cis d es e f fis g as a b h
(event-list (list '() '() '() '() '() '() '() '() '() '() '() '()))
(is-main-mom #t)
(current-main-mom -1)
(note-started #f)
)
`((start-translation-timestep
. ,(lambda (trans)
(let* ((current-mom (ly:context-current-moment ctx))
(main-mom (ly:moment-main current-mom))
(grace-mom (ly:moment-grace current-mom)))
(set! is-main-mom (eq? grace-mom 0))
(if is-main-mom
(begin
; (for-each display (list "\nstart " main-mom " G " grace-mom "\n"))
(set! current-main-mom (ly:make-moment main-mom))
(for-each display (list "\ncurrent PitchList at " current-main-mom " :"))
(for-each (lambda (pl)
(for-each display (list "\nPL-Line." (length pl) " = " pl ))
) pitch-list)
(set! pitch-list (map (lambda (pe)
(filter (lambda (ts) (ly:moment<? current-main-mom ts)) pe)) pitch-list))
(display "\nafter terminated tones are removed:")
(for-each (lambda (pl)
(for-each display (list "\nPL-Line." (length pl) " = " pl ))
) pitch-list)
(display "\n")
))
)
)
)
(listeners
(note-event
. ,(lambda (trans ev)
(if is-main-mom
(let* ((pit (ly:event-property ev 'pitch))
(len (ly:event-property ev 'length))
(end-at (ly:moment-add len current-main-mom))
(st (modulo (ly:pitch-semitones pit) 12))
)
; (for-each display (list "\nlength " len " pitch " pit "\n"))
(for-each display (list "\nadd semitone " st " which ends at " end-at "\n"))
(list-set! pitch-list st (cons end-at (list-ref pitch-list st)))
(list-set! event-list st ev)
(set! note-started #t)
))
)
))
(stop-translation-timestep
. ,(lambda (trans)
(for-each display (list "\nend timestep\n"))
(if note-started
(let ((index 0))
(for-each (lambda (pl)
(if (and (not (null? pl))
#t) ; this section fails! You may use this boolean to turn it on/off
(let* ((usage-count (length pl))
(note-head (ly:engraver-make-grob trans 'NoteHead (ly:event-deep-copy (list-ref event-list index)))))
(ly:grob-set-property! note-head 'staff-position (- (* 2 index) 4))
; (ly:grob-set-property! note-head 'duration-log 2)
(ly:grob-set-property! note-head 'stencil ly:text-interface::print)
(ly:grob-set-property! note-head 'text (make-simple-markup (number->string usage-count)))
))
(set! index (1+ index))
) pitch-list)
(set! note-started #f)
))
)
)
)
))
Immerhin habe ich einen Workaround für mich gefunden:Ich mache das ganze in zwei Schritten.
Mit der ersten LY-Datei wird anstelle der Notenköpfe eine neue Lilypond-Datei mit einer kompletten Staff-Definition geschreiben,
diese muß dann nur per \include als weitere Notenzeile an die Ziel-Partitur angehängt werden. Dazu als Dateianlage mein »analysis-output-engraver.ly«.
Hat da jemand noch gute Vorschläge für mich?
Vielleicht ist aber auch der Aufwand, eine richtige »single pass«-Lösung zu erstellen viel zu aufwändig im Vergleich zu meiner aktuellen »two runs«-Lösung.
Arnold