ならば

音とかで遊んでいたログ

L-systemを使った作曲

「マッチ箱の脳」というとっても平易な人工知能の入門書がある。WEBバージョンもある。素晴らしい。

マッチ箱の脳(AI)―使える人工知能のお話

マッチ箱の脳(AI)―使える人工知能のお話

この本にはL-systemを自動作曲に応用する章がある。そこに載っている一番簡単な自動作曲装置をChucKで実装してみた。

L-systemの仕様としては、初期状態が「ド」で、置換規則が

◆ルール1:ドはミ、レ、ファに分裂する
◆ルール2:レはドに変化する
◆ルール3:ミはミのまま
◆ルール4:ファはソ、シに分裂する
◆ルール5:ソはレ、ラに分裂する
◆ルール6:ラはファに変化する
◆ルール7:シはシのまま

ほぼ日刊イトイ新聞 - がんばれ森川くんの遺伝子くん

となっている。この表現では文字とその解釈が一体化しているけれど、本来L-systemそのものは置換規則に従って単に文字列を生成するだけで、文字列を何に応用するか(どう解釈するか)はL-systemとは独立している。


実装では7種類の文字 ドレミファソラシ をそれぞれ 0123456 に変換した。

14 => int N;      // 置換規則を適用する回数
.3::second => dur T;

StifKarp karp => JCRev rev => dac;
.1 => karp.gain;
.7 => rev.mix;

class Symbol {
    int symbol;  // 文字
    null @=> Symbol @ next;
}
Symbol @ str;    // 文字列

init([0]);
for (int i; i < N; i++) next();
play();

fun void init(int axiom[]) {
    new Symbol @=> str;
    axiom[0] => str.symbol;
    str @=> Symbol tail;
    for (1 => int i; i < axiom.cap(); i++) {
        add(tail, axiom[i]) @=> tail;
    }
}
    
// 置換規則の実装
fun void next() {
    int s;
    for (str @=> Symbol @ p; p != null; p.next @=> p) {
        p.symbol => s;
        if (s == 0) {
            2 => p.symbol;
            add(add(p, 1), 3) @=> p;
        } else if (s == 1) {
            0 => p.symbol;
        } else if (s == 2) {
            // do nothing
        } else if (s == 3) {
            4 => p.symbol;
            add(p, 6) @=> p;
        } else if (s == 4) {
            1 => p.symbol;
            add(p, 5) @=> p;
        } else if (s == 5) {
            3 => p.symbol;
        } else if (s == 6) {
            // do nothing
        }
    }
}

// 文字列の解釈の実装
fun void play() {
    [0, 2, 4, 5, 7, 9, 11] @=> int scale[];
    for (str @=> Symbol @ p; p != null; p.next @=> p) {
        60 + scale[p.symbol] => Std.mtof => karp.freq;
        1 => karp.pluck;
        T => now;
    }
    T => now;
}

fun Symbol add(Symbol pre, int s) {
    Symbol ns;
    s => ns.symbol;
    pre.next @=> ns.next;
    ns @=> pre.next;
    return ns;
}

StifKarpはSTKのユニットジェネレータで、撥弦楽器の音をシミュレートする。

録音したもの。
Download

自己相似的なメロディ。