ならば

音とかで遊んでいたログ

関数

関数は「fun 返り値の型 名前」で定義する。

fun int sqr(int x) { return x*x; }

オーバーロードも可能。なのに何故かStdでは rand(), randf() と rand2(int min, int max), rand2f(float min, float max) がわざわざ別名で実装されている。開発者が使う気ないのか?
引数に配列などのオブジェクトを渡すこともできる。例えば前日のseqプレイヤーの部分は関数として以下のように書き直せる。

fun void player(int seq[][], float unitTime)
{
    for(0 => int i; i < seq.cap(); i++)
    {
        seq[i][0] => Std.mtof => s.freq;
        (unitTime * seq[i][1])::second => now;
    }
}

再帰関数も書ける。再帰的処理といえばハノイの塔が有名で、exampleにも既に二種類ある(10月8日追記:オンラインのexamplesには四種類ある)けど別に自分で書いた。今回は波形に三角波を使ってみた。

TriOsc s => Pan2 p => dac;

fun void move(int height, int from, int to)
{
    // fromポールからディスクを取る
    60 - height * 2 => Std.mtof => s.freq;
    from - 2 => p.pan;
    100::ms => now;
    // toポールにディスクを置く
    60 + height * 2 => Std.mtof => s.freq;
    to - 2 => p.pan;
    100::ms => now;
}

fun void hanoi(int height, int from, int to, int other)
{
    if (height > 0) {
        hanoi(height - 1, from, other, to);
        move(height, from, to);
        hanoi(height - 1, other, to, from);
    }
}

hanoi(10, 1, 3, 2);

ディスクを取るときと置くときに音が鳴る。音高はディスクの高さと関係していて、ディスクを取るときは基準音(中央のド)より低く、置くときは高くした。音の位置(左、中央、右)はポールの位置に対応している。ポールは三本あって左側から1,2,3に番号付けしたので、ポール番号から2を引けば-1,0,1の数になる。これをpanにセットした。
基準音や「* 2」の部分を色々変えると雰囲気が結構変わる。少しは楽しそうな領域に近づけたかも。