在LilyPond中定义\ score内的函数

时间:2013-12-31 13:20:37

标签: scope lisp user-defined-functions lilypond

我编写了一本大型的歌曲书,为此我希望有许多本地函数定义,最终会在\include d文件中,但这没有区别。为此,我需要在\score{ ... }范围内定义函数。但是,LilyPond一直在抛出错误。

非工作示例:

\version "2.17.26"

\book {

    \header {
        title = "This is a book"
    }

    \score {
        xyz = { a' b' c'' }
        abc = #(define-music-function
            ( parser location musicnotes )
            ( ly:music? )
            #{
                c' $musicnotes e'
            #}
        )
        { \abc { d' } f' \xyz }
        \header {
            piece = "First piece"
            opus = "op. 1024"
        }
    }

    \score {
        xyz = { a' a' a' }
        abc = #(define-music-function
            ( parser location musicnotes )
            ( ly:music? )
            #{
                e' $musicnotes c'
            #}
        )
        { \abc { d' } f' \xyz }
        \header {
            piece = "Second piece"
            opus = "op. 1025"
        }
    }

}

引发错误:

test.ly:10:17: error: unrecognized string, not in text script or \lyricmode   
           xyz = { a' b' c'' }

以下作品,我必须给函数赋予唯一的名称,这是不赞成的。

\version "2.17.26"

xyz = { a' b' c'' }
abc = #(define-music-function
    ( parser location musicnotes )
    ( ly:music? )
    #{
        c' $musicnotes e'
    #}
)

xxyz = { a' a' a' }
aabc = #(define-music-function
    ( parser location musicnotes )
    ( ly:music? )
    #{
        e' $musicnotes c'
    #}
)

\book {

    \header {
        title = "This is a book"
    }

    \score {
        { \abc { d' } f' \xyz }
        \header {
            piece = "First piece"
            opus = "op. 1024"
        }
    }

    \score {
        { \aabc { d' } f' \xxyz }
        \header {
            piece = "Second piece"
            opus = "op. 1025"
        }
    }

}

2 个答案:

答案 0 :(得分:6)

不幸的是,不可能在分数中坚持分配。您只能在以下位置放置作业:

  • 顶级,
  • \display\header\midi块内

LilyPond语法非常清楚,即使手册的其余部分有点回避它。 (查看http://lilypond.org/doc/v2.17/Documentation/contributor/lilypond-grammar,查找assignment规则的使用位置。

假设您的分配不适合上面列出的块(在本例中肯定是这种情况),并且假设您不想做一些奇特的事情,比如去定义您自己的Scheme模块并弄清楚如何在LilyPond文件中使用它们,您有两种选择:

  1. 定义xyzabc,然后定义将进入第一个分数的音乐。然后重新定义 xyzabc,然后为下一个分数定义音乐。这是有效的,因为赋值会覆盖之前的任何内容,并且因为LilyPond定义通常按顺序处理。但是,如果您希望某些定义在两个分数中使用并且相同,则可能会感到困惑。
  2. 为你的方法做准备,虽然我会选择一个前缀或后缀,以便更清楚地定义了定义所依据的分数。
  3. 第一个选项看起来像这样:

    \version "2.18.0"
    xyz = { a' b' c'' }
    abc = #(define-music-function (parser location musicnotes)
      (ly:music?)
      #{ c' $musicnotes e' #})
    smus_a = { \abc { d' } f' \xyz }
    
    xyz = { a' a' a' }
    abc = #(define-music-function (parser location musicnotes)
      (ly:music?)
      #{ e' $musicnotes c' #})
    smus_b = { \abc { d' } f' \xyz }
    
    \book {
      \header {
        title = "A Book!"
      }
      \score {
        \smus_a
        \header { piece = "First piece" }
      }
      \score {
        \smus_b
        \header { piece = "Second piece" }
      }
    }
    

    如果音乐定义部分被重构为单独的LilyPond源文件,这也有效。

答案 1 :(得分:3)

有可能! 您必须定义一个命令来定义变量或命令:

parserDefine =
#(define-void-function (parser location name val)(symbol? scheme?)
    (ly:parser-define! parser name val))

这是一个void函数,可以在任何地方被称为

\score {
    {
        % you have to be in your music-expression
        \parserDefine xyz { a' a' a' }
        % There must be something between parserDefine and the call!
        c'' \xyz
        \parserDefine abc #(define-music-function
            ( parser location musicnotes )
            ( ly:music? )
            #{
                c' $musicnotes e'
            #}
            )
         a' \abc d'
    }
}

如果定义了命令,则可以在音乐表达式中调用。完成之后,解析器需要一点前瞻,因此变量确实可用 - 这里是c''。您可以选择将表达式包装在另一对花括号中。