事情的起因是我在制作一款歌谱生成软件,希望找找乐谱的绘图库,居然发现完全没有现成的库,不得不承认,国内外计算机水平是差着不少的。。。因为,在百度上完全找不到这方面的内容,搜索歌谱排版,歌谱转pdf等等,一直没有结果。而在google上搜英文,东西一堆一堆的,于是我就把一个个人认为非常好的软件拿过来分享一下。
Lilypond是一款GNU软件,免费而开源,可以将一篇歌谱脚本自动排版成五线谱,ps文档和midi乐,而且渲染质量非常之高,这是下面它的效果图:
而它使用的脚本则是自定义语法规则的描述类语言:
\header {
title = "LilyPond demo"
enteredby="Han-Wen Nienhuys"
maintainer="[email protected]"
texidoc = "heavily mutilated Edition Peters Morgenlied by Schubert"
}
\version "2.12.0"
ignoreMelisma = \set ignoreMelismata = ##t
ignoreMelismaOff = \unset ignoreMelismata
#(set-global-staff-size 21)
\paper {
%#(set-global-staff-size (* 5.8 mm))
indent = #(* mm 4)
line-width = #(* mm 140)
interscoreline = 2.\mm
between-system-space = 15\mm
ragged-bottom = ##t
}
modernAccidentals = {
\set Staff.extraNatural = ##f
\set Staff.autoAccidentals = #'(Staff (same-octave . 1) (any-octave . 0))
\set Staff.autoCautionaries = #'()
}
melody = \relative c'' \repeat volta 2 \context Voice = "singer" {
\time 6/8
\autoBeamOff
s1*0^\markup { \larger { \hspace #-3.0 Lieblich, etwas geschwind } }
R2.
r4 r8 c4 g8 |
\acciaccatura { f16 } e4 c8
<<
\new Voice { \stemUp f8. g16 }
{ \stemDown f8.[ g16] } >> \stemNeutral a8 |
fis4 g8 c16[ b a g] f[ e] |
d4 f8
\transpose a' e' \relative c'' { a16[ g fis! g] f![ d] } |
g4. r8 gis gis |
a4 a16.[ b32] c8[( a]) fis8 |
g4.~ g8-\fermata
}
firstVerse = \lyricmode {
\set stanza = "1."
Sü -- ßes Licht! Aus
\ignoreMelisma
gol --
\ignoreMelismaOff
de -- nen Pfor -- ten brichst du __ |
sie -- gend durch __ die Nacht. Schö -- ner Tag, du __ bist er -- wacht. __
}
secondVerse = \lyricmode {
\set stanza = "2."
いろはに כיף та та ほへど ちり ぬるを
Жъл дю ля זה
いろ はに כיף та та ほへ ちり ぬる
Жъл дю ля __
}
pianoRH = \relative c''' \repeat volta 2\new Voice {
#(set-accidental-style 'modern)
\voiceOne
g16( fis a g fis g f e d c b
\oneVoice
a ) |
8( \arpeggio) r8 r |
r8 c'( e,) f r a |
\once \override DynamicLineSpanner #'padding =#3
r8
<< { fis( g) } \\
<< { a4 } { s8\> s8\! } >>
>>
r8 8[ ] |
4. r8 \clef bass |
\crescTextCresc
e,16_" "\<
g c g e g d gis b gis d gis |
c, e a e c e a,-\f\! d fis d a d |
b d g d b g e16. r32\fermata
}
pianoLH = \relative c'' \repeat volta 2\new Voice {
#(set-accidental-style 'modern)
\voiceTwo
g16( fis a g fis g
f e d c b
\change Staff = down
\oneVoice
d,) |
g4.( b,8) r r
\clef treble \grace s16 r8 8-> 8->([ )] r |
\clef bass
r8 dis( e) r c c |
f,4. g8[ r8 g] |
4. 4. |
a,4. 4. |
g,8 r r g16 r16\fermata
}
\book {
\score {
<< \time 6/8
\new Staff \with {
fontSize = #-3
\override StaffSymbol #'staff-space = #(magstep -3)
} <<
\context Staff #(set-accidental-style 'modern)
\melody >>
\lyricsto "singer" \new Lyrics \firstVerse
\lyricsto "singer" \new Lyrics \secondVerse
\new PianoStaff <<
\set PianoStaff.instrumentName = \markup {
\bold
\larger\larger\larger\larger
\huge
"2."
}
\context Staff = up <<
\pianoRH
\pianoLH
>>
\context Staff = down { \clef bass \skip 1*2 }
>>
>>
\layout {
\context {
\Lyrics
\override VerticalAxisGroup #'minimum-Y-extent = #'(-0.85 . 2.2)
\override LyricText #'font-size = #-1
}
\context {
\Score
\override Beam #'thickness = #0.55
\override Beam #'auto-knee-gap = #4.0
\override SpacingSpanner #'spacing-increment = #1.0
\override Stem #'stemlet-length = #0.5
\override Slur #'height-limit = #1.5
}
}
\midi {
\context {
\Score
tempoWholesPerMinute = #(ly:make-moment 70 4)
}
}
}
}
这款软件可以很方便的通过命令行调用,(因为是GNU的嘛),使用方法就是
lilypond 文件名 (当然还有各种可选参数表,具体就看help吧)
我用C#写了段脚本生成代码,然后用cmd命令调用了一下,有需要的就当做参考吧:
/*
* @Author: sxf
* @Date: 2014-01-12 22:02:12
* @Last Modified by: sxf
* @Last Modified time: 2014-01-16 12:43:15
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Diagnostics;
using System.IO;
class GenerateStaff{
String title = "Demo";
public void Set(String title)
{
this.title = title;
}
StreamWriter sw;
public void Generate(String str) {
sw = new StreamWriter(str,false);
sw.WriteLine("\\header {");
sw.WriteLine("title = \"{0}\" ",title);
sw.WriteLine("}");
sw.WriteLine("\\version \"2.12.0\"");
sw.WriteLine("ignoreMelisma =\\set ignoreMelismata = ##t");
sw.WriteLine("ignoreMelismaOff = \\unset ignoreMelismata");
sw.WriteLine("#(set-global-staff-size {0})",21);
sw.WriteLine("\\paper {{\n%#(set-global-staff-size (* {0} mm))",5.8);
sw.WriteLine("indent = #(* mm {0})",4);
sw.WriteLine("line-width = #(* mm {0})",140);
sw.WriteLine("interscoreline = {0}.\\mm",2);
sw.WriteLine("between-system-space = {0}\\mm",15);
sw.WriteLine("ragged-bottom = ##t ");
sw.WriteLine("}");
sw.WriteLine("modernAccidentals = {");
sw.WriteLine("\\set Staff.extraNatural = ##f");
sw.WriteLine("\\set Staff.autoAccidentals = #\'(Staff (same-octave . 1) (any-octave . 0))");
sw.WriteLine("\\set Staff.autoCautionaries = #\'() ");
sw.WriteLine("}");
sw.Write("melody = ");
writeRelative("c\'\' ");
// writeClef("bass");
writeTime(6,8);
// sw.Write("\\repeat volta 2 \\context Voice = \"singer\" ");
sw.WriteLine("{");
// sw.WriteLine("\\autoBeamOff");
writeClef("bass");
// writeTime(6,8);
// sw.WriteLine("\\autoBeamOff");
// sw.WriteLine("s1*0^\\markup {{ \\larger {{ \\hspace #-3.0 Lieblich, etwas geschwind }} }}");
// sw.WriteLine("R2.");
writeNote(1);
writeNote(2);
for (int i = 1; i < 8; ++i)
{
writeNote(i,4);
}
for (int i = 1; i < 8; ++i)
{
writeNote(i,4);
}
Random ra = new Random();
for (int i = 1; i < 250; ++i)
{
writeNote(ra.Next(7)+1,8);
}
sw.WriteLine("}");
sw.Close();
}
int mi(int x)
{
int y = 2;
for (int i =1;i