YAMAGUCHI::weblog

土足で窓から失礼いたします。今日からあなたの息子になります。 当年とって92歳、下町の発明王、エジソンです。

オーディオプログラミング言語 ChucKをいじる

動機

ふとこんなエントリをみたら自分でもいじってみたくなってしまいました。ちょっと前にSuperColliderを一瞬だけ触って使わなかった記憶があるため、こちらもそうならないようにメモに残しておこうと思いました。

参考リンク

Princeton大学の方が作ってるみたいですね。

ここでEmacsのchuck-modeを配布しています。

チュートリアル

ここでざざっと説明を読んで下のサンプルコードを眺めるのがいいと思います。(サンプルコードはバイナリが入っているアーカイブに同梱されている)以下でチュートリアルを読んでの個人的なメモを書いておきます。

基本文法

データ型

基本的には一般的なプログラミング言語にあるような感じのプリミティブ型(int, floatなど)。ただChucKはオーディオプログラミング言語なので、波(音波)や時間に関係する型があらかじめ用意されています。以下がその4つ。

  • dur(時間型)
  • time(時刻型)
  • complex(複素数型)
  • polar(極座標型)
配列(array)

配列は静的配列はもちろん多重配列や動的配列や辞書にも対応しています。

int array_1[3] // 3個の要素を持つ配列
[2.0, 3.0, 4.0] => float array_2[] // 初期化をした
[[1,0, 2.0, 3.0], [4.0, 5.0]] => float array_3[][] // 多重配列は長さが違っていてもよい
3 => array_1["hoge"] // 辞書も対応。既存の配列に追加可能
演算子

演算子はChucK operator(後述)を除いては他のプログラミング言語と同様。+,-,*,/,%やビット演算子、論理演算子さらに後置の++,--がある。型キャストだけ若干違うくらい。

4.8 $ int => int foo // foo == 4
=> (ChucK演算子)

ChucKらしい演算子はこのChucK演算子だと思います。ChucK演算子は文脈によって意味が違ってくるのですが、例としてあげられているのは

  • 値の代入
  • 発生器の連結

なんかがあるかと思います。値の代入の場合は一般的なプログラミング言語の=演算子みたいに、その前に算術演算子(+,-,*,/,%)を置いて省略的な書き方ができます。また面白いのは変数への参照を与える@=>演算子

int ary[2][2];
2 => ary[0][1];
ary[0] @=> int ary1[];
<<<ary1[1]>>>; // 2 :(int)
3 => ary1[1];
<<<ary[0][1]>>>; // 3 :(int)

C言語のポインタのように参照を操作することで実体を変更することができます。

制御構文

if/else, do/while, do/until, for, break/continueがあります。

時間制御

データ型でも書いたとおり時刻型と時間型があって、一般的に考えられる演算は可能です。ここで大事なのはnowというキーワード。このnowというキーワードが名前の通り「(スクリプト実行時からの)現在時刻」を保持していて、これに対して操作を行うことで予約みたいな操作ができる。

関数

関数の宣言もCと同様の形。ただし、宣言するときに"fun"というキーワードを置く必要がある。

// define function call 'funk'
fun void funk( int arg )
{
    // insert code here
}

// define function 'addOne'
fun int addOne(int x)
{
    // result
    return x + 1;
}

あとオーバーロードもできます。すばらしい。

コンカレンシーとShred

ChucKでは1つのスクリプト(プロセス)で1つのD/Aを占有する感じで書きます。そのため、複数の音を鳴らしたいときは

$ chuck foo.ck bar.ck buz.ck

のように同時に読み込ませてあげることで、ChucK側で同期をとってくれます。またChucKにはいわゆるスレッドの様な機能を果たすShredというものがあります。1つのプロセスは必ず1つのShredを走らせているのですが、そこから子Shredを発生させたいときはsporkというキーワードを使います。
さらにMachine.add()を使うと、プロセスから他のChucKプログラムを走らせることができます。この場合はsporkでShredを作る場合と違って、別のプロセスが立ち上がり、親子関係ではなくなります。

// add
Machine.add( "foo.ck" ) => int id;
// remove shred with id
Machine.remove( id );
// add
Machine.add( "boo.ck" ) => id
// replace shred with "bar.ck"
Machine.replace( id, "bar.ck" )
クラスとオブジェクト

ChucKではC++, Javaと似たようなOOPの特徴を持っています。

  • ポリモーフィズム
  • すべての変数は参照

などです。Javaと違う点として注意すべきはやはり参照オブジェクトです。(@を使うやつ)これはC/C++のポインタと同様実体それ自身ではありません。
メンバやメソッドはstaticメンバ/メソッドも可能。継承はextendsキーワードで。多重継承はサポートされてません。
また現時点で注意すべき点は

  • privete, protected, publicの実装が未完全
  • コンストラクタはない

後者に関してはクラス定義の中に直接コンストラクタで書くようなコードを書くことで対処しています。JavaScriptみたいですね。以上で基本的な文法はおしまいです。

おまけ

講義
  • ChucK: A Computer Music Programming Language


開発者のGe WangによるStanford大学の大学院での講義が公開されています。英語が分かる方ならこれを見ればポイントは押さえられます。
こういう講義があるのはうらやましいですね。日本の大学(特に国立大学)がもっとこういう講義を行ってもいいんじゃないかと思うのですが。

まとめ

ChucKのざっくりとしたまとめからProcessingとの連携まで踏み込んだエントリです。わかりやすい。