to top page
2013-02-06
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 と楽譜。

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 の記法などソースにもある。前処理その他使い方の問題。