LilyPond:从音乐中提取音高名称

我使用LilyPond创建练习成绩和练习曲。我已经想出了如何允许在Moveable Do solfege表示法中输入音符,并且有一个模板(见下文),它支持在音符下面显示solfege符号作为歌词。目前,我必须手动从符号加上生成音乐的标记中提取歌词。我已经能够使用一些python和vim代码(这里没有显示)部分自动化,但它仍然有点令人不满意。 在我看来,最好的解决方案是使用LilyPond的内置Scheme解释器在处理文件时提取音高名称。我已经尝试过使用地图与ly:note-pitchname,但到目前为止还没有成功。可能是因为我知道对Scheme的蹲坐,特别是在LilyPond脚本中使用的。
% 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"                 
    
已邀请:
我从LilyPond用户论坛上收到了Valentin Villenave的有用信息,从而产生了以下可行的解决方案: LilyPond提供了一个NoteNames雕刻机,可自动打印音高名称,例如。 “c d e”作为音符下方的歌词,但有一个长期存在的错误导致NoteNames恢复为荷兰音调名称。 Valentin的解决方法是创建一个关联数组,并将其用作lambda函数中的查找,该函数在每个音高即将打印时被调用。通过替换阵列中的条目,打印所需的音高名称。 为了使解决方案完全可行,我还必须添加第二个分数块以将midi输出生成与乐谱打印分开。这是为了防止NoteNames雕刻师产生midi输出。 我使用完整的彩色solfege名称测试了这个解决方案的大文件。它工作得很好。唯一剩下的问题是能够在NoteNames输出上调整字体属性以使solfege与普通歌词不同是很好的。到目前为止,我还未能做到这一点。
% 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"  
更新: 事实证明,可以使用标记功能来控制字体属性,例如通过改变
(ly:grob-set-property! grob 'text new-name)
(ly:grob-set-property! grob 'text (markup #:italic #:smaller new-name))
可能还有其他方法可以完成相同的事情,但这很简单,并且做我需要的。在这一点上,我认为这个问题得到了回答。请注意,未来版本的LilyPond可能会修复NoteNames错误,并且无需为此目的使用Scheme。     
答案非常接近我的需要。只是想念如何在我的口琴和小提琴练习的数字上方或下方获得一些点。 我重新构建了这些东西,所以它更像是未来包含的脚本,也用于生成数字,英语而不是OP do-re-mi:
% 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 {

    } 
}
    

要回复问题请先登录注册