LilyPond と Ruby による自動作曲システム ver-0.1
楽譜制作ソフト LilyPond を利用した自動作曲システム、Ruby 版。
考え方は Awk 版と同じ。
- LilyPond と Awk による自動作曲システム ver.minus1.0
結果の MIDI と楽譜は次の通り。
- bwv997-r.midi
ソースは Awk 版と同じで、バッハの Prelude to Suite in C Major。
- Preludio
このうち最初の % 1、% 10、% 20、% 30、% 40 の箇所を次の Ruby プログラムで読み込んで新しい ly ファイル(LilyPond 形式のファイル)を作り、その ly ファイルを LilyPond のコマンドで処理した結果が上の MIDI と楽譜。
[メモ]
MarkovChain クラスの initialize メソッドに与える引数 n でマルコフ連鎖の次数を変えることができる。
Awk 版の出力見本で音程がずり上がったままになったり、今回の Ruby 版でずりさがったりしてるのは、連鎖の次数が低いのが一因だが、曲自体の特性や LilyPond の記法などソースにもある。前処理その他使い方の問題。
考え方は Awk 版と同じ。
- LilyPond と Awk による自動作曲システム ver.minus1.0
結果の MIDI と楽譜は次の通り。
- bwv997-r.midi
ソースは Awk 版と同じで、バッハの Prelude to Suite in C Major。
- Preludio
このうち最初の % 1、% 10、% 20、% 30、% 40 の箇所を次の Ruby プログラムで読み込んで新しい ly ファイル(LilyPond 形式のファイル)を作り、その ly ファイルを LilyPond のコマンドで処理した結果が上の MIDI と楽譜。
class MarkovChain
def initialize(n)
@order = n
@nodes = { Array.new(@order) => [] }
@history = Array.new(@order)
end
def reset
(0...@order).each {|i| @history[i] = nil }
end
def add(leaf)
if @nodes.has_key?(@history)
@nodes[@history].push leaf
else
@nodes[@history.dup] = [leaf]
end
@history.shift
@history.push leaf
end
def get()
reset unless @nodes.has_key?(@history)
leaves = @nodes[@history]
leaf = leaves[rand(leaves.size)]
@history.shift
@history.push leaf
return leaf
end
end
print <<HEADER
\\version "2.14.2"
\\score {
\\relative c'' {
\\key c \\major
\\time 4/4
HEADER
mc = MarkovChain.new(2)
$stdin.readlines.each do |line|
line.split.each do |sym|
mc.add(sym)
mc.reset if sym == "|"
end
end
mc.reset
1.upto(5).each do
while(true)
sym = mc.get
if sym == "|"
print "\n"; break
else
print sym + " "
end
end
end
print <<FOOTER
}
\\layout { }
\\midi {} }
FOOTER
[メモ]
MarkovChain クラスの initialize メソッドに与える引数 n でマルコフ連鎖の次数を変えることができる。
Awk 版の出力見本で音程がずり上がったままになったり、今回の Ruby 版でずりさがったりしてるのは、連鎖の次数が低いのが一因だが、曲自体の特性や LilyPond の記法などソースにもある。前処理その他使い方の問題。