LilyPond:从音乐中提取音高

Mik*_*lis 6 scheme guile 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"                 
Run Code Online (Sandbox Code Playgroud)

Mik*_*lis 5

我在 LilyPond 用户论坛上收到了来自 Valentin Villenave 的有用信息,这些信息导致了以下可行的解决方案:

LilyPond 提供了一个 NoteNames 雕刻机,可以自动打印音高名称,例如。“cd e”作为音符下方的歌词,但存在一个长期存在的错误,导致音符名称恢复为荷兰语音高名称。Valentin 的解决方法是创建一个关联数组,并将其用作 lambda 函数中的查找,该函数在每个音高即将打印时被调用。通过替换数组中的条目,可以打印所需的音高名称。

为了使该解决方案完全可行,我还必须添加第二个乐谱块,以将 MIDI 输出生成与乐谱打印分开。这是为了防止 NoteNames 雕刻机产生 MIDI 输出。

我已经使用完整的半音视唱名称集使用更大的文件测试了该解决方案。它运作得很好。唯一剩下的问题是,如果能够调整 NoteNames 输出上的字体属性以使视唱与正常歌词不同,那就太好了。到目前为止我还没能做到这一点。

% 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"  
Run Code Online (Sandbox Code Playgroud)

更新:事实证明,可以使用标记功能来控制字体属性,例如,通过更改

(ly:grob-set-property! grob 'text new-name)
Run Code Online (Sandbox Code Playgroud)

(ly:grob-set-property! grob 'text (markup #:italic #:smaller new-name))
Run Code Online (Sandbox Code Playgroud)

可能还有其他方法可以完成同样的事情,但这很简单并且可以满足我的需要。至此,我认为这个问题得到了解答。请注意,LilyPond 的未来版本可能会修复 NoteNames 错误,并消除为此目的使用 Scheme 的需要。