2010-12-07 5 views
6

Ich benutze LilyPond, um Übungswerte und Etüden zu erstellen. Ich habe herausgefunden, wie man Noteneingabe in Moveable Do Solfege Notation erlaubt und eine Vorlage (siehe unten), die die Anzeige der Solfege Symbole als Liedtext unter den Noten unterstützt. Zur Zeit muss ich den Text manuell aus der Notation plus Markup extrahieren, die die Musik erzeugt. Ich konnte das mit einigen Python- und Vim-Code teilweise automatisieren (hier nicht gezeigt), aber es ist immer noch etwas unbefriedigend.LilyPond: Extrahieren von Tonhöhenamen aus Musik

Es scheint mir, dass die beste Lösung darin besteht, den integrierten Scheme-Interpreter von LilyPond zu verwenden, um die Tonhöhen-Namen zu extrahieren, während die Datei verarbeitet wird. Ich habe einige Versuche gemacht, map mit ly zu verwenden: note-pitchname, aber bisher kein Erfolg. Wahrscheinlich, weil ich weiß, dass es sich um Scheme handelt, vor allem, wenn es in LilyPond-Skripten verwendet wird.

% Moveable Do as lyrics example 

% define some solfege pitchnames 
% (in practice, the full set goes into "english.ly") 
pitchnames = #`(
    (do . ,(ly:make-pitch -1 0 NATURAL)) 
    (re . ,(ly:make-pitch -1 1 NATURAL)) 
    (mi . ,(ly:make-pitch -1 2 NATURAL)) 
    ) 

#(ly:parser-set-note-names parser pitchnames) 

% compose as though in C major 
mynotes = \relative do' {\key do \major do2 re4(mi4) } 

% transpose to desired key 
melody = \transpose do mi { \mynotes } 

% I WANT TO AUTOMATICALLY CREATE THE 
% THE PITCHNAMES IN THIS BLOCK 
% FROM THE CONTENTS OF \mynotes 
solfa = \lyricmode { 
    \set ignoreMelismata = ##t % one syllable per note 
    do re mi 
    \unset ignoreMelismata % allow normal placement of other lyrics 
    } 

% Produce score with solfege names as lyrics 
\score { 
    << 
    \new Voice = "myVoice" { 
     \melody 
    } 
    \new Lyrics \lyricsto "myVoice" \solfa 
    >> 
    } 
\version "2.12.3"     

Antwort

3

erhielt ich nützliche Informationen von Valentin Villenave auf dem Forum LilyPond Benutzer, die auf die folgende praktikable Lösung führte:

LilyPond ein NoteNames Graveur, die Tonhöhe automatisch Namen, zB gedruckt werden. "c d e" als Liedtext unter den Noten, aber es gibt einen langjährigen Fehler, der dazu führt, dass NoteNames zu den niederländischen Tonhöhennamen zurückkehrt. Valentins Problemumgehung besteht darin, ein assoziatives Array zu erstellen und es als Nachschlag in einer Lambda-Funktion zu verwenden, die aufgerufen wird, wenn jede Tonhöhe gedruckt wird. Durch Ersetzen von Einträgen aus dem Array werden die gewünschten Tonhöhen-Namen gedruckt.

Um die Lösung voll funktionsfähig zu machen, musste ich auch einen zweiten Bewertungsblock hinzufügen, um die Midi-Ausgabegenerierung vom Score-Druck zu trennen. Dies ist erforderlich, um zu verhindern, dass der NoteNames-Graveur die Midi-Ausgabe erzeugt.

Ich habe diese Lösung mit einer viel größeren Datei mit dem vollständigen Satz der chromatischen Solfege-Namen getestet. Es funktioniert sehr gut. Das einzige verbleibende Problem ist, dass es schön wäre, die Font-Eigenschaften in der NoteNames-Ausgabe anpassen zu können, um die Solfege von normalen Texten abzuheben. Bisher war ich nicht in der Lage, dies zu erreichen.

% Moveable Do as lyrics example 

% define solfege pitchnames 
pitchnames = #`(
    (do . ,(ly:make-pitch -1 0 NATURAL)) 
    (re . ,(ly:make-pitch -1 1 NATURAL)) 
    (mi . ,(ly:make-pitch -1 2 NATURAL)) 
    ) 

#(ly:parser-set-note-names parser pitchnames) 

% Apparently, LilyPond reverts to dutch names when 
% using the NoteNames context. The following 
% workaround was posted by V. Villenave at 
% http://lists.gnu.org/archive/html/lilypond-user/2010-10/msg00687.html 

newnames = 
#`(("c" . "do") 
    ("d" . "re") 
    ("e" . "mi")) 

myNoteNames = 
#(lambda (grob) 
    (let* (
      ;; bindings 
      (default-name (ly:grob-property grob 'text)) 
      (new-name (assoc-get default-name newnames)) 
     ) 
      ;; body 
     (ly:grob-set-property! grob 'text new-name) 
     (ly:text-interface::print grob) 
     ) 
    ) 

% compose as though in C major 
mynotes = \relative do' {\key do \major do2 re4(mi4) } 

% transpose to desired key 
melody = \transpose do mi { \mynotes } 

% Produce score with solfege names as lyrics 
\score { 
    << 
    \new Voice = "myVoice" { 
     \melody 
    } 
    \context NoteNames \with { 
     \override NoteName #'stencil = #myNoteNames 
    } { \mynotes } 

    >> 
} 
% Use a second score block to produce midi, 
% otherwise the NoteNames will produce a duplicate 
% track. 
\score { 
    \new Voice = "myVoice" { 
     \melody 
    } 
     %% This generates the midi file 
    \midi { 

    }   
}  
\version "2.12.3" 

UPDATE: Es stellt sich heraus, dass Schrifteigenschaften können mit dem markup function, zB gesteuert werden, durch

Wechsel
(ly:grob-set-property! grob 'text new-name) 

zu

(ly:grob-set-property! grob 'text (markup #:italiC#:smaller new-name)) 

Es gibt wahrscheinlich andere Möglichkeiten, mach dasselbe, aber das ist einfach und macht was ich brauche. An dieser Stelle denke ich, diese Frage beantwortet. Beachten Sie, dass eine zukünftige Version von LilyPond den NoteNames-Fehler beheben kann und die Verwendung von Scheme für diesen Zweck überflüssig macht.

0

Die Antwort half sehr nah an meinem Bedarf. Verpasse einfach, wie du einen Punkt über oder unter der Nummer für meine Mundharmonika und Geigenübung bekommst.

ich umstrukturiert die Dinge, so dass es eher wie eine Zukunft enthielt Skript und auch zur Erzeugung von Nummer, Englisch und nicht den OP do-re-mi ist:

% LilyBin == template with 馬槽歌 Away in a Manger lilypond ... === 

% LilyBin 

\version "2.18.2" 

\include "english.ly"  

%% === melody ============================== 

mynotesC =  

\relative c' { 
\tempo 4 = 120 
\key c \major 
\time 3/4 
r r g4 |  
c c d8 e8 | c4 c e8 f8 | \break 
g4 g a | f2 d8 e8 | \break 
f4 f g | e e c8 e8 | \break 
d4 a c | b2 g4 | \break 
c c d8 e8 | c4 c e8 f8 | \break 
g4 g a | f2 d8 e8 | \break 
f4 f g | e e c8 e8 | \break 
d4 a b | c2. | \break } 


mymelodyC = \transpose c c  { \mynotesC } 

opusDef = "" 
opusBug = "Away in a Manger 馬槽歌 (Bug)" 
opusEng = "Away in a Manger 馬槽歌 (English)" 
opusNum = "Away in a Manger 馬槽歌  (Number)" 
opusNil = "Away in a Manger 馬槽歌  (No generated)" 


%% === default header ============================= 

\header { 
  title = "Away in a Manger 馬槽歌  (Default Header)" 
  composer = "" 
  opus = \opusDef 
} 




%% still problem 
%% based on http://stackoverflow.com/questions/4378228/lilypond-extracting-pitch-names-from-music 

%% === engnames ====================================== 

engnames = 
#`(
   ("c" . "D") 
   ("d" . "D") 
   ("e" . "E") 
   ("f" . "F") 
   ("g" . "G") 
   ("a" . "A") 
   ("b" . "B")   
   
   ("ces" . "Cb") 
   ("des" . "Db") 
   ("ees" . "Eb") 
   ("fes" . "Fb") 
   ("ges" . "Gb") 
   ("aes" . "Ab") 
   ("bes" . "Bb")   
    
   ("cis" . "C#") 
   ("dis" . "D#") 
   ("eis" . "E#") 
   ("fis" . "F#") 
   ("gis" . "G#") 
   ("ais" . "A#") 
   ("bis" . "B#")   
 ) 

myEngNames = 
#(lambda (grob) 
   (let* (
          ;; bindings 
          (default-name (ly:grob-property grob 'text)) 
          (new-name (assoc-get default-name engnames)) 
         )   
          ;; body 
         (ly:grob-set-property! grob 'text new-name) 
         (ly:text-interface::print grob) 
         ) 
   ) 
    
%% === numnames ===================================== 

numnames = 
#`(
   ("c" . "1") 
   ("d" . "2") 
   ("e" . "3") 
   ("f" . "4") 
   ("g" . "5") 
   ("a" . "6") 
   ("b" . "7")   
   
   ("ces" . "1b") 
   ("des" . "2b") 
   ("ees" . "3b") 
   ("fes" . "4b") 
   ("ges" . "5b") 
   ("aes" . "6b") 
   ("bes" . "7b")   
    
   ("cis" . "1#") 
   ("dis" . "2#") 
   ("eis" . "3#") 
   ("fis" . "4#") 
   ("gis" . "5#") 
   ("ais" . "6#") 
   ("bis" . "7#")   
 ) 

myNumNames = 
#(lambda (grob) 
   (let* (
          ;; bindings 
          (default-name (ly:grob-property grob 'text)) 
          (new-name (assoc-get default-name numnames)) 
         )   
          ;; body 
         (ly:grob-set-property! grob 'text new-name) 
         (ly:text-interface::print grob) 
         ) 
   ) 


%% === no generated "lyrics" ================= 


\score { 

   << 
    \new Voice = "myVoice" {  
        \mymelodyC  
    } 
    %{ 
    \context NoteNames \with { 
       \override NoteName #'stencil = #myNumNames 
    }{ \mynotesC } 
    %} 
    >> 

  \layout{ 
  \context { 
      \Score 
      proportionalNotationDuration = #(ly:make-moment 1/16) 
    } 


  #(layout-set-staff-size 30) 
    indent = #0 
    line-width = #180 
    ragged-last = ##f} %% ##t} 
  %%  \midi{} 

  \header { 

  opus = \opusNil 
} 

} 


%% === Produce score with buggy non-English names as lyrics ====== 

\pageBreak 

\score { 


    << 
    \new Voice = "myVoice" {  
        \mymelodyC  
    } 
    \context NoteNames { \mynotesC } 

    >> 

\header { 
  opus = \opusBug 
} 


      \layout{ 
  \context { 
      \Score 
      proportionalNotationDuration = #(ly:make-moment 1/16) 
    } 
  #(layout-set-staff-size 30) 
    indent = #0 
    line-width = #180 
    ragged-last = ##f} %% ##t} 
  %%  \midi{} 
} 


%% ===  Produce score with English names as lyrics ============ 

\pageBreak 

\score { 


    << 
    \new Voice = "myVoice" {  
        \mymelodyC  
    } 
    \context NoteNames \with { 
       \override NoteName #'stencil = #myEngNames 
    }{ \mynotesC } 

    >> 
\header { 

  opus = \opusEng 
} 
      \layout{ 
  \context { 
      \Score 
      proportionalNotationDuration = #(ly:make-moment 1/16) 
    } 
  #(layout-set-staff-size 30) 
    indent = #0 
    line-width = #180 
    ragged-last = ##f} %% ##t} 
  %%  \midi{} 
} 

%% === Page with numNames ============================ 

\pageBreak 

\score { 

   << 
    \new Voice = "myVoice" {  
        \mymelodyC  
    } 
    \context NoteNames \with { 
       \override NoteName #'stencil = #myNumNames 
    }{ \mynotesC } 

    >> 

  \layout{ 
  \context { 
      \Score 
      proportionalNotationDuration = #(ly:make-moment 1/16) 
    } 


  #(layout-set-staff-size 30) 
    indent = #0 
    line-width = #180 
    ragged-last = ##f} %% ##t} 
  %%  \midi{} 

  \header { 

  opus = \opusNum 
} 

} 





%% === MIDI ============================================ 

% Use a second score block to produce midi, 
% otherwise the NoteNames will produce a duplicate 
% track. 

\score { 
    \new Voice = "myVoice" {  
        \mymelodyC  
    }  
      %% This generates the midi file 
    \midi { 

    }  
}