Kombination von Language mit EasyHeads und NoteNames

Begonnen von helmut, Donnerstag, 25. Mai 2017, 18:28

« vorheriges - nächstes »

helmut

Hallo,

In den Dokumentationen habe ich folgendes gefunden:
Zitate aus ,,notation de.pdf":
Easy-Notation-Notenköpfe
Die ,,einfachen Notenköpfe" haben die Bezeichnung der Note im Kopf gedruckt. Das wird eingesetzt, um die Notation beizubringen. Damit die Buchstaben noch lesbar sind, müssen sie sehr groß gesetzt werden. ...

Notenbezeichnungen in anderen Sprachen
Es gibt vordefinierte Bezeichnungen für die Notenbezeichnungen in anderen Sprachen als Englisch. Die Sprache für die Notenbezeichnungen wird normalerweise zu Beginn einer Datei ausgewählt: ...

Zitat aus ,,snippets":
Printing note names with and without an octave marker
The NoteNames context can be used to print the text value of notes. The printOctaveNames
property turns on or off the representation of the octave of the note.

Nur mit der Anwendung habe ich Probleme:

An dieser Stelle möchte ich gerne noch aus Harms Antwort nur 5 zum Thema "Fingersatz im Context .." zitieren (vielleicht hilft das ja  ;) ).
Zitat... außer "LilyPond kann (fast) alles" :D


Egal, ob ich als Sprache ,,deutsch" oder ,,italiano" wähle, die Noten werden immer in ,,ausländisch" angezeigt.
Ich möchte aber als Output die Bezeichnung haben, die ich als Input verwendet habe.
Weiß einer wie das geht?


\version "2.18.2"

#(set-global-staff-size 26)

\language "deutsch"

musik = \relative c' { c^"deutsch ?" d e f g a h c }

\score {
  \new Staff {
    <<
    \musik
      \context NoteNames
          { \set printOctaveNames = ##t \musik }
    \easyHeadsOn
    >>
  }
  \layout {}
}
%
\language "italiano"

musica = \relative do' { mi_"italiano ?" fa sol la si do re mi }
 
\score {
  \new Staff {
    <<
    \musica
      \context NoteNames
          { \set printOctaveNames = ##t \musica }
    \easyHeadsOn
    >>
  }
  \layout {}
}


Gruß
Helmut

harm6

ZitatEgal, ob ich als Sprache ,,deutsch" oder ,,italiano" wähle, die Noten werden immer in ,,ausländisch" angezeigt.
Ich möchte aber als Output die Bezeichnung haben, die ich als Input verwendet habe.

Solange issue 1367
https://sourceforge.net/p/testlilyissues/issues/1367/
ungelöst ist, wird es schwierig die richtigen NoteNames hinzukriegen.
Aber hier einige Anregungen für deutsche Notennamen:
https://archiv.lilypondforum.de/index.php/topic,2443.msg13806.html#msg13806
https://archiv.lilypondforum.de/index.php/topic,2443.msg13988.html#msg13988

easyHeadsOn kümmert sich nicht um Alterationen, falls Du diese Einschränkung akzeptierst so geht:


\language "deutsch"

musik = \relative c' { c^"deutsch ?" d e f g a h c }

{
    \override NoteHead.note-names = ##("c" "d" "e" "f" "g" "a" "h")
    \easyHeadsOn
    \musik
}


Gruß,
  Harm

Manuela

Eine dumme Frage. Könnte man nicht die in dieser Funktion enthaltene Umwandlungsfunktion

#(define ((chord-name->german-markup-text-alteration B-instead-of-Bb) pitch lowercase?)

   (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))
          (n-a (if (member (cons name alt-semitones) `((6 . -1) (6 . -1)))
                   (cons 7 (+ (if B-instead-of-Bb 1 1) alt-semitones))
                   (cons name alt-semitones))))
     (make-line-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 (equal? lowercase? #f) (= 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)))))))


in diese Funktion einbauen?

#(define (note-head::brew-ez-stencil grob)
   (let* ((log (ly:grob-property grob 'duration-log))
          (pitch (ly:event-property (event-cause grob) 'pitch))
          (pitch-index (ly:pitch-notename pitch))
          (note-names (ly:grob-property grob 'note-names))
          (pitch-string (if (and (vector? note-names)
                                 (> (vector-length note-names) pitch-index))
                            (vector-ref note-names pitch-index)
                            (string
                             (integer->char
                              (+ (modulo (+ pitch-index 2) 7)
                                (char->integer #\A))))))
          (staff-space (ly:staff-symbol-staff-space grob))
          (line-thickness (ly:staff-symbol-line-thickness grob))
          (stem (ly:grob-object grob 'stem))
          (stem-thickness (* (if (ly:grob? stem)
                                 (ly:grob-property stem 'thickness)
                                 1.3)
                            line-thickness))
          (radius (/ (+ staff-space line-thickness) 2))
          (letter (make-center-align-markup (make-vcenter-markup pitch-string)))
          (filled-circle (make-draw-circle-markup radius 0 #t)))

     (ly:stencil-translate-axis
      (grob-interpret-markup
       grob
       (if (>= log 2)
           (make-combine-markup
            filled-circle
            (make-with-color-markup white letter))
           (make-combine-markup
            (make-combine-markup
             filled-circle
             (make-with-color-markup white (make-draw-circle-markup
                                            (- radius stem-thickness) 0 #t)))
            letter)))
      radius X)))


Wahrscheinlich geht es nicht so einfach (für jemand, dessen Scheme nicht eingerostet ist ;-) ), sonst wäre schon längst jemand drauf gekommen.
Danke für eure Hilfe
viele Grüße
-- Manuela

harm6

Zitat
Könnte man nicht die in dieser Funktion enthaltene Umwandlungsfunktion
[...]
in diese Funktion einbauen?
[...]

Geht bestimmt, ohne das jetzt versucht zu haben.

Jedoch gibts das Problem das alterierte NotenNamen länger sind. Wenn man also fisis in einen Notenkopf schreibt, muß man die Abmessungen/Schriftgröße des "fisis"-markup so wählen, daß es rein passt.
So habe ich es vor einiger Zeit bei Griffdiagrammen gemacht, das feature ist jetzt im source-code.
Aber natürlich wird die Schrift dann so klein, daß sie kaum lesbar ist, oder man muß die generelle Größe riesig setzten.
Such nach
'fretdiagram-markup-in-dots.ly'
in
http://lilypond.org/doc/v2.19/input/regression/collated-files.html


Bei einem feature welches eigentlich fürs Notenlesen von Anfängern gedacht ist hat noch niemand die Notwendigkeit gesehen es zu implementieren.

Gruß,
  Harm

helmut

Hallo Harm, hallo Manuela,

ich danke für Eure Beiträge, auch wenn ich mit dem Dank etwas spät dran bin. Aber vielleicht hat sich die Verzögerung ja gelohnt.


Zum Thema ,,EasyHeads":
Wenn man weiß, wie es geht, ist es ganz einfach und wenn ich weiß, wo es in der Doku steht, kann ich es auch finden.
Ich war nicht auf die Idee gekommen, nur nach ,,easy" in den Dokus zu suchen. Aber selbst dann wäre ich ohne Harms Beispiel nicht klar gekommen.

Die Möglichkeit, auf diese Art und Weise ,,nationale" Notenbezeichnungen in die EasyHeads zu bekommen, überzeugt mich programmiertechnisch jedoch nicht. Mir ist da spontan das beigefügte Beispiel eingefallen. Da man ja die Eingabesprache bestimmen kann, hatte ich erwartet, dass LilyPond die Notenbezeichnungen dann auch in der Sprache ausgibt, in der sie eingegeben worden sind bzw. die Möglichkeit dazu zumindest als Option bereit stellt. Dazu bräuchte der override-Befehl nur mit einem sprachspezifischen Stammtonvektor aufgerufen zu werden. Und dies sollte/könnte m.E. standardmäßig erfolgen. Mir erschließt sich das pädagogische Konzept nicht, welches dahintersteckt, die Noten in verschiedenen Sprachen in Kleinbuchstaben eingeben zu können, sie aber standardmäßig in ,,nederlands" bzw. ,,english" als Großbuchstabe auszugeben.

Zum Thema ,,NoteNames":
Von dem Hinweis ,,Solange issue 1367
https://sourceforge.net/p/testlilyissues/issues/1367/
ungelöst ist, wird es schwierig die richtigen NoteNames hinzukriegen." ausgehend bin ich bei ,,Of course, there are workarounds: I posted a very dumb one on -user
http://lists.gnu.org/archive/html/lilypond-user/2010-10/msg00687.html" gelandet. Den dort vorgestellten Lösungsansatz habe ich aufgegriffen und verallgemeinert.

Ich habe daraus folgendes Verfahren entwickelt:
In der LilyPond-Datei bestimmt man die Notensprache statt durch den LilyPond-Befehl \include "deutsch.ly" durch den Scheme-Aufruf  #(notensprachebestimmen  "deutsch") und ruft dann im \score-Block den LilyPond-Befehl \notenspracheausgeben auf.
Notwendig ist dafür, dass die Datei  ,,notensprache.ly" mit \include eingebunden wird.

Dann erhält man mit dem üblichen LilyPond-Befehl \context die NoteNames in der Eingabesprache. Nur die Option ,,printOctaveNames" ist dann ohne Wirkung.
Getestet habe ich dies für ,,deutsch", ,,italiano" und ,,nederlands". Ich gehe deshalb davon aus, dass es auch für andere Sprachen klappt. Testergebnis kommt mit nächster Nachricht.
Ob issue 1367 damit gelöst ist, will ich nicht entscheiden, dazu sind wohl noch weitere Tests notwendig.

Nochmal zum Thema ,,EasyHeads":
Weil das mit den NoteNames so gut geklappt hat, hab ich nach vergleichbarer Mechanik (oder sollte ich besser Melodie sagen, wegen Notensatzprogramm...) auch gleich die Stammtonvektoren entwickelt. So enthalten die EasyHeads jetzt auch die Stammtöne in der Eingabesprache (in Kleinbuchstaben).

In einigen Sprachen haben die Stammtonbezeichnungen aber auch 2 oder 3 Buchstaben. Wenn die von dem brew-ez-Algorithmus alle in die runden Notenköpfe gequetscht werden, dürfte die Lesbarkeit wohl eingeschränkt sein. Als Lösung könnte ich mir so etwas vorstellen, was mit den LilyPond-Befehlen \rounded-box und \whiteout erreicht werden kann. Nur hab ich keine Ahnung, wie man LilyPond-Befehle in Scheme aufruft.

Gruß
Helmut

P.S.
Wann oder wie wird der von Manuela vorgeschlagene Code eingesetzt? Gibt's da irgendwo ein (Minimal-)Beispiel


helmut


ingmar

Zitathelmut: ... hatte ich erwartet, dass LilyPond die Notenbezeichnungen dann auch in der Sprache ausgibt, in der sie eingegeben worden sind bzw. die Möglichkeit dazu zumindest als Option bereit stellt.
Das finde ich nicht so naheliegend. Was ist, wenn ein Tscheche die Noten eingegeben hat und ich sie mir in den Notenköpfen anzeigen lassen möchte? Muss ich die Noten neu eingeben? Was ist, wenn ich ein Lehrwerk schreibe, in vier verschiedenen Sprachen? Muss ich dann meine Noten viermal eingeben? Das kanns doch nicht sein!

Ich würde erwarten, dass ich bei EasyHeads die Sprache als Parameter mitgeben kann. Vielleicht die Eingabesprache meines Files als Default, ja, vielleicht. (Das wäre dann als Defaultdefault allerdings Niederländisch..)


Gruß,
--ingmar

helmut

Ich hatte EasyHeads bisher nicht positiv als ,,Übersetzungsprogramm" wahrgenommen oder eingesetzt. Im Gegenteil, ich wollte/will meine Noten in der Sprache rausbekommen, in der ich sie eingebe.
Aber ja, kann man auch anders haben wollen, warum nicht. Funktioniert ja.

Aber diese Funktionalität fehlte bisher in Bezug auf \context NoteNames. Diese musste man sich immer in ,,nederlands" ausgeben lassen, weil man/LilyPond es anders nicht konnte.

Jetzt hat man mehr Möglichkeiten, die man aber nicht nutzen muss!

So könnte man über \include <sprache_A.ly> die Eingabesprache der Noten festlegen und diese anschließend eingeben.

Danach könnte man dann die Ausgabesprache für \context NoteNames über #(notensprachebestimmen <sprache_B>) festlegen.

Im \score-Block kann man dann durch \notenspracheausgeben die NoteNames (zwar nur, aber immerhin) in der <sprache_B> ausgeben und die EasyHeads entweder auch in  <sprache_B> ausgeben oder durch \overwrite NoteHead.note-names = ##(<stammtonvektor_sprache_C> vor \easyHeadsOn sogar eine dritte Sprache ins Spiel bringen.

Und man kann wählen, ob man die NoteNames ohne \notenspracheausgeben mit Oktav-Kennzeichnung in ,,nederlands" ausgeben möchte, oder ohne Oktavkennzeichnung in einer beliebigen LilyPond-Sprache. Was man braucht, was einem wichtiger ist.

Aber auf jeden Fall müssen die Noten (nur) einmal eingegeben werden (von wem auch immer).

Gruß
Helmut

Manuela

Zitat von: helmut am Dienstag, 22. August 2017, 12:14
Ich habe daraus folgendes Verfahren entwickelt:
In der LilyPond-Datei bestimmt man die Notensprache statt durch den LilyPond-Befehl \include "deutsch.ly" durch den Scheme-Aufruf  #(notensprachebestimmen  "deutsch") und ruft dann im \score-Block den LilyPond-Befehl \notenspracheausgeben auf.
Notwendig ist dafür, dass die Datei  ,,notensprache.ly" mit \include eingebunden wird.

Hallo Helmut,

ich habe versucht, dein Verfahren anzuwenden, bin jedoch schon an #(notensprachebestimmen  "deutsch") gescheitert, das bei mir eine Fehlermeldung bewirkt.

Hast du ein Minimalbeispiel bei der Hand?
Danke für eure Hilfe
viele Grüße
-- Manuela

helmut

Hallo Manuela,

damit das Ganze funktioniert, musst Du die Datei ,,notensprache.ly" einbinden.

Den Code hatte ich bisher noch nicht bereitgestellt, ist aber jetzt beigefügt.

Und zwei komplette Beispiele:
,,Test original.ly": ist so, wie ich es mir ursprünglich vorgestellt hatte;
,,Test ingmar.ly": da habe ich versucht den Erwartungen, Vorstellungen, Anregungen von ingmar gerecht zu werden bzw. umzusetzen. Deshalb ist der Dateiaufbau etwas anders.

Viel Spasz beim Ausprobieren (hoffentlich klappt es auch außerhalb meines Rechners!).

Gruß
Helmut

P.S.:
Kannst Du mir ein Beispiel für die Anwendung von
#(define ((chord-name->german-markup-text-alteration B-instead-of-Bb) pitch lowercase?)
zeigen?

Manuela

Hallo Helmut,

leider klappt es nicht, ich erhalte folgende Fehlermeldung

Starte lilypond-windows.exe 2.19.62 [Test original.ly]...
Processing `Test original.ly'
Parsing...
Test original.ly:21:2: error: GUILE signaled an error for the expression beginning here
#
(notensprachebestimmen "deutsch")

Interpreting music...[8]
Preprocessing graphical objects...
fatal error: make-vcenter-markup: Invalid argument in position 1.  Expect: markup, found: z.
Unbound variable: parser
Wurde mit dem Return-Code 1 beendet.


Sobald ich wieder auf meinen großen Rechner Zugriff habe, poste ich das von dir gewünschte Beispiel
Danke für eure Hilfe
viele Grüße
-- Manuela

harm6

Zitat
leider klappt es nicht, ich erhalte folgende Fehlermeldung

Starte lilypond-windows.exe 2.19.62
Deshalb hatte Helmut wohl 2.18.2 angegeben ;)

Das Problem ist (zunächst), daß ly:parser-set-note-names ab 2.19.xx nur noch ein argument will, `parser' muß man weglassen und auch an einigen anderen Stellen. Ob convert-ly das hinkriegt hab ich nicht getestet, sondern manuell upgedated.

Allerdings gibt selbst die updated Version mit meiner experimentellen guile-2.2-Version:
Zitat
$ lilypond-git-guile-2.2 Test\ ingmar.ly
GNU LilyPond 2.21.0
Processing `Test ingmar.ly'
Parsing...
notensprache.ly:57:2: error: GUILE signaled an error for the expression beginning here
#
(define (neue-note-names str)
ERROR: sequence of zero expressions
notensprache.ly:73:2: error: GUILE signaled an error for the expression beginning here
#
(define (durchlaufen listeeins)
ERROR: sequence of zero expressions
notensprache.ly:86:2: error: GUILE signaled an error for the expression beginning here
#
(define (finden listeeins listezwei)
ERROR: sequence of zero expressions
Test ingmar.ly:25:2: error: GUILE signaled an error for the expression beginning here
#
(notensprachebestimmen "deutsch")
ERROR: Unbound variable: neue-note-names
Interpreting music...
Preprocessing graphical objects...Backtrace:
          14 (apply-smob/1 #<catch-closure 27582e0>)
In ice-9/eval.scm:
   293:34 13 (_ #(#(#<directory (lily) 2811f00>) #<variable 3e0500...>))
    619:8 12 (_ #(#(#(#(#(#(#(#<directory (lily) ...>) ...) ...) ...) ...) ...) ...))
In srfi/srfi-1.scm:
    640:9 11 (for-each #<procedure 3c0f4a0 at ice-9/eval.scm:333:13...> ...)
In ice-9/eval.scm:
    619:8 10 (_ #(#(#(#(#(#<directory (lily) 2811f00> # ...) ...) ...) ...) ...))
In ice-9/boot-9.scm:
    837:9  9 (catch _ _ #<procedure 4fbfc80 at ice-9/eval.scm:386:1...> ...)
In unknown file:
           8 (ly:parse-file "Test ingmar.ly")
           7 (ly:book-process #<Book> #< Output_def> #< Output_def> #)
           6 (ly:spacing-spanner::set-springs #<Grob SpacingSpanner >)
           5 (ly:separation-item::calc-skylines #<Grob NonMusicalPap...>)
           4 (ly:hara-kiri-group-spanner::pure-height #<Grob Vertic...> ...)
           3 (ly:axis-group-interface::adjacent-pure-heights #<Grob ...>)
           2 (ly:grob::stencil-height #<Grob NoteName >)
In ice-9/eval.scm:
   293:34  1 (_ #(#(#(#<module (#{ g163}#) 30e01e0>) #<Grob Not...>) #))
In unknown file:
           0 (ly:assoc-get "c" (()) #<undefined> #<undefined>)

ERROR: In procedure ly:assoc-get:
ERROR: In procedure assoc: Wrong type argument in position 2 (expecting association list): (())

lol

Ich würde erstmal versuchen diese ganzen set-car!, etc Sachen auszumerzen.
set-car!, set-cdr!, etc auf literals angewendet geben mit guile-2.2 einen error. Die anderen mögen Folge-errors sein...

guile-1.8:
Zitat
guile> (version)
"1.8.8"
guile> (define xx '(0 . 0))
guile> (set-car! xx 'a)
guile> xx
(a . 0)
guile>

guile-2.2
Zitat
scheme@(guile-user)> (version)
$1 = "2.2.2.5-96c9"
scheme@(guile-user)> (define xx '(0 . 0))
scheme@(guile-user)> (set-car! xx 'a)
<unnamed port>:3:0: <unnamed port>:3:0: In procedure set-car!: Wrong type argument in position 1 (expecting mutable pair): (0 . 0)

Entering a new prompt.  Type `,bt' for a backtrace or `,q' to continue.
scheme@(guile-user) [1]>

Gruß,
  Harm


harm6

Eine andere Sache noch: Bitte keine Leerzeichen in file-names. Das gibt immer wieder Probleme ...

Gruß,
  Harm

harm6

literals sind vereinfacht gesagt solche mit dem '-Zeichen.
'(0 . 0) ist eins, (cons 0 0) nicht.

Deshalb:
Zitat
scheme@(guile-user)> (version)
$4 = "2.2.2.5-96c9"
scheme@(guile-user)> (define yy (cons 0 0))
scheme@(guile-user)> (set-car! yy 'a)
scheme@(guile-user)> yy
$5 = (a . 0)
scheme@(guile-user)>

Gruß,
  Harm

helmut

Da hatte ich so eine schöne Antwort an Manuela vorbereitet und dann funkt mir Harm mit etwas dazwischen, dass ich nur noch die Segel streichen kann. Das ist zu hoch für mich.
Ich habe Version 2.18.2 installiert Friscobaldi 2.20.0 und Windows 10.
So richtig Spasz machts allmählich nicht mehr!


Hier aber trotzdem noch meine Antwort an Manuela:


Hallo Manuela,

das ist ja nicht so schön.

Ich versuche mal eine Ferndiagnose.

Die Fehler scheinen durch #(notensprachebestimmen  "deutsch")verursacht zu werden.

Hast Du die Datei ,,notensprache.ly" mal alleine kompiliert?
Klappt das ohne Fehlermeldung bzw. mit der Meldung ,,Kompilation erfolgreich beendet"?

Wenn ja,
ergibt sich für mich die Frage, ob die Datei  ,,notensprache.ly" an einer Stelle gespeichert ist, an der " \include-Dateien" zu stehen haben. Ich verwende Frescobaldi und habe dort einen entsprechenden Pfad hinterlegt. Vielleicht hilft es, wenn Du die Datei in das Verzeichnis verschiebst, wo auch die Dateien ,,deutsch.ly" ,,italiano.ly" ... ... stehen.

Oder:
Du könntest auch versuchen, die Datei ,,Test original.ly" in die Datei ,,notensprache.ly" zu kopieren (ans Ende).
Vielleicht gibt es dann Fehlermeldungen, die besagen, dass Du Teile der Datei verschieben musst, z.B. ,,\version ... ..." oder vielleicht hilft es, die fehlerverursachende Zeile ersteinmal als LilyPond-Kommentar zu kennzeichnen bis die Kompilation klappt.

Oder:
Vielleicht probiert ja auch jemand anderes den Code mal aus und hat noch weitere oder bessere Ideen.

Und wenn die Kompilation der Datei ,,notensprache.ly" nicht klappt, frage ich mich, warum das bei mir aber funktioniert.

Gruß
Helmut