Deutsches Lilypond Forum (Archiv)

Allgemein => Fragen zu Funktionen => Thema gestartet von: Hilflos-im-Code am Dienstag, 20. Dezember 2016, 08:53

Titel: Irgendetwas systematisch an Noten automatisch schreiben
Beitrag von: Hilflos-im-Code am Dienstag, 20. Dezember 2016, 08:53
Ich bilde mir ein, dass ich irgendwo in den Tiefen des Netzes irgendeine Erklärung gesehen habe, wie man automatisch Notennamen an die Noten schreiben kann. Ich finde diese Seite aber nicht mehr. Hat jemand einen Tipp.

Bevor jemand mit einem Skript antwortet. Die Idee ist Notenschreibaufgaben/Rätsel in Massenproduktion für Kinder.

z.B {\hideNotes a4 h2} Unter der ersten Note das Bild eines Affen erscheinen und darüber die berühmte Viertelpizza. Dann halt der unvermeidliche Hase mit einer halben Pizza.

Ginge so etwas?
Titel: Re: Irgendetwas systematisch an Noten automatisch schreiben
Beitrag von: Manuela am Dienstag, 20. Dezember 2016, 09:33
Ja, gibt es, sogar einen eigenen Context gibt es dafür.

Liest du hier  :D :

NoteNames (http://lilypond.org/doc/v2.19/Documentation/internals/notenames)
Titel: Re: Irgendetwas systematisch an Noten automatisch schreiben
Beitrag von: harm6 am Freitag, 23. Dezember 2016, 17:38
Hallo Hilflos :)

ich bin mal etwas tiefer in die Materie eingetaucht, da ich für dergleichen auch Verwendung habe.
Manuelas Hinweis auf den NoteNames-context ist zwar per se correct, jedoch sind die niederländischen Notennamen hard-coded (oder ich habe die Möglichkeit sie auf deutsch zu setzen nicht gefunden).

Also habe ich folgendes gemacht:
(1)
Die Funktion printGermanNoteNames verändert NoteName.stencil, um wirklich deutsche Namen auszugeben.
Basierend auf chord-name->my-german-markup-text-alteration, welches ich früher schon entwickelt hatte.
(2)
Die Funktion addTextScript fügt markups zu den Noten hinzu.
a) Über den Noten einen Kreisausschnitt basierend auf dem neu entwickelten markup-command arc
b) Unter den Noten ein epsfile-markup welches per note-name aus pitch-markup-list geholt wird. Diese Liste ist allerdings nicht vollständig, außer eps für Affe und Hase sind nur dummies drin. Auch habe ich auf die Schnelle keine guten und freien Bilder gefunden, so daß auch Affe.eps und Hase.eps einfachste, von mir per Hand gemachte Pseudobilder sind.
Aber da kann man ja später weitersuchen. Auch wird wohl jeder Nutzer diese Codes eine eigene Auswahl treffen wollen.
(3)
exercise ist die finale Ausgabefunktion. Neben der Musik gibts noch ein zusätzliches Argument, welches bestimmt, ob der Druck die Aufgabe an sich oder deren Auflösungen beinhalten soll.

Alles zusammen im Anhang, sowie ein png zur Ansicht.

Gruß,
  Harm
Titel: Re: Irgendetwas systematisch an Noten automatisch schreiben
Beitrag von: Hilflos-im-Code am Donnerstag, 5. Januar 2017, 08:38
Vielen Dank. Muss ich mir noch anschauen. Deine Antwort habe ich soeben entdeckt.
Titel: Re: Irgendetwas systematisch an Noten automatisch schreiben
Beitrag von: Manuela am Donnerstag, 5. Januar 2017, 09:04
Deine Antwort habe ich soeben entdeckt.

Wirst du nicht automatisch per Mail benachrichtigt? Oder schaut du so selten in dein Postfach?  ;)
Titel: Re: Irgendetwas systematisch an Noten automatisch schreiben
Beitrag von: Hilflos-im-Code am Donnerstag, 5. Januar 2017, 10:08
Deine Antwort habe ich soeben entdeckt.

Wirst du nicht automatisch per Mail benachrichtigt? Oder schaut du so selten in dein Postfach?  ;)
Ich schalte bei jedem Forum die Benachrichtigungsfunktion ab, damit ich meine wirklich wichtigen Mails nicht übersehe.
Titel: Re: Irgendetwas systematisch an Noten automatisch schreiben
Beitrag von: Hilflos-im-Code am Dienstag, 10. Januar 2017, 13:53
Ich wollte die ANgabe von den Notenwerten flexibler machen. Daraus wurde

\version "2.19.52"

#(define pitch-markup-list
;; An alist assigning markups to certain integers, which will be used later
;; as reference for the pitch-names
;; TODO add the missing eps-markups
`(
  (0 . ,(markup #:fontsize -8 #:halign 0 "[dummy für: c-eps]"))
  (1 . ,(markup #:fontsize -8 #:halign 0 "[dummy für: d-eps]"))
  (2 . ,(markup #:fontsize -8 #:halign 0 "[dummy für: e-eps]"))
  (3 . ,(markup #:fontsize -8 #:halign 0 "[dummy für: f-eps]"))
  (4 . ,(markup #:fontsize -8 #:halign 0 "[dummy für: g-eps]"))
  (5 . ,(markup #:halign 0 #:epsfile X 10 "Affe.eps"))
  (6 . ,(markup #:halign 0 #:epsfile X 10 "Hase.eps"))))


#(define notenwerteliste-list
;; Analog zur pitch-markup-list
`(
  (0 . ,(markup #:fontsize -8 #:halign 0 "Ganze"))
  (1 . ,(markup #:fontsize -8 #:halign 0 "punktierte Halbe"))
  (2 . ,(markup #:fontsize -8 #:halign 0 "Halbe"))
  (3 . ,(markup #:fontsize -8 #:halign 0 "punktierte Viertel"))
  (4 . ,(markup #:fontsize -8 #:halign 0 "Viertel"))
  (5 . ,(markup #:halign 0 #:halign 0 "Achtel"))
  ))


%Grenze

#(define ((chord-name->my-german-markup-text-alteration) pitch lowercase?)
"Print real german names."
;; Remark: currently ases is printed, may be discussable...
   (define (pitch-alteration-semitones pitch)
    (inexact->exact (round (* (ly:pitch-alteration pitch) 2))))

   (define (conditional-string-downcase str condition)
    (if condition
        (string-downcase str)
        str))

   (let* ((name (ly:pitch-notename pitch))
          (alt-semitones  (pitch-alteration-semitones pitch))
          ;; The following condition is weird. Though, we let them in to ease
          ;; comporability with the original.
          (n-a (cond ((member (cons name alt-semitones) `((6 . -1) (6 . -1)))
                      (cons 7 alt-semitones))
                     (else (cons name alt-semitones)))))
    (make-concat-markup
     (list
      (make-simple-markup
       (conditional-string-downcase
        (vector-ref #("C" "D" "E" "F" "G" "A" "H" "B") (car n-a))
       lowercase?))
      (let ((alteration (/ (cdr n-a) 2)))
        (cond
           ((and (= alteration FLAT) (= (car n-a) 7))
             (make-simple-markup ""))
           ((and (= alteration FLAT) (or (= (car n-a) 5) (= (car n-a) 2) ))
             (make-simple-markup "s"))
           ((= alteration FLAT) (make-simple-markup "es"))
           ((and (= alteration DOUBLE-FLAT) (or (= (car n-a) 5)(= (car n-a) 2)))
             (make-simple-markup "ses"))
           ((= alteration DOUBLE-FLAT)
             (make-simple-markup "eses"))
           ((= alteration SHARP)
             (make-simple-markup "is"))
           ((= alteration DOUBLE-SHARP)
             (make-simple-markup "isis"))
           (else empty-markup)))))))




%Grenze

#(define-markup-command (arc layout props angle)(number?)
  #:properties ((radius 1.5)
                (font-size 1)
                (double-radius-x-ext #t))
  "Print a circle-segment relying on @var{angle} in degrees.
The radius may be adjusted by overriding the @code{radius}-property.
The dimensions of the resulting stencil are set properly.
If @var{double-radius-x-ext} is set @code{#t}, (the default) the dimensions are
always from @code{(- radius)} to @code{radius} in Y-axis."
  (let* ((scaled-radius (* radius font-size))
         (top radius)
         (bottom
           (if double-radius-x-ext
               (- scaled-radius)
               (cond ((<= angle 90) 0)
                     ((> angle 180) (- scaled-radius))
                     (else
                       (* (cos (degrees->radians angle)) scaled-radius)))))
         (left
           (cond ((>= angle 270) (- scaled-radius))
                  ((> angle 180)
                   (* (sin (degrees->radians angle)) scaled-radius))
                  (else 0)))
         (right
           (cond ((> angle 90) scaled-radius)
                 (else
                   (* (sin (degrees->radians angle)) scaled-radius)))))
  (ly:make-stencil
   (list 'embedded-ps
         (format #f "
gsave currentpoint translate
0.1 setlinewidth
0 0 ~a 90 ~a arcn % Bogen 90 Grad
fill
grestore
"
scaled-radius
(- 90 angle)))
   (cons left right)
   (cons bottom top))))



%Grenze Hier werden die Kreise erzeugt

addTextScript =
#(define-music-function (music)(ly:music?)
"Adds markups to note-heads.
- a circle-segment above
    (relying on and representing the duration of a note-head
- an eps below
    (called with the note-name from @code{pitch-markup-list}"
  (music-map
    (lambda (mus)
      (if (music-is-of-type? mus 'note-event)
       
       (let* ((dur-frac (ly:moment-main (ly:music-length mus)))
               (pitch (ly:music-property mus 'pitch))
               (pitch-name (ly:pitch-notename pitch)))
          (ly:music-set-property! mus 'articulations
            (append
              (list
                (make-music
                  'TextScriptEvent
                  'direction DOWN
                  'text
                  (assoc-get pitch-name pitch-markup-list))
                (make-music
                  'TextScriptEvent
                  'direction UP
                  'text
                   (assoc-get dur-frac notenwerteliste-list))))
              (ly:music-property mus 'articulations)))
          mus)
        mus))
      music)
  music)

%Grenze



printGermanNoteNames =
#(define-music-function (solve?)(boolean?)
#{
\override NoteName.stencil =
#(lambda (grob)
  (let ((pitch (ly:prob-property (ly:grob-property grob 'cause) 'pitch)))
    (grob-interpret-markup
      grob
      (if solve?
          ((chord-name->my-german-markup-text-alteration) pitch #t)
          (markup #:with-dimensions-from "XXX" "...")))))
#})

exercise =
#(define-music-function (solve? music)(boolean? ly:music?)
#{
<<
  \new Staff
  \with { instrumentName = #(if solve? "Aufösung " "Aufgabe ") }
  {
    #(if solve?
         #{ \unHideNotes #}
         #{ \hideNotes #})
    \addTextScript $music
  }

  \new NoteNames
    \with {
      %\override VerticalAxisGroup.nonstaff-relatedstaff-spacing.padding = 4
      \printGermanNoteNames $solve?
    }
    $music
>>
#})

%grenze


\language "deutsch"

\paper { score-system-spacing.padding = 6 }

\layout {
  \override TextScript.parent-alignment-X = #CENTER
  \override TextScript.staff-padding = 4.5
  \override TextScript.font-size = 2
  \textLengthOn
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% EXAMPLE
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

mus = {
  \cadenzaOn
  c'4 d'2 e'4. f'8 g'16 a'2. h'1 c''8.
  \bar "|."
}

%% exercise:
\exercise ##f \mus

%% solved:
\exercise ##t \mus


Was natürlich nicht geht, weil ich einfach analog kopiert habe.

Geht das überhaupt mit

'TextScriptEvent
                  'direction UP
                  'text
                   (assoc-get dur-frac notenwerteliste-list)

Was gibt dur-frac aus? Und was müsste ich statt der Ziffern am Zeilenanfang in notenwerteliste-list eintragen?

 #(define notenwerteliste-list
;; Analog zur pitch-markup-list
`(
  (0 . ,(markup #:fontsize -8 #:halign 0 "Ganze"))
  (1 . ,(markup #:fontsize -8 #:halign 0 "punktierte Halbe"))
  (2 . ,(markup #:fontsize -8 #:halign 0 "Halbe"))
  (3 . ,(markup #:fontsize -8 #:halign 0 "punktierte Viertel"))
  (4 . ,(markup #:fontsize -8 #:halign 0 "Viertel"))
  (5 . ,(markup #:halign 0 #:halign 0 "Achtel"))
  ))

Titel: Re: Irgendetwas systematisch an Noten automatisch schreiben
Beitrag von: harm6 am Dienstag, 10. Januar 2017, 22:28
Zitat
Was gibt dur-frac aus? Und was müsste ich statt der Ziffern am Zeilenanfang in notenwerteliste-list eintragen?

Die (lokale) Definition:
  (dur-frac (ly:moment-main (ly:music-length mus)))

Um hier Aufschluss zu bekommen setze display-Funktionen in einem minimal ein:

mus = { c''2. }
\displayMusic \mus
#(write-me "\nly:music-length: " (ly:music-length mus))
#(write-me "ly:moment-main:  " (ly:moment-main (ly:music-length mus)))

=>
Zitat von: terminal
(make-music
  'SequentialMusic
  'elements
  (list (make-music
          'NoteEvent
          'duration
          (ly:make-duration 1 1)
          'pitch
          (ly:make-pitch 1 0))))


ly:music-length: #<Mom 3/4>
ly:moment-main:  3/4

Also:
ly:music-length gibt die Länge des musikalischen Arguments (hier die von (ly:make-duration 1 1)) als moment zurück. ly:moment-main extrahiert dann für gewöhnlich den numerischen Wert.

Aber aufgepasst, ly:music-length akzeptiert natürlich auch zusammengesetzte Ausdrücke, deshalb ist die Anwendung in der Funktion auf einzelne note-events begrenzt.

Zitat
Und was müsste ich statt der Ziffern am Zeilenanfang in notenwerteliste-list eintragen?
Den Bruch, der dann referenziert werden kann:

\version "2.19.52"

#(define pitch-markup-list
;; An alist assigning markups to certain integers, which will be used later
;; as reference for the pitch-names
;; TODO add the missing eps-markups
`(
  (0 . ,(markup #:fontsize -8 #:halign 0 "[dummy für: c-eps]"))
  (1 . ,(markup #:fontsize -8 #:halign 0 "[dummy für: d-eps]"))
  (2 . ,(markup #:fontsize -8 #:halign 0 "[dummy für: e-eps]"))
  (3 . ,(markup #:fontsize -8 #:halign 0 "[dummy für: f-eps]"))
  (4 . ,(markup #:fontsize -8 #:halign 0 "[dummy für: g-eps]"))
  (5 . ,(markup #:halign 0 #:epsfile X 10 "Affe.eps"))
  (6 . ,(markup #:halign 0 #:epsfile X 10 "Hase.eps"))))


#(define notenwerteliste-list
;; Analog zur pitch-markup-list
`(
  (1    . ,(markup #:fontsize -8 #:halign 0 "Ganze"))
  (3/4  . ,(markup #:fontsize -8 #:halign 0 "punktierte Halbe"))
  (1/2  . ,(markup #:fontsize -8 #:halign 0 "Halbe"))
  (3/8  . ,(markup #:fontsize -8 #:halign 0 "punktierte Viertel"))
  (1/4  . ,(markup #:fontsize -8 #:halign 0 "Viertel"))
  (1/8  . ,(markup #:fontsize -8 #:halign 0 "Achtel"))
  (1/16 . ,(markup #:fontsize -8 #:halign 0 "Sechzehntel"))
  (3/16 . ,(markup #:fontsize -8 #:halign 0 "punktierte Achtel"))
  ))


%Grenze

#(define ((chord-name->my-german-markup-text-alteration) pitch lowercase?)
"Print real german names."
;; Remark: currently ases is printed, may be discussable...
   (define (pitch-alteration-semitones pitch)
    (inexact->exact (round (* (ly:pitch-alteration pitch) 2))))

   (define (conditional-string-downcase str condition)
    (if condition
        (string-downcase str)
        str))

   (let* ((name (ly:pitch-notename pitch))
          (alt-semitones  (pitch-alteration-semitones pitch))
          ;; The following condition is weird. Though, we let them in to ease
          ;; comporability with the original.
          (n-a (cond ((member (cons name alt-semitones) `((6 . -1) (6 . -1)))
                      (cons 7 alt-semitones))
                     (else (cons name alt-semitones)))))
    (make-concat-markup
     (list
      (make-simple-markup
       (conditional-string-downcase
        (vector-ref #("C" "D" "E" "F" "G" "A" "H" "B") (car n-a))
       lowercase?))
      (let ((alteration (/ (cdr n-a) 2)))
        (cond
           ((and (= alteration FLAT) (= (car n-a) 7))
             (make-simple-markup ""))
           ((and (= alteration FLAT) (or (= (car n-a) 5) (= (car n-a) 2) ))
             (make-simple-markup "s"))
           ((= alteration FLAT) (make-simple-markup "es"))
           ((and (= alteration DOUBLE-FLAT) (or (= (car n-a) 5)(= (car n-a) 2)))
             (make-simple-markup "ses"))
           ((= alteration DOUBLE-FLAT)
             (make-simple-markup "eses"))
           ((= alteration SHARP)
             (make-simple-markup "is"))
           ((= alteration DOUBLE-SHARP)
             (make-simple-markup "isis"))
           (else empty-markup)))))))




%Grenze

#(define-markup-command (arc layout props angle)(number?)
  #:properties ((radius 1.5)
                (font-size 1)
                (double-radius-x-ext #t))
  "Print a circle-segment relying on @var{angle} in degrees.
The radius may be adjusted by overriding the @code{radius}-property.
The dimensions of the resulting stencil are set properly.
If @var{double-radius-x-ext} is set @code{#t}, (the default) the dimensions are
always from @code{(- radius)} to @code{radius} in Y-axis."
  (let* ((scaled-radius (* radius font-size))
         (top radius)
         (bottom
           (if double-radius-x-ext
               (- scaled-radius)
               (cond ((<= angle 90) 0)
                     ((> angle 180) (- scaled-radius))
                     (else
                       (* (cos (degrees->radians angle)) scaled-radius)))))
         (left
           (cond ((>= angle 270) (- scaled-radius))
                  ((> angle 180)
                   (* (sin (degrees->radians angle)) scaled-radius))
                  (else 0)))
         (right
           (cond ((> angle 90) scaled-radius)
                 (else
                   (* (sin (degrees->radians angle)) scaled-radius)))))
  (ly:make-stencil
   (list 'embedded-ps
         (format #f "
gsave currentpoint translate
0.1 setlinewidth
0 0 ~a 90 ~a arcn % Bogen 90 Grad
fill
grestore
"
scaled-radius
(- 90 angle)))
   (cons left right)
   (cons bottom top))))



%Grenze Hier werden die Kreise erzeugt

addTextScript =
#(define-music-function (music)(ly:music?)
"Adds markups to note-heads.
- a circle-segment above
    (relying on and representing the duration of a note-head
- an eps below
    (called with the note-name from @code{pitch-markup-list}"
  (music-map
    (lambda (mus)
      (if (music-is-of-type? mus 'note-event)
       
       (let* ((dur-frac (ly:moment-main (ly:music-length mus)))
              (pitch (ly:music-property mus 'pitch))
              (pitch-name (ly:pitch-notename pitch)))
          (ly:music-set-property! mus 'articulations
            (append
              (list
                ;; print eps
                (make-music
                  'TextScriptEvent
                  'direction DOWN
                  'text
                  (assoc-get pitch-name pitch-markup-list))
                ;; print text
                (make-music
                  'TextScriptEvent
                  'direction UP
                  'text
                   (assoc-get dur-frac notenwerteliste-list))
                ;; print the circles
                (make-music
                  'TextScriptEvent
                  'direction UP
                  'text
                  #{
                    \markup
                      \with-color #'(0.6 0.6 0.6)
                      \arc #(* 360.0 dur-frac)
                  #})
                   )
              (ly:music-property mus 'articulations)))
          mus)
        mus))
      music)
  music)

%Grenze



printGermanNoteNames =
#(define-music-function (solve?)(boolean?)
#{
\override NoteName.stencil =
#(lambda (grob)
  (let ((pitch (ly:prob-property (ly:grob-property grob 'cause) 'pitch)))
    (grob-interpret-markup
      grob
      (if solve?
          ((chord-name->my-german-markup-text-alteration) pitch #t)
          (markup #:with-dimensions-from "XXX" "...")))))
#})

exercise =
#(define-music-function (solve? music)(boolean? ly:music?)
#{
<<
  \new Staff
  \with { instrumentName = #(if solve? "Aufösung " "Aufgabe ") }
  {
    #(if solve?
         #{ \unHideNotes #}
         #{ \hideNotes #})
    \addTextScript $music
  }

  \new NoteNames
    \with {
      %\override VerticalAxisGroup.nonstaff-relatedstaff-spacing.padding = 4
      \printGermanNoteNames $solve?
    }
    $music
>>
#})

%grenze


\language "deutsch"

\paper { score-system-spacing.padding = 6 }

\layout {
  \override TextScript.parent-alignment-X = #CENTER
  \override TextScript.staff-padding = 2.5
  \override TextScript.font-size = 2
  \textLengthOn
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% EXAMPLE
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

mus = {
  \cadenzaOn
  c'4 d'2 e'4. f'8 g'16 a'2. h'1 c''8.
  \bar "|."
}

%% exercise:
\exercise ##f \mus

%% solved:
\exercise ##t \mus

HTH,
  Harm

EDIT Kopierfehler korrigiert



Titel: Re: Irgendetwas systematisch an Noten automatisch schreiben
Beitrag von: Hilflos-im-Code am Mittwoch, 11. Januar 2017, 10:18
Vielen Dank.

(ly:make-pitch 0 5 1/2)
hat mich auf die Idee gebracht, das Problem zu lösen, dass bei deinem Code Oktaven und Vorzeichen unterschlagen werden. Bei der Referenzierung

#(define pitch-markup-list
;; An alist assigning markups to certain integers, which will be used later
;; as reference for the pitch-names
;; TODO add the missing eps-markups
`(
    (0 5 1/2 . ,(markup #:halign 0 "Das falsche Ais eingestrichen"))
  (0 6 -1/2 . ,(markup #:halign 0 "Ein gestrichener Bube"))
  ))


bekomme ich noch keine Fehlermeldung.

Aber was ich wie bei  (assoc-get pitch-name pitch-markup-list) für pitch-name einsetzen muss, habe ich noch nicht herausgefunden. Letztendlich würde dann ein Script einstehen, was für jedes Instrument einsetzbar wäre, ohne dass man die Gebräuche im Anfängerunterricht kennen muss.
Titel: Re: Irgendetwas systematisch an Noten automatisch schreiben
Beitrag von: Hilflos-im-Code am Montag, 16. Januar 2017, 12:43
Ich habe jetzt zwei Stunden rumprobiert, komme aber auf keinen grünen Zweig. Bei meiner Suche, die Syntax zu verstehen bin ich unter https://archiv.lilypondforum.de/index.php?topic=1712.0
auf
\version "2.18.0"

%% nicer output
#(use-modules (ice-9 pretty-print))

%% Define the language, if you want, needs to be a string:
which-language = "deutsch"

#(define which-language
;; tests whether 'which-language' is defined already and if 'which-language' is
;; part of 'language-pitch-names', see define-note-names.scm
;; if not, use 'default-language' (netherlands), see declarations-init.ly
 (if (defined? 'which-language)
     (let ((possible-languages (map car language-pitch-names)))
       ;(write possible-languages)
       (if (member (string->symbol which-language) possible-languages)
           which-language
           (ly:error "specified language, \"~a\", does not exist"
                     which-language)))
     default-language))
 
\language \which-language

#(define used-notenames
;; returns a subset of 'language-pitch-names', specified by which-language.
;; key and value are exchanged
;; i.e. the alist is from type '((pitch . name) ... )
  (map
    (lambda (e) (reverse-interval e))
    (assoc-get
      (string->symbol which-language)
          language-pitch-names)))

%#(pretty-print used-notenames)
 
display-note-names =
#(define-music-function (parser loction music)(ly:music?)
"
 Returns the unchanged music, writing the absolute notenames in terminal.
"
    (music-map
       (lambda (mus)
         (if (music-is-of-type? mus 'note-event)
             (begin
               (let* ((pitch (ly:music-property mus 'pitch))
                      (pitch-octaves (ly:pitch-octave pitch))
                      (pitch-notename (ly:pitch-notename pitch))
                      (pitch-alteration (ly:pitch-alteration pitch))
                      ;; create a pitch with alteration, name and
                      ;; octave set to -1
                      ;; this ensures the possibility to look it up in
                      ;; 'used-notenames'
                      (p (ly:make-pitch -1 pitch-notename pitch-alteration))
                      (pitch-name-strg
                         (symbol->string (assoc-get p used-notenames)))
                      ;; recreate the octave-notation
                      (octave-sign
                        (cond ((< pitch-octaves 0)
                               (string-concatenate
                                 (make-list (1- (abs pitch-octaves)) ",")))
                              ((= pitch-octaves 0) "'")
                              ((> pitch-octaves 0)
                               (string-concatenate
                                 (make-list (1+ (abs pitch-octaves)) "'")))))
                      (absolute-pitch-name
                        (string-append pitch-name-strg octave-sign)))
               (newline)
               (write pitch)
               (format #t "\t~a" absolute-pitch-name)
               mus))
             mus))
       music)
 
  music)
 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% EXAMPLE
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\display-note-names
\relative c' {
c, cis d dis e f fis g gis a ais h c
cis d dis e f fis g gis a ais h c
cis d dis e f fis g gis a ais h c
h b a as g ges f e es d des c
\transpose c cis <c e g>
}
gestoßen und habe mir daran meine geistige Nase blutig geschlagen, wie ich pitch-name durch display-note-names in (assoc-get pitch-name pitch-markup-list) ersetze.

Titel: Re: Irgendetwas systematisch an Noten automatisch schreiben
Beitrag von: harm6 am Mittwoch, 18. Januar 2017, 00:29
Zitat
das Problem zu lösen, dass bei deinem Code Oktaven und Vorzeichen unterschlagen werden
Das war Absicht, da der Code auf den Anfängerunterricht gemünzt war und daher Alterationen außer acht läßt.
Wenn Du sie haben willst muß man anders vorgehen.
Ich habe meinen Code aus
https://archiv.lilypondforum.de/index.php?topic=1712.0 (https://archiv.lilypondforum.de/index.php?topic=1712.0)
als Steinbruch genutzt:

\version "2.19.52"

#(define (used-notenames lang)
;; returns a subset of 'language-pitch-names', specified by `lang'.
;; key and value are exchanged
;; i.e. the alist is from type '((pitch . name) ... )
  (map
    (lambda (e) (reverse-interval e))
    (assoc-get
      (string->symbol lang)
          language-pitch-names)))

#(define german-notenames (used-notenames "deutsch"))

#(define (pitch->notename pitch)
  (let* ((pitch-octaves (ly:pitch-octave pitch))
         (pitch-notename (ly:pitch-notename pitch))
         (pitch-alteration (ly:pitch-alteration pitch))
         ;; create a pitch with alteration, name and
         ;; octave set to -1
         ;; this ensures the possibility to look it up in
         ;; 'used-notenames'
         (p (ly:make-pitch -1 pitch-notename pitch-alteration))
         (pitch-name-strg
            (symbol->string (assoc-get p german-notenames)))
         ;; recreate the octave-notation
         (octave-sign
           (cond ((and (>= pitch-octaves -2) (<= pitch-octaves -1)) "")
                 ((<= pitch-octaves -1)
                  (string-concatenate
                    (make-list (- (abs pitch-octaves) 2) ",")))
                 ((= pitch-octaves 0) "'")
                 ((> pitch-octaves 0)
                  (string-concatenate
                    (make-list (1+ (abs pitch-octaves)) "'")))))
         (absolute-pitch-name
           (string-append
             (if (<= pitch-octaves -2)
                 (string-upcase pitch-name-strg)
                 pitch-name-strg)
             octave-sign)))
  (format #f "~a" absolute-pitch-name)))
 
#(define pitch-markup-list
;; An alist assigning markups to certain integers, which will be used later
;; as reference for the pitch-names
;; TODO add the missing eps-markups
`(
  (0 . ,(markup #:fontsize -8 #:halign 0 "[dummy für: c-eps]"))
  (1 . ,(markup #:fontsize -8 #:halign 0 "[dummy für: d-eps]"))
  (2 . ,(markup #:fontsize -8 #:halign 0 "[dummy für: e-eps]"))
  (3 . ,(markup #:fontsize -8 #:halign 0 "[dummy für: f-eps]"))
  (4 . ,(markup #:fontsize -8 #:halign 0 "[dummy für: g-eps]"))
  (5 . ,(markup #:halign 0 #:epsfile X 10 "Affe.eps"))
  (6 . ,(markup #:halign 0 #:epsfile X 10 "Hase.eps"))))


#(define notenwerteliste-list
;; Analog zur pitch-markup-list
`(
  (1    . ,(markup #:fontsize -8 #:halign 0 "Ganze"))
  (3/4  . ,(markup #:fontsize -8 #:halign 0 "punktierte Halbe"))
  (1/2  . ,(markup #:fontsize -8 #:halign 0 "Halbe"))
  (3/8  . ,(markup #:fontsize -8 #:halign 0 "punktierte Viertel"))
  (1/4  . ,(markup #:fontsize -8 #:halign 0 "Viertel"))
  (1/8  . ,(markup #:fontsize -8 #:halign 0 "Achtel"))
  (1/16 . ,(markup #:fontsize -8 #:halign 0 "Sechzehntel"))
  (3/16 . ,(markup #:fontsize -8 #:halign 0 "punktierte Achtel"))
  ))

#(define-markup-command (arc layout props angle)(number?)
  #:properties ((radius 1.5)
                (font-size 1)
                (double-radius-x-ext #t))
  "Print a circle-segment relying on @var{angle} in degrees.
The radius may be adjusted by overriding the @code{radius}-property.
The dimensions of the resulting stencil are set properly.
If @var{double-radius-x-ext} is set @code{#t}, (the default) the dimensions are
always from @code{(- radius)} to @code{radius} in Y-axis."
  (let* ((scaled-radius (* radius font-size))
         (top radius)
         (bottom
           (if double-radius-x-ext
               (- scaled-radius)
               (cond ((<= angle 90) 0)
                     ((> angle 180) (- scaled-radius))
                     (else
                       (* (cos (degrees->radians angle)) scaled-radius)))))
         (left
           (cond ((>= angle 270) (- scaled-radius))
                  ((> angle 180)
                   (* (sin (degrees->radians angle)) scaled-radius))
                  (else 0)))
         (right
           (cond ((> angle 90) scaled-radius)
                 (else
                   (* (sin (degrees->radians angle)) scaled-radius)))))
  (ly:make-stencil
   (list 'embedded-ps
         (format #f "
gsave currentpoint translate
0.1 setlinewidth
0 0 ~a 90 ~a arcn % Bogen 90 Grad
fill
grestore
"
scaled-radius
(- 90 angle)))
   (cons left right)
   (cons bottom top))))

addTextScript =
#(define-music-function (music)(ly:music?)
"Adds markups to note-heads.
- a circle-segment above
    (relying on and representing the duration of a note-head
- an eps below
    (called with the note-name from @code{pitch-markup-list}"
  (music-map
    (lambda (mus)
      (if (music-is-of-type? mus 'note-event)
       
       (let* ((dur-frac (ly:moment-main (ly:music-length mus)))
              (pitch (ly:music-property mus 'pitch))
              (pitch-name (ly:pitch-notename pitch)))
          (ly:music-set-property! mus 'articulations
            (append
              (list
                ;; print eps
                (make-music
                  'TextScriptEvent
                  'direction DOWN
                  'text
                  (assoc-get pitch-name pitch-markup-list))
                ;; print text
                (make-music
                  'TextScriptEvent
                  'direction UP
                  'text
                   (assoc-get dur-frac notenwerteliste-list))
                ;; print the circles
                (make-music
                  'TextScriptEvent
                  'direction UP
                  'text
                  #{
                    \markup
                      \with-color #'(0.6 0.6 0.6)
                      \arc #(* 360.0 dur-frac)
                  #})
                   )
              (ly:music-property mus 'articulations)))
          mus)
        mus))
      music)
  music)
 
printGermanNoteNames =
#(define-music-function (solve?)(boolean?)
#{
\override NoteName.stencil =
#(lambda (grob)
  (let ((pitch (ly:prob-property (ly:grob-property grob 'cause) 'pitch)))
    (grob-interpret-markup
      grob
      (if solve?
          (pitch->notename pitch)
          (markup #:with-dimensions-from "XXX" "...")))))
#})

exercise =
#(define-music-function (solve? music)(boolean? ly:music?)
#{
<<
  \new Staff
  \with {
    instrumentName = #(if solve? "Aufösung " "Aufgabe ")
    shortInstrumentName = #(if solve? "Aufösung " "Aufgabe ")
  }
  {
    #(if solve?
         #{ \unHideNotes #}
         #{ \hideNotes #})
    \addTextScript $music
  }

  \new NoteNames
    \with {
      %\override VerticalAxisGroup.nonstaff-relatedstaff-spacing.padding = 4
      \printGermanNoteNames $solve?
    }
    $music
>>
#})

\paper {
  system-system-spacing.padding = 16
  indent = 12
  short-indent = 12
}

\layout {
  \override TextScript.parent-alignment-X = #CENTER
  \override TextScript.staff-padding = 2.5
  \override TextScript.font-size = 2
  \override Staff.VerticalAxisGroup.staff-staff-spacing.padding = 5
  \textLengthOn
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% EXAMPLE
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

mus = {
  \cadenzaOn
  c'4 d'2 e'4. f'8 g'16 a'2. b'1 c''8.
  \bar "|"
}

<<
%% exercise:
\exercise ##f { \mus \break \transpose c cis \mus }

%% solved:
\exercise ##t { \mus \break \transpose c cis \mus }
>>

Ob Du mit meinen Formatierungen einverstanden bist, ist natürlich eine andere Frage :D

Gruß,
  Harm
Titel: Re: Irgendetwas systematisch an Noten automatisch schreiben
Beitrag von: Hilflos-im-Code am Mittwoch, 18. Januar 2017, 10:09
Danke. Das mir wichtige sind weniger die Alterationen, sondern die Oktaven, weil g' ist eine Gans und g'' eine Giraffe. Das scheine ich hinzubekommen


Gesamter Code
\version "2.19.40"

#(define (used-notenames lang)
;; returns a subset of 'language-pitch-names', specified by `lang'.
;; key and value are exchanged
;; i.e. the alist is from type '((pitch . name) ... )
  (map
    (lambda (e) (reverse-interval e))
    (assoc-get
      (string->symbol lang)
          language-pitch-names)))

#(define german-notenames (used-notenames "deutsch"))

#(define (pitch->notename pitch)
  (let* ((pitch-octaves (ly:pitch-octave pitch))
         (pitch-notename (ly:pitch-notename pitch))
         (pitch-alteration (ly:pitch-alteration pitch))
         ;; create a pitch with alteration, name and
         ;; octave set to -1
         ;; this ensures the possibility to look it up in
         ;; 'used-notenames'
         (p (ly:make-pitch -1 pitch-notename pitch-alteration))
         (pitch-name-strg
            (symbol->string (assoc-get p german-notenames)))
         ;; recreate the octave-notation
         (octave-sign
           (cond ((and (>= pitch-octaves -2) (<= pitch-octaves -1)) "")
                 ((<= pitch-octaves -1)
                  (string-concatenate
                    (make-list (- (abs pitch-octaves) 2) ",")))
                 ((= pitch-octaves 0) "'")
                 ((> pitch-octaves 0)
                  (string-concatenate
                    (make-list (1+ (abs pitch-octaves)) "'")))))
         (absolute-pitch-name
           (string-append
             (if (<= pitch-octaves -2)
                 (string-upcase pitch-name-strg)
                 pitch-name-strg)
             octave-sign)))
  (format #f "~a" absolute-pitch-name)))
 
#(define pitch-markup-list
;; An alist assigning markups to certain integers, which will be used later
;; as reference for the pitch-names
;; TODO add the missing eps-markups
`(
  (10 1  . ,(markup #:fontsize -8 #:halign 0 "[dummy für: c-eps]"))
  (1 . ,(markup #:fontsize -8 #:halign 0 "[dummy für: d-eps]"))
  (02 . ,(markup #:fontsize -8 #:halign 0 "[dummy für: e-eps]"))
  (3 . ,(markup #:fontsize -8 #:halign 0 "[dummy für: f-eps]"))
  (4 . ,(markup #:fontsize -8 #:halign 0 "[dummy für: g-eps]"))
  (5 . ,(markup #:halign 0 #:epsfile X 10 "Affe.eps"))
  (6 . ,(markup #:halign 0 #:epsfile X 10 "Hase.eps"))))


#(define notenwerteliste-list
;; Analog zur pitch-markup-list
`(
  (1    . ,(markup #:fontsize -8 #:halign 0 "Ganze"))
  (3/4  . ,(markup #:fontsize -8 #:halign 0 "punktierte Halbe"))
  (1/2  . ,(markup #:fontsize -8 #:halign 0 "Halbe"))
  (3/8  . ,(markup #:fontsize -8 #:halign 0 "punktierte Viertel"))
  (1/4  . ,(markup #:fontsize -8 #:halign 0 "Viertel"))
  (1/8  . ,(markup #:fontsize -8 #:halign 0 "Achtel"))
  (1/16 . ,(markup #:fontsize -8 #:halign 0 "Sechzehntel"))
  (3/16 . ,(markup #:fontsize -8 #:halign 0 "punktierte Achtel"))
  ))

#(define-markup-command (arc layout props angle)(number?)
  #:properties ((radius 1.5)
                (font-size 1)
                (double-radius-x-ext #t))
  "Print a circle-segment relying on @var{angle} in degrees.
The radius may be adjusted by overriding the @code{radius}-property.
The dimensions of the resulting stencil are set properly.
If @var{double-radius-x-ext} is set @code{#t}, (the default) the dimensions are
always from @code{(- radius)} to @code{radius} in Y-axis."
  (let* ((scaled-radius (* radius font-size))
         (top radius)
         (bottom
           (if double-radius-x-ext
               (- scaled-radius)
               (cond ((<= angle 90) 0)
                     ((> angle 180) (- scaled-radius))
                     (else
                       (* (cos (degrees->radians angle)) scaled-radius)))))
         (left
           (cond ((>= angle 270) (- scaled-radius))
                  ((> angle 180)
                   (* (sin (degrees->radians angle)) scaled-radius))
                  (else 0)))
         (right
           (cond ((> angle 90) scaled-radius)
                 (else
                   (* (sin (degrees->radians angle)) scaled-radius)))))
  (ly:make-stencil
   (list 'embedded-ps
         (format #f "
gsave currentpoint translate
0.1 setlinewidth
0 0 ~a 90 ~a arcn % Bogen 90 Grad
fill
grestore
"
scaled-radius
(- 90 angle)))
   (cons left right)
   (cons bottom top))))

addTextScript =
#(define-music-function (music)(ly:music?)
"Adds markups to note-heads.
- a circle-segment above
    (relying on and representing the duration of a note-head
- an eps below
    (called with the note-name from @code{pitch-markup-list}"
  (music-map
    (lambda (mus)
      (if (music-is-of-type? mus 'note-event)
       
       (let* ((dur-frac (ly:moment-main (ly:music-length mus)))
              (pitch (ly:music-property mus 'pitch))
              (pitch-name (ly:pitch-notename pitch))
             
              (pitch-alteration (ly:pitch-alteration pitch))
             
              (pitch-octaves (ly:pitch-octave pitch))
              )           
         
          (ly:music-set-property! mus 'articulations
            (append
              (list
                ;; print eps
                (make-music
                  'TextScriptEvent
                  'direction DOWN
                  'text
                  (assoc-get (+ pitch-octaves  pitch-name pitch-alteration )   pitch-markup-list))
                ;; print text
                (make-music
                  'TextScriptEvent
                  'direction UP
                  'text
                   (assoc-get dur-frac notenwerteliste-list))
                ;; print the circles
                (make-music
                  'TextScriptEvent
                  'direction UP
                  'text
                  #{
                    \markup
                      \with-color #'(0.6 0.6 0.6)
                      \arc #(* 360.0 dur-frac)
                  #})
                   )
              (ly:music-property mus 'articulations)))
          mus)
        mus))
      music)
  music)
 
printGermanNoteNames =
#(define-music-function (solve?)(boolean?)
#{
\override NoteName.stencil =
#(lambda (grob)
  (let ((pitch (ly:prob-property (ly:grob-property grob 'cause) 'pitch)))
    (grob-interpret-markup
      grob
      (if solve?
          (pitch->notename pitch)
          (markup #:with-dimensions-from "XXX" "...")))))
#})

exercise =
#(define-music-function (solve? music)(boolean? ly:music?)
#{
<<
  \new Staff
  \with {
    instrumentName = #(if solve? "Aufösung " "Aufgabe ")
    shortInstrumentName = #(if solve? "Aufösung " "Aufgabe ")
  }
  {
    #(if solve?
         #{ \unHideNotes #}
         #{ \hideNotes #})
    \addTextScript $music
  }

  \new NoteNames
    \with {
      %\override VerticalAxisGroup.nonstaff-relatedstaff-spacing.padding = 4
      \printGermanNoteNames $solve?
    }
    $music
>>
#})

\paper {
  system-system-spacing.padding = 16
  indent = 12
  short-indent = 12
}

\layout {
  \override TextScript.parent-alignment-X = #CENTER
  \override TextScript.staff-padding = 2.5
  \override TextScript.font-size = 2
  \override Staff.VerticalAxisGroup.staff-staff-spacing.padding = 5
  \textLengthOn
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% EXAMPLE
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

mus = {
  \cadenzaOn
   c' cis' d' c'' cis'' d''
  \bar "|"
}

<<
%% exercise:
\exercise ##f { \mus  }


>>


aus

(let* ((dur-frac (ly:moment-main (ly:music-length mus)))
              (pitch (ly:music-property mus 'pitch))
              (pitch-name (ly:pitch-notename pitch)))
                             
         

wurde

(let* ((dur-frac (ly:moment-main (ly:music-length mus)))
              (pitch (ly:music-property mus 'pitch))
              (pitch-name (ly:pitch-notename pitch))
             
              (pitch-alteration (ly:pitch-alteration pitch))
             
              (pitch-octaves (ly:pitch-octave pitch))
              )           
         

und aus
  (assoc-get   pitch-name   pitch-markup-list))

wurde

  (assoc-get (+ pitch-octaves  pitch-name pitch-alteration )   pitch-markup-list))

Aber ich schaffe es nicht Oktavlage noch Alterationen zu berücksichtigen.

So sieht die markupliste aus

#(define pitch-markup-list
;; An alist assigning markups to certain integers, which will be used later
;; as reference for the pitch-names
;; TODO add the missing eps-markups
`(
  (00  . ,(markup #:fontsize -8 #:halign 0 "[dummy für: c'-eps]"))
  (001/2 . ,(markup #:fontsize -8 #:halign 0 "[dummy für: cis'-eps]"))
    (01 . ,(markup #:fontsize -8 #:halign 0 "[dummy für: d'-eps]"))
   (01  . ,(markup #:fontsize -8 #:halign 0 "[dummy für: c''-eps]"))
  (101/2 . ,(markup #:fontsize -8 #:halign 0 "[dummy für: cis''-eps]"))
  (11 . ,(markup #:fontsize -8 #:halign 0 "[dummy für: d''-eps]"))
 
  ))




Titel: Re: Irgendetwas systematisch an Noten automatisch schreiben
Beitrag von: harm6 am Mittwoch, 18. Januar 2017, 11:12
Ich hatte mich nur darum gekümmert, daß die Noten den richtigen Namen bekommen jetzt auch mit Berücksichtigung der Oktavlage sowie möglichen Alterationen.

Zitat
Das mir wichtige sind weniger die Alterationen, sondern die Oktaven, weil g' ist eine Gans und g'' eine Giraffe.
Wenn ich das richtig verstehe, so geht es in diesem Teilaspekt darum je nach Oktave unerschiedliche eps-Bilder demselben Tonnamen zuzuordnen.

Über wie viele Möglichkeiten reden wir?
Für g,, g, g g' g' g'' g''' wären es ja schon 7, multipliziert mit den sieben Stammtönen 49, multipliziert mit "normal", hoch- und tiefalteriert komme ich schon auf 147, mit doppelten Alterationen auf 245.
Das ist in jedem Fall 'ne ganze Menge...

Ich kann frühestens heute abend hier weitermachen.
Aber es wäre schön Du würdest genau spezifizieren, für welche Oktaven Du etwas haben willst, z.B.:
c, - eps1a
c - eps1b
c'- eps1c
(andere Oktaven nicht)

Gruß,
  Harm
Titel: Re: Irgendetwas systematisch an Noten automatisch schreiben
Beitrag von: Hilflos-im-Code am Mittwoch, 18. Januar 2017, 16:37
Der Anhang tut, was er soll. Aber ob das sauber und richtig ist keine Ahnung.

Geht über neun Oktaven.