Deutschsprachiges LilyPond-Forum

Allgemeine Fragen und Probleme => Fragen und Probleme aller Art => Thema gestartet von: Köbi am Dienstag, 8. August 2017, 14:25

Titel: Transpose mit MusicTree
Beitrag von: Köbi am Dienstag, 8. August 2017, 14:25
Unter http://lilypondblog.org/2014/07/trees-music-and-lilypond/ habe ich etwas praktisches gefunden (Spielt für das nachvollziehen des Problems nicht direkt eine Rolle.)

Leider funktioniert das in Kombination mit \transpose zu einem unerwarteten Problem: Wieso steht im 1. Ssystem auch ein d' und nicht ein c', wie ich es erwarten würde?


\version "2.19.64"

musicTree = #'()

% function to store music in `musicTree`
putMusic =
#(define-void-function (parser location path content)(string? ly:music?)
   (let ((pl (string->path path)))
     (set! musicTree (tree-set! musicTree pl content))
     ))

% function to get music from `musicTree`
getMusic =
#(define-music-function (parser location path)(string?)
   (let* ((pl (string->path path))
          (content (tree-get musicTree pl)))
     (if (ly:music? content) content (make-music 'SequentialMusic 'void #t))
     ))

% set a value in a tree -- based on nested association lists
#(define-public (tree-set! tree path val)
   (if (> (length path) 1)
       (let ((tab (assoc (car path) tree)))
         (if (not (pair? tab))(set! tab '((car path))))
         (assoc-set! tree (car path) (tree-set! (cdr tab) (cdr path) val))
         )
       (assoc-set! tree (car path) val))
   )

% get a value from a tree -- based on nested association lists
#(define-public (tree-get tree path)
   (let ((ret (assoc (car path) tree)))
     (if (pair? ret)
         (if (> (length path) 1)
             (tree-get (cdr ret) (cdr path))
             (cdr ret))
         #f))
   )

% split a string by '/'
#(define-public (string->path str)(string-split str #\/))

\putMusic "A" \relative { c' }


\new Staff {
  \getMusic "A"
}
\new Staff {
  \transpose c d \getMusic "A"
}


Ich komme einfach nicht drauf, sorry.
Titel: Antw:Transpose mit MusicTree
Beitrag von: Malte am Dienstag, 8. August 2017, 14:42
Zitat von: Köbi am Dienstag,  8. August 2017, 14:25
Leider funktioniert das in Kombination mit \transpose zu einem unerwarteten Problem: Wieso steht im 1. Ssystem auch ein d' und nicht ein c', wie ich es erwarten würde?
musicTree ist eine einzige Datenstruktur, die durch das \transpose anscheinend verändert wird. Aber merkwürdig, denn PDF-Ausgabe und Output von \displayLilyMusic widersprechen sich:\new Staff {
  \displayLilyMusic \getMusic "A"
}
\new Staff {
  \displayLilyMusic \transpose c d \getMusic "A"
}

Du kannst aber zwischen die beiden Partituren noch die ZeilemusicTree = #(ly:music-deep-copy musicTree)schalten. Dann wird musicTree kopiert und diese Kopie wieder dem Namen musicTree zugewiesen. Die erste Partitur arbeitet dann mit der alten, die zweite mit der neuen Kopie.
Titel: Antw:Transpose mit MusicTree
Beitrag von: harm6 am Dienstag, 8. August 2017, 15:42
Unter gewissen Umständen kann transpose ihr Argument nicht nur destruktiv verändern, sondern sogar "zurückschlagen" bis in die originale Definition des Arguments und es auch dort verändern.
Gewisse Umstände sind idR nicht ganz astreine Codings. Hier ist es getMusic. Verwende:

getMusic =
#(define-music-function (parser location path)(string?)
   (let* ((pl (string->path path))
          (content (tree-get musicTree pl)))
     (if (ly:music? content)
         (ly:music-deep-copy content) ;; <-----------
         (make-music 'SequentialMusic 'void #t))))


Das von Malte vorgeschlagene:
musicTree = #(ly:music-deep-copy musicTree)
würde ich nicht verwenden.
Es funktioniert ja. Aber musicTree ist keine Musik, insoweit bin ich etwas erstaunt, daß es klappt. Das mag auch nur solange gelten wie ein paranoider Code-Hygeniker diesen Fall nicht ausschließt... ;)

Gruß,
  Harm
Titel: Antw:Transpose mit MusicTree
Beitrag von: Köbi am Dienstag, 8. August 2017, 16:12
Ihr seid einfach super! Vielen Dank Harm, so funktioniert es :-)