yoppa.org


Blog

SuperCollider自主練 – 基本編

ここしばらく、openFrameworksやProcessingを主につかっているうちに、音から遠ざかってしまってる。もともとは、コンピュータ音楽が専門なのに…。ということで、この夏もういちど音と向きあおうと思いたち、SuperColliderに再入門してみようかと思い立つ。教材は、MIT Pressから刊行された”The SuperCollider Book“。この本を読みながら、SCの基本をもういちどおさらいしてみたい。

まずは、最初の章から順番に。

Chapter 1: Beginner’s Tutorial

1.1 Hello World

まずは、基本から。

初心者向けチュートリアルといいながら、いきなり冒頭でオシレータ、LFO、エンベロープなどの音響合成の基礎知識を前提としていると宣言される。この突き放し感がSCらしい感じ。1章のねらいは言語の成り立ちを詳細に学ぶというよりは、実際に音のでるサンプルを通してSCで出来ることを体験していこうという主眼のよう。

まずは、Hello Worldと、サーバーのブート:

そして、実際に音の出るサンプル。シンプルだけど出てくる音はなかなか面白い。

ここで簡単にプログラムの実行方法や停止のやりかた、ボリュームの上げ下げなどの基本操作の解説と、エラーメッセージの読み方など。さらにもう一つ音の出るサンプル。

ここで、Dust.arの仲の12と15や、LFNoise1の3と4の数値をいろいろ変化させてみろ、との指示。こうやって実際に数値を変えてすぐに実践できるのがSCの良さの一つかもしれない。

ここまでで、オーディオシグナル”.ar”の意味や関数”{…}“の意味などの説明は一切ないが、まあまずは体験しながらということなのだろう。

次にいままでは1行で書いていたプログラムを機能ごとに改行してインデントした、加算合成のサンプル。こうやって書くとわかりやすい。

このサンプルでは、新たに関数の中での変数(var)の使用や、引数(arg)なども出てきているが、ここでもあまり具体的な解説はなし。「この記述がギリシャ語のように感じるかもしれないが、おいおい学んでいきましょう」という感じ。

1.2 メッセージと引数

メッセージと引数という概念の紹介。

メッセージとは、複数のコンマで区切られたパラメータのリストをもった小文字で始まる命令。

メッセージは、大文字で始まる言葉(つまりクラスのことか?)の後に接続されることもある。

他のOOP言語に慣れていると、逆にオブジェクトに対するメッセージだけでなくメッセージ単体で使用できることの方が奇異に感じるが、ここらへんはSmallTalkから来ているものなのだろうか?

メッセージの例としてランダムな値の生成について。単純な乱数と指数範囲での乱数exprandの紹介など。引数にfloat()小数点以下の数)を入れると出力もfloatになり、整数(int)だと出力結果もintとなるなど。

例えば、10から100のランダムの数値を使用する場合でも、音程をランダムに生成する場合にはexprandomを使うべきという話。なぜなら我々の耳は音程を指数的に知覚しているから。こうした乱数の説明も、音を基本にしているところがSC的。

ランダムシードを指定して、常に同じランダム数列を得る方法もある。これは知らなかった…

そのあとは様々なメッセージの紹介。くりかえし、小数点の桁の切り捨て、ソートなど。

こういったメッセージを必要に応じてすぐに使用できるようになると、気の効いたプログラムがつくれそう。

1.3 ネスティング(Nesting)

ネスティングについて。SCではあるメッセージの出力結果を、そのまま別のメッセージの引数として使用できる。それをさらに別のメッセージの引数にしていってというように、どんどんネストしていけるという話。

実例がわかり易い。

こうしたネストの使用を音響合成の例でみてみる。

様々なユニットジェネレータがネストされている。

1.4 レシーバー.メッセージ、コメント (Receiver.message, Comments)

1.3の例では、大文字で始まる命令にメッセージがドット(.)で接続されていた。SinOsc.ar、LFNoise1.ar など。これらはユニットジェネレータ(UGens)と呼ばれ、デジタルオーディオに特化した数値のストリームを出力する。これらはより広範な定義でいうと「レシーバー(Receiver)」と呼ばれるもの。レシーバーは、引数をもったメッセージからの指令によって動作する。

例えば、

これは「-100から100の範囲でランダムな値を生成するタイプ1の低周波のノイズ生成器でノイズを1秒に10個生成する」という意味になる。

数(Numbers)、関数(functions)、配列(arrays)、文字列(strings)もメッセージをドットで継いで何をするか伝えることができる。

などなど。

ところで、ちょっと前のサンプルで出てきた、rand(100) と 100.rand はどう違うのか? 結論からいうと両者は同じ。rand(100) は関数的な表記法。100.rand はメッセージによる表記になる。どちらの記述方法を使うかはケースバイケース。

メッセージを利用した書式は、ドットで継いでいくことでネストを実現できる。

つづく(たぶん…)