Csound


目次
1)Csoundの発展史
2)マックへのftp
3)UNIXマシンへのftp
4)Csoundの特徴
5)Csoundを使う
6)ディレクトリの設定
7)取り敢えず音を出す
8)サウンドファイルのデータ型
9)マニュアルの使い方 
10)マニュアルの付録
11)プログラムのプロセス
12)オーケストラファイル1
13)ヘッダ 
14)楽器のフォーマット
15)変数のアップデート
16)ピッチの指定
17)ヴィブラート
18)オーケストラファイル2
19)スコアファイルのフォーマット
20)f 文とGENサブルーティン
21)GEN09, GEN10, GEN19
22)i 文
23)e ステートメント
24)t ステートメント 
25)a文
26)s文
27)自作のCモジュールを加える
28)プログラミングの練習
29)ノイズジェネレータ
30)ノイズ楽器を作る
31)フィルタ
32)サウンドファイルを読む
33)フィルタ楽器を作る
34)リヴァーブとグローバル変数
35)ノイズ→フィルタ→リヴァーブ
36)アルゴリズミックコンポジション言語としてのPerl
37) 例題解説  

以下では、コンピュータミュージックの「標準言語」の一つであるCsoundの使い方を概説する。Csoundは、50年代以降のコンピュータ音楽の発展の歴史を受け継ぐメインストリームでもあり、MIT MediaLabの Barry Vercoe教授によって開発された。

1)Csoundの発展史
コンピュータミュージック言語の起源は、ベル研究所のマックス・マシューズらによって50年代後半に開発された音響生成用のプログラムにある。これらは開発年代順にそれぞれMUSIC 1 からMUSIC 5と名付けられたが、FORTRANで書かれたMUSIC 5以外は特定のマシンに依存していたた?゚今日では忘れ去られている。ベル研究所で開発されたこれらの初期のプログラムの内、60年代初頭に開発されたMUSIC 4は、スタンフォード大学のチャウニング(John Chowning)のグループと、プリンストン大学のウインハム(Godfrey Winham)とホウ(Hubert Howe)のグループに受け継がれ、それぞれ独立に発展の歴史を歩む事になる。スタンフォードでの発展史は、拙著「コンピュータミュージック」(オーム社、1994)でのチャウニングへのインタヴィユーなどを参照して頂く事にして、本章では少しの間プリンストンでの流れを追ってみる。プリンストンで受け継がれたプログラムはMUSIC 4Bへと発展するが、これはさらにプリンストンから移ったMITのヴァーコウ(Barry Vercoe)によって1968年にMUSIC 360へと発展する。これは、その名が示す様にIBM360上で走らせるプログラムとして開発された。ヴァーコウはこれをPDPー11上で走るMUSIC 11へと1973年に展開したが、現在のヴァージョンはC言語で書かれているので多様なマシン上で走らせる事ができる。これが本章で紹介するCsoundである。Csoundは完成された言語ではあるが、コンピュータと同様に常に発展しつつある。1991ヴァージョンにはフェイズヴォコーダとフォーマント合成が加えられた。1992ヴァージョンにはMIDIコンヴァータとコントロールユニットが加えられたので、Csoundは外側のMIDIキーボードからも走らす事ができる。従って、スピードの早いコンピュータ上では、センサーなどからのコントロールによってリアルタイムのソフトウエア合成も可能である。

2)マックへのftp
Csoundアプリケーションは、MITのMediaLabからインターネットを介して自分のコンピュータにftpする事ができる。以下ではマックを使う場合の手順を示す。
1)Fetchをクリックして起動する。
2)画面が現われたら、Host に Cecelia.media.mit.edu をタイプする
3)User ID にanonymousを、Passwordとして自分のe-mailアドレスをタイプする
4)pubをダブルクリックする
ここでftpで得る事のできるファイルのリストを見ることができる。これは常にアップデートされる。Csoundを自分のコンピュータに転送する?ノは、
5)Csound.sit.hqx をダブルクリックする。Automatic Mode を選択しておく
Passwordには何を使っても良いが、慣習として自分のe-mail addressをタイプすると良い。拡張子.hqxはCsoundのマックヴァージョンである事を示すので、Csound.hqxをftpする訳である。数秒後には、Csoundアプリケーションとマニュアルなどのドキュメント類を含めて、必要なすべ?トのファイルを手に入れる事ができているはずである。なお、ユーザーが使えるブレティンボードはcsound-BB@media-lab.media.mit.eduである。ここへの投稿はすべてのユーザーにブロードキャストされる。アドミニストレーションに関する質問はcsound-request@media-lab.media.mit.eduへ、バグのレポートは、csound@media-lab.media.mit.eduへ、それぞれ送る事ができる。

3)UNIXマシンへのftp
UNIXのマシンでftpを行うには、シェルのプロンプトの後で以下のコマンドをタイプすれば良い。
1)ftp Cecelia.media.mit.edu
2)Name: anonymous
3)Password: iwatake@sfc.keio.ac.jp
4)cd pub
5)ls -l
ここでftpで得る事のできるファイルのリストを見ることができる。Csoundを自分のコンピュータに転送するには、
6)binary
7)get Csound.tar.Z
とする。ファイルが転送され終わるとプロンプトが現われるので、ここでftpから出る。
8)quit
次に、ファイルを以下の手順でアンコンプレスする。
9)uncompress filename.tar.Z
10)tar xvf filename.tar
後は適当なディレクトリに転送されたCsoundのファイルを置けば良い。

4)Csoundの特徴
Csoundでは、音響的なイベントの単位は音符(note)、音符の集合はスコア、音響生成のアルゴリズムは楽器(instrument)、楽器の集合はオーケストラと呼ばれる。つまりオーケストラとスコアのアナロジーが採用されているので、プログラムの構造が概念的に分かりやすい。しかしだからといって、Csoundで作られる作品が伝統的なオーケストラの発想を踏襲したものである訳ではなく、作者のアイディアしだいで全くアヴァンギャルドな音響を作り出す事ができる。Csoundではプログラムのフォーマットが明快に定義されているので、ユーザはあたかもパッチコードでアナログシンセサイザのユニットを繋ぐ感覚でプログラミングができる。またプログラムで使われるユニット・ジェネレータを含めシステム全体がC言語で書かれているのでコンピュータ間での移植性に優れ、最近ではコンピュータミュージックの標準言語と呼べる状況になって来?トいる。しかもユニット・ジェネレータがプログラミングの単位なので、直接C言語を使ってプログラミングをしないで済む点ではミュージシャン向きであり、MIDIとの接続も可能である。もちろん市販のどんなシンセサイザよりもパワフルで、スピードの早いプロセッサを搭載したコンピュータ上ではリアルタイムで走る事も魅力的である。という訳なので、コンピュータとCsoundがあれば他の器材はほとんど必要なくなってしまう。既に多様な音響合成のアルゴリズムが使えるので、今後は日本でもCsoundのユーザが増えて行く事だろう。この様にCsoundは非常にパワフルな道具であるが、本章では基礎的なほんの一部分しか紹介する事はできない。上達のコツは、実際に使ってみる事である。

5)Csoundを使う
CsoundはCで書かれているので、DECのRISCマシン、SUN、SGIのIndigo、NeXT、HP、Macintosh等のUNIX または Cが走るマシンにインストールできる。本章では主にマックの場合について説明するが、UNIX マシンを使う手順も並行して説明する。とは言っても両者の環境に大差は無く、UNIXではシェルでコマンドラインを入力する部分が、マックではダイアログのウインドウでボタンをクリックする様になっているだけである。?痰ヲば、オーケストラとスコアからサウンドファイルを作る場合のUNIXコマンドラインは、
csound -oサウンドファイル名.snd オーケストラ名.orc スコア名.sco
である。-oフラッグは、これが目的のサウンドファイルである事を示す。音を聞くには、
sndplay サウンドファイル名.snd
で良い。サウンドファイルが/tmpにある場合には、
sndplay /tmp/test.snd
などとなる。NeXTが使える場合には、SoundWorksなどのアプリケーションを使っても良い。マックでCsoundのプログラムを行う場合には、Csoundアプリケーションの他に、ファイルの作成用にEZWordなどの適当なエディタが必要である。出力サウンドファイルのフォーマットはDigidesignのSound Designer IIであるが、音を聞くにはSoundAppアプリケーションが使える。また自分でモジュールをC言語で書く場合には、マック用のCコンパイラLightspeedCが必要になる。なお、マニュアルはMicrosoftのWordで書かれているので、マニュアルを読むにはこのアプリケーシ??唐ェ必要である。

6)ディレクトリの設定
マックでは、Csoundアプリケーションのアイコンをダブルクリックするとファイル選択ダイアローグが現われる。ここには、オーケストラ、スコア、出力ファイル、そしてオプションとしてMIDIと出力リスティングのファイルを選択するコラムがある。出力ファイル名を例外として、他のファイルは選択ボタンをクリックするだけで選択ダイアローグが現われるので、例えばオーケストラのselectボタンを押し、適当なオーケストラファイルを選択すると、スコアファイルもアウトプットファイルも自動的に作られる。通常はオーケストラとスコアは拡張子だけが違うので(オーケストラは".orc" 、スコアは".sco"、そしてサウンドは".snd")、どちらかを選べば他は自動的に決まる。オプションダイアログで?Aウトプットファイルが指定されれば、".snd"として自動的に作られる。Csoundはこれらのファイルをすべて単一のSFDirディレクトリに置く。マックではSFDirボタンをクリックしてこのディレクトリをユーザが適当に選択するので、あらかじめ適当な所にCsound用のディレクトリを作?チておくと良い。一度ディレクトリを設定した後でSaveボタンを押しておけば、次回からは自動的にこのディレクトリが選択される。UNIXでは?Aサウンドファイルのディレクトリは、例えばsetenv SFDIR /tmpの様にシェル環境変数で指定する。
7)取り敢えず音を出してみる

設定が終わった後で選択ダイアローグのOKボタンをクリックすると、コンソールが現われ、計算が実行され、その結果が次々にコンソールに示される。後で述べるファンクションテーブルが使われていれば波形が示される。エラーがあればコンソールにメッセージが現われるが、なければサウンドファイルのサイズなどがコンソールにプリントされて計算は終了する。音を聞くには、まずコンソールをクリックしてCsoundから抜け出る。その後でSoundappを起動し、目的のサウンドファイルを選択すると合成された音を聞くことができる。UNIXの場合には、引き続きシェルでsndplayコマンドを使う。

8)サウンドファイルのフォーマット
CsoundのメニューからOutput Sample Formatを選ぶと、サウンドファイルのフォーマットを選ぶ事ができる。前述の様にサウンドファイルのフォーマットはDigidesign のSound Designer IIであるが、コマンドラインで-Aオプションを指定すれば、AIFF (Audio Interchange File Format)のフォーマットを選ぶ事もできる。サンプルフォーマットは8-bit 整数型から32-bit fフロート型までを選択できる。no header checkboxがチェックされると、サウンドファイルからヘッダが取り除かれデータだけが出力される。blocksizeは出力サンプルファイルに書き込まれるサ?塔vル数である。データのフォーマットはディフォールトで16ビット整数型なので、データの値は-32768~32767の整数として表現される。従って、データサンプルに与える事のできる最大値は32767であり、この値を超えるとエラーになる。次に述べるオシレータのアンプとして与えるデータは、この16ビット整数フォーマットでの数値である。この場合、例えばアンプの値32000は90dbに相?魔キる。関数ampdb(x) を使うとデシベル値xに対応するアンプの値を知る事ができる。

9)マニュアルの使い方
Microsoft Wordで書かれたCsoundのマニュアルは125ページの膨大なものであるが、それ自体が丁寧なCsoundのテキストになっているので、関?Sのあるユーザには根気良く読むことをお薦めしたい。例えばオーケストラで使われる事の多い信号ジェネレータoscilについて調べて見る。マニュアルの目次またはコマンドFでoscilを探すと、22ページに記述がある事が分かるので、EditメニューからGo Toを選び Page Numberに22を?^イプする。すると、 SIGNAL GENERATORS の章にある以下の様なoscil を含んだ項目のフォーマットと簡単な説明が現われ、INITIALIZATIONとPERFORMANCEのセクションへと続く。以下ではoscilに関係する項目だけをピックアップして示す。
     kr oscil kamp, kcps, ifn[, iphs]
     ar oscil xamp, xcps, ifn[, iphs]
Table ifn is incrementally sampled modulo the table length and the value obtained is multiplied by amp. INITIALIZATION 以下は省略する。
マニュアルを読めば、oscilはコントロールまたはオーディオの両方の信号を生成するオシレータである事が分かる。例えばオーディオ信号の?Iシレータは、xcpsの値に対応する位相の増分を使って指定された関数ifnをスキャンし、それらの値をxampでスケーリングして、xcpsHzの周期信号として出力する。この時、オーディオ信号を生成するオシレータへのxampとxcpsのインプットに関しては、振幅変調と周波数変調ができる。FM用のオシレータとしてはfoscilを使うこともできるので、マニュアルを参照すると良い。さてここでifn はファンクションテーブル番号であるが、これはoscilでは特定の波形を参照する番号として使われる。波形番号はストアされた関数テーブルを指すので、前もって関数テーブ?汲ノ何らかの波形をストアしておかなければならない。この点に関してはスコアのセクションで説明する。またiphs はオプショナルの初期位相で、ゼロから1までの1周期のフラクションで表わす。ディフォールトはゼロである。従って、
a1 oscil 10000,440,1
は、関数テーブル番号1にストアされている波形を使い、アンプ10000、周波数440Hzのオーディオ信号を生成する。持続時間は後で述べるスコアで指定される。

10)マニュアルの付録
現在のCsoundマニュアルにはAppendix 1~9の付録が付いている。これらは、マニュアルでは扱えない個別のトピックに関する非常に優れたイントロダクションになっているので是非目?ハして欲しい。ここでは詳細を扱う事はできないので、これらの付録の内容を簡単に紹介する。
Appendix 1は、C言語によるスコア操作/生成プログラムであるCSCOREのマニュアルである。
Appendix 2は、R.C. Boulangerによる楽器デザインのチュートリアルで、Csoundによる音響生成アルゴリズムの13の例題が難易度に従って整理されている。これらの例題はtutorfilesサブディレクトリにもあるので、すぐに音を出す事ができる様になっている。内容はエンヴェロープ、コーラス効果、ヴィブラートなどから、GENファンクション、サウンドファイルの操作、フィルタへと進み、最後の例題ではスペクトラル・フ?❺[ジョンが扱われる。ここではフィジカル・モデリングによって生成された弾かれた弦の音がFM音へ変容し、さらにFOF合成によってヴォーカルな音へと変化する。
Appendix 3は、J.M. Clarkerによる FOF合成 チュートリアルである。FOF合成はグラニュラー合成の特別な形であり、オーヴァーラップするグレインの連続によって音を生成する。FOFジェネレータは単一のフォーマントを生成するので、4個以上組み合わせれば音声の模倣ができる。??ケは、新しいグレインが生成されるスピードなので、基音が非常に低い場合にはグレインが分離して聞こえる。この場合には基音はピッチで?ヘなくパルスのスピードになる。FOFを使うと、ピッチとパルスの間の移動、つまり音色とグラニュラーテクスチュアの間の移動が聞こえる。
Appendix 4のHETROは、adsynユニットジェネレータのためのヘテロダインフィルタ分析モジュールである。adsynは、オシレータバンクまたは?tェイズヴォコーダ分析の出力の加算合成を行う。この場合、任意の数のサイン波を個別にコントロールして加えるので、時間的に変化する複?Gな音色を合成できる。
Appendix 5は、線形予測コーディングのプログラムである。 lpcanalはlpジェネレータのための線形予測コーディング(lpc)分析モジュールで、サウンドファイル入力に対して、線形予測コーディングとピッチトラッキング分析の両方を行い、再合成のためのコントロール情報のフレームを時系列で生成する。以下は題目を紹介するに止める。
Appendix 6は、Dan EllisによるフェイズヴォコーダPvAnalプログラムである。
Appendix 7は、W. GardnerによるマックでのCsound の使い方の説明である。
Appendix 8は、新しいCsoundのモジュールを自分で作る方法の説明である。
Appendix 9は、ここにはCsoundで使われるすべての信号生成関数、変換関数、コントロール関数、サウンド入出力関数、信号表示関数などのフォーマットのリストがあるので、これらを使うときに役に立つクイックレファランスになる。

11)プログラムの仕組み
Csoundでは、オーケストラとスコアの2つの基本ファイルによって構成される。プログラムで使われる音響生成用のソフトウエア楽器の定義をまとめたファイルがオーケストラである。楽器は信号を生成/変換するモジュールの集合で、生成された信号はシンボルで表現されモジュール間でパッチできる。一方のスコアでは、それぞれの楽器の具体的な演奏情報と演奏時刻を指定する。
  !             <オーケストラとスコアの概念図>
プログラムは、以下の手順で実行される。まずスコアファイルが時間順にソートされるる。この段階でエラーがあればコンソールにメッセージが現われる。次にオーケストラを機械語に翻訳しロードする。翻訳が開始されるとコンソールにそれぞれの楽器番号が現われ、エラーがあればメッセージが現われる。その後で波形テーブルを生成し、スコアの演奏を開始する。演奏の情報は以下の様な形でコンソールに現われる。
B 4.000 .. 6.000 T 3.000 TT 3.000 M 7929. 7929.
Bの後の2つの数はスコアでのビート数であるが、これが表示されている時には、対応する区間で音響生成が行われている事を示す。Tの後の数値はこの区間の実際の秒数で、TTの後はスコアの先頭からの合計秒数である。Mの後の数値はその区間での最大のアンプの値で、最後の数値は?ナ大のアンプ値をチャンネル毎に分離して表示した値である。 もしもマシンのスピードが十分に早ければ、音響が生成されると同時にその音をリアルタイムで聞く事ができる。

12)オーケストラ・ファイル1
では実際にオーケストラ・ファイル(以後オーケストラと呼ぶ)の中味を見てみよう。
Csound/tutorfilesの下には、R.C. Boulangerによ?チて書かれた例題があるので、例えばtoot1.orcを開けてみると以下の様になっている。
; toot1.orc
sr = 16000
kr = 1000
ksmps = 16
nchnls = 1
instr 1
a1 oscil 10000,440,1
out a1
endin
上の例で、セミコロンで始まる行はコメントである。コメントに続く4行は、サンプリングレイトなどのグローバル変数を宣言する部分でヘッダと呼ぶ。instr 1からendinまでが、プログラムで使われるソフトウエア楽器(以後楽器と呼ぶ)を定義する部分で、楽器ブロックと呼ぶ。この例では楽器は1個しかないが、いくつあっても良い。
一般にオーケストラは、ヘッダと楽器ブロックの2つの部分から構成される。まずオーケストラのヘッダでグローバル変数を宣言し、続いてソフトウエア楽器を定義する。グローバル変数はすべての楽器で使われるが、楽器内部で宣言されるローカル変数は、その楽器内部だけで参照される。単一の楽器のまとまりを示すためには、上の様に instr nとendinのステートメントのペアで楽器プログラムの中味を囲む。instrの次にはスペースを入れ、その次のnには楽器の番号を示す数値を書く。a1 oscil 10000,440,1は、信号a1が、アンプ10000、周波数440Hz、波形番号1のオーディオ信号である事を示している。out a1は、この信号をチャンネル1から出力する。楽器プログラムの詳細は、以下で順を追って調べる事にする。

13)ヘッダ 
通常のヘッダで宣言される変数の種類は、以下の通りである。
sr は、サンプリングレイトを指定する。ディフォールトは10000である。
kr は、コントロールレイトを指定する。ディフォールトは1000である。
ksmps は、コントロール周期のサンプル数を指定する。ksmps の値は、sr/krに等しくなければならない。ディフォールトは10である。
nchnls は、オーディオ出力チャンネル数を指定する。ディフォールトは1である。
その他のグローバル変数も、必要であれば楽器ステートメントの前にヘッダで宣言する。 一般に、エンヴェロープなどのコントロール信号の変化はオーディオ信号の変化に比べてゆっくりしているので、コントロール信号には実際に出力されるオーディオ信号のサンプリングレイトほどの分解能は必要無い。従って、コントロールにはオーディオとは別な信号を使う事によって波形の計算を早くできる。そのためにコントロール周期を設定する訳である。

14)楽器のフォーマット
楽器のブロックのフォーマットは、
instr n
<楽器のプログラム >
endin
である。
instr は楽器のブロックの先頭を定義する。この時に、nは正の整数で楽器番号を指定する。endin は楽器のブロックの終了を定義する。複数?フ楽器を使う場合には、以下の様に楽器のプログラムをinstr nと endinで囲み、これらを複数個作れば良い。
,,,,,,,,,
instr 17
 <instr 17のプログラム >
endin
instr 18
  <instr 18のプログラム >
endin
,,,,,,,,,,,
オーケストラに含まれる楽器の数も順序も任意であるが、ネストする事はできない。
instr nとendinで囲まれた楽器プログラムは、ローカル変数の設定、論理の流れ、信号生成のサブルーティン、オーディオ信号の入出力などをコントロールする文よりなる。ローカル変数は、p, i, k, aの文字で始まる。pはパラメータフィールドの番号を示すために使われる。その他の文字?フ使い方は以下で説明する。プログラムのステートメント(以後文と呼ぶ)で使われるフォーマットは以下の通りである。
label: result opcode argument1, argument2, ... ; comments
labelはオプショナルでgo-to操作のターゲットになるが、あまり使われる事はなくその有無にかかわらずステートメントには影響を与えない。通常のプログラムで使われる部分は result以下のステートメントで、resultの先頭文字がiの場合は音符信号、kの場合はコントロール信号、aの場合はオーディオ信号である事を表わす。opcode以下の引き数の意味はopcodeに依存する。

15)変数の初期化とアップデート
楽器で使われる出力信号には4種類のレイトがあり、以下の様にそれぞれ初期化とアップデートの方法が異なる。
1)オーケストラの初期化の時に1回だけ計算されるヘッダの変数
2)I- 変数:それぞれの音符の開始毎にアップデートされる変数
3)K-変数:コントロールループ毎アップデートされるコントロール信号
4)A-変数:サンプル毎にアップデートされるオーディオ信号
従ってI- 変数は音符のピッチやデュレイションの指定に、K-変数は音符の持続期間中にゆっくり動くヴィブラートなどのパラメータの指定に?L用である。
A-変数のコントロール区間はサンプリングレイトそのものなので最も分解能が高く、オーディオ信号に使われる。ここで言う「音符」は、単一のデュレイションで指定される音響的なイヴェントのまとまりの意味である。

16)ピッチの指定と変換
ピッチと周波数に関するデータはpch, oct, cpsの3種類のフォーマットで表わされる。cpsは周波数の値であるが、pchとoctは例えば8.6の様な数値であり、小数点前の整数はオク?^ーヴを、小数点以下のフラクションはピッチをそれぞれ表わす。オクターヴの対応関係は、いずれも8 → 中央のC, 9→中央のCのオクターヴ?繧フC,,,である。小数点以下のフラクションは、pchでは平均律のピッチクラスを表わし、対応関係は.00 → C, .01 → C#, .02 → D,,,, .11 → Bである。octのフラクションは、実際のオクターヴに対する割合である。従って、440Hzのピッチは440 (cps),8.09 (pch), 8.75 (oct), 7.21 (pch)などで表わされる。平均律ピッチからの微細なずれを指定するには、小数点以下の数値を増やせば良い。ピッチのフォーマットを変換する関数には以下の5種類があり、関数名の後半のフォーマットを前半のフォーマットにそれぞれ変換する。例えば、
octpch(pch)は
pchフォーマットをoctフォーマットに、pchoct(oct)はoctフォーマットをpchフォーマットに変換する。
同様に
cpspch(pch)はpchをcpsに、
octcps(cps)は、cpsをoctに、
cpsoct(oct)は、octをcpsに変換する。
これらの関数では、変換する数値を直接指定する代りにパラメータを使ってcpspch(p5)などとし、ピッチをスコアからコントロールする事もできる。

17)ヴィブラート
ファンクションテーブル1にサイン波がストアされている場合、ヴィブラートは以下のようにすれば作る事ができる。
k1 oscil 10, 5, 1 ; 5 cps vibrato
a1 oscil 5000, 440 + k1, 1 ; around A440 ±10 cps
この場合には、k1は振幅の値が最大10、最小-10の間で変化する周波数5Hzのサブオーディオ信号になるが、2行目のa1のxcpsは440 + k1になっているので、±10Hzの周波数幅で変化する5Hzのスピードのヴィブラートになる。ヴィブラートの幅が小さい場合にはこれで良いが、実際には?sッチの知覚は対数的なので、中心ピッチより高い方向へのピッチの揺れ幅は下方向への揺れ幅よりも小さく聞こえる。一般に、ヴィブラート?ネどのピッチの操作はピッチクラスやcpsではなく、ピッチの幅をオクターヴに対する小数のフラクションで表わし、上下の揺れの音程を同じにすると良い。そのために以下の様にピッチ変換関数cpsoctを使う。
instr 1
ioct = octpch(p5)
kamp line 0, p3, 10000
kvib oscil 1/120, cpspch(p5)/50, 1
asig oscil kamp, cpsoct(ioct+kvib), 1
out asig
endin

18)オーケストラファイル2
次に、以下のtoot3.orcファイルをマニュアルを見ながら解読してみよう。ヘッダについては前の例と同様なので省略する。
instr 3 ; p3=duration of note
k1 linen p4, p6, p3, p7 ; p4=amp
a1 oscil k1, p5, 1 ; p5=freq
out a1 ; p6=attack time
endin ; p7=release time
ここで、kから始まるシンボルはコントロール信号を表わすので、
a1 oscil k1, p5, 1 ; p5=freq
は、アンプがk1、周波数がp5、波形番号が1のオーディオ信号を生成する。このk1を作るlinenのフォーマットを前例と同様にマニュアルで調?ラると、以下の通りである。
    kr linen kamp, irise, idur, idec
    ar linen xamp, irise, idur, idec
linenは、ゼロからkampの値までをライズし、kampからゼロまでをディケイする直線のエンヴェロープを与える。だたしiriseはライズ秒数、idurは全体の持続秒数、idecはディケイ秒数であり、これらの値がゼロまたはマイナスであればライズのエンヴェロープは適用されない。従って k1 linen p4, p6, p3, p7 は、信号全体の長さをp3秒に設定し、p6秒のライズとp7秒のディケイをp4の振幅に与える事になる。linenのパラメータが数値で指定されずにp4, p6, p3, p7となっている理由は、実際に生成される音毎にパラメータの値を変更したいためである。これらのパラメータフィールドについ?トは、以下のスコア・ファイルの項で説明する。

19)スコアファイルのフォーマット
スコアファイル(以後スコア)は、オーケストラの楽器にタイミングとパラメータ値を指定する。Csoundはスコアを自動的にソートするので、以下で説明する各種のステートメント(以後文)は、時間の順にタイプされる必要はない。もちろん同一の楽器が同時に2つ以上の音を出すこともできる。CscoreやScotなどのハイレベルのスコア生成言語を使う場合にも、最終的にはオーケストラが理解できるスコアのフォーマットに書き下される。スコアのフォーマットは、以下の通りである。
opcode p1 p2 p3 p4... ;comments
文の最初のオプコードは単一のアルファベットで、 f, i, a, t, s, e,の6種類が使われる。 これらの意味は以下で説明する。オプコードとp1の間のスペースまたはタブはオプショナルであるが、パラメータ間はスペースまたはタブで区切る。p1, p2, p3, ... などはパラメータである。これらは浮動小数点の値を持ち、符号はオプショナルである。例えば、中央のCのすぐ上のC#から始まるペンタトニック音階を、0.5秒の長さのサイン音で演奏したい場合、以下の様なスコアを書く。これらの文の意味は、以下で順に説明する。
; a sine wave function table
f1 0 256 10 1
; a pentatonic scale
i 1 0 .5 0. 8.01
i 1 .5 . . 8.03
i 1 1.0 . . 8.06
i 1 1.5 . . 8.08
i 1 2.0 . . 8.10
e
なお、直前の文のパラメータをコピーする場合には、pフィールドにドットをタイプすれば良い。上の例では、p3とp4のパラメータがキャリー?ウれている。

20)f 文とGENサブルーティン
上の例で使われているf文は、関数を描く手続きであるGENサブルーティンを呼び出し、生成された波形にテーブル番号を与えてストアする。フォーマットは以下の通り。
   f # time size GEN# ,,,,
# (p1)はテーブル番号
time(p2)は関数を呼び出す時刻
size(p3)はテーブルに含まれるサンプル数で、2のべき乗を指定する。最大値は224=16777216である。
GEN#(p4)はサブルーティンの種類を示す番号。値がプラスであればテーブルは正規化される。つまり最大値は1にスケールされるが、マイナスであれば正規化されない。
p5以下は、GENサブルーティンによって異なる。
例えば、GEN01は、サウンドファイルのデータをファンクションテーブル(関数表)に変換する。フォーマットは以下の通りである。
   f # time size 1 filcod skiptime format
size(p3)は、サウンドファイルAIFFがならばゼロにする。この場合には、sizeはファイルのサンプル数になり、通常のオシレータからはテー?uルが使えないが、loscil では使える。
filcod(p5)は、ソースのサウンドファイル名。ダブルクオートで囲む。
skiptime(p6) は、サウンドファイルの先頭からスキップする秒数。
format(p7) は、オーディオのデータファイルを以下の様に指定する。
1 - 8-bit signed character 4 - 16-bit short integers
2 - 8-bit A-law bytes 5 - 32-bit long integers
3 - 8-bit U-law bytes 6 - 32-bit floats
formatがゼロであれば、サウンドファイルのフォーマットが指定される。

21)GEN09, GEN10, GEN19
GENルーティンには1から17まで17種類ある。詳細はマニュアルを参照して頂く事にして、ここではサイン波を合成して複合された波形を作る3つのGENルーティンを紹介する。これらのルーティンで使われる部分音は、それぞれGEN09では3個、GEN10では1個、GEN19では4個のpfieldのパラメータによって決定される。フォーマットは以下の通りである。
f # time size 9 pna stra phsa pnb strb phsb . . .
f # time size 10 str1 str2 str3 str4 . . . .
f # time size 19 pna stra phsa dcoa pnb strb phsb dcob . . .
p4までは上の例と同じなので省略する。p5以降のパラメータは以下の通りである。
pna, pnb,,,は基音に対する相対的な部分音の次数。正でなければならないが、整数である必要はないので、ノンハーモニックな部分音が可能?ナある。順序も任意である。
stra, strb,,,は部分音pna, pnbなどの相対的な強さ。負の値は180度の位相シフト。
phsa, phsb,,, は部分音pna, pnbなどの、角度で表わされた初期位相。
dcoa, dcob,,,は部分音pna, pnbなどの直流成分オフセット。例えば2の値は、サイン波のレンジを [-2,2] から [0,4] へシフトする。
str1, str2, str3,,,は固定された倍音成分の相対的な強さ。この場合には部分音の次数は整数なのでハーモニックな部分音だけが可能になる?B必要無い倍音成分はゼロにする。 GEN10では、ハーモニックで位相のそろった倍音による波形しか作れないが、GEN09とGEN19ではこの様な限界はない。これらの部分音が加え合??ウれた後で、p4が正であれば最大値が1になる様にリスケールされるが、p4が負ならばリスケールされない。 例えば、
  f1 0 256 10 1
は、時刻ゼロでGEN 10サブルーティンを呼び出し、サイン波形(基音成分だけ)を256サンプルの関数テーブル1にストアする。

22)i 文
i 文は楽器のノートステートメントで、フォーマットは以下の通りである。
i # time beat p4 ...
p1は楽器の番号、p2は楽器がオンされる時刻、p3は持続拍数、p4以降は楽器に依存するパラメータである。拍は後述のt文がない限りは秒数と?オて評価される。例えば、
f1 0 4096 10 1 ; sine wave
; ins strt dur amp(p4) freq(p5) attack(p6) release(p7)
i 3 0 1 10000 440 05 .7
i 3 1.5 1 10000 440 .9 .1
i 3 3 1 5000 880 .02 .99
i 3 4.5 1 5000 880 .7 .01
i 3 6 2 20000 220 .5 .5
e
このスコアをtoot3.orcに渡すと、これらのノートは1.5秒毎にオンされ、それぞれがlinenの指示によりp3秒後にオフされる。p4はlinenのアンプとして使われ、p5はoscilで周波数のパラメータになる。

23)e 文
e文はスコアを終了させる。パラメータはない。e文はオプショナルなので、スコアの最後にe文がなくてもCsoundは実行される。

24)t 文
Csoundスコアでの時間の単位はビートであるが、Tempoステートメントが無い場合は、1拍は1秒として扱われる。テンポを変えるには、ノー?gのすべてのp2とp3の値を変える代わりに以下のt 文を加えれば良い。
t 0 120
これは、ゼロビートからテンポ120である事を意味する。

25)a文
a文は、選択された部分のスコアをとばす。フォーマットは以下の通りである。
a p1 p2 p3
p1 には、意味はない。通常はゼロにする
p2 はビートで数えた省略の開始時刻
p3 はビートで数えた省略の長さ
これは、スコアが未完成のときに使うと便利である。

26)s文
セクションの終わりに置かれるs文には、e文と同様にパラメータはない。s文は、新たなセクションの先頭に相対的な時刻ゼロを設定するが、?シのパラメータの初期化は行わない。同一セクション内での時刻は、セクションの先頭からはかられ、i 文、f文のソート、a文の実行、t文による時間の処理はセクション毎に行われる。最後のセクションの終わりでは、s文の代わりにe文を使う。

27)自作のCモジュールを加える
既にあるCsoundのモジュールでは自分のアイディアを実現できない時には自作のモジュールをシステムに加える事ができるが、これは上級者向きの課題である。オーケストラとスコアでCsoundを呼び出すと、オーケストラは otranという翻訳プログラムによって解読され、楽器ブロックはメモリにロード可能なテンプレートの形にコード化される。そして、スコア解読プログラムの指示でoloadというローダーが発動されると、?w定されたコードがメモリにロードされ、計算が実行される。従って自作のモジュールをオーケストラで使うには、モジュールをotranのテーブルに登録し、自作のコードをCsoundにリンクする。ただしその場合、入力、出力、ワークスペース、初期化コード、perf-timeコードを定義す?骰¥造体が必要である。これらを書けば、翻訳プログラム、ローダー、ランタイムモニタは、自作のモジュールを既成のモジュールと同様に扱?、。リンクの方法はUnixとマックでは多少異なる。実際のC言語でのコードの書き方の詳細その他は、マニュアルのAppendix8を参照して欲しい?B

28)プログラミングの練習
では、実際に具体的なアイディアを実現する簡単なプログラムを書いてみよう。例えば、(1)鋭いアタックと緩やかで長いディケイを持つノイ?Yを作り、(2)これを中心周波数とカットオフバンド幅が時間的に変化するフィルタに通し、(3)リヴァーブを加えて出力する楽器をデザインす?骼魔ノする。上の番号は、プログラミングを行う手順を示している。この場合には特に複雑なプログラムではないが、一般に複雑なアイディア?ナあっても、上の例の様にいくつかのステップに分割してプログラミングを行えば良い。上のアイディアを実現するには2通りの方法がある。?ミとつは、単一のオーケストラの中でオーディオ信号の生成、フィルタリング、リヴァーブの処理をすべて行う方法で、もう一つは、他のオー?Pストラなどによって既に生成されたサウンドファイルを別なオーケストラに読み込んで、その信号に対してフィルタリングとリヴァーブの処?揩sう方法である。以下では後者の方法を使う。楽器のデザインの際には、Csoundが用意しているユニットジェネレータに関する知識が必要?ノなるが、ある程度使い込んで慣れるまではマニュアルを読み例題をこなす事が良い練習になる。しかしマニュアルを最初から1ページづつ読?ナいたのではどうにもならないので、勘を働かせる事も大切である。例えばノイズの場合、ランダムな数値をサンプリングレイトの早さで音?ノ変換すればノイズになるだろうと思い付けば、マニュアルで乱数発生ジェネレータ randを探せば良い事が分かる。その他のジェネレータの場合も、付けられた名前によって機能を判断できる様になっている。例えばオシレータにはoscilがあり、フィルタにはresonやcombといった名前がある。リヴァーブのユニットにはreverbがある、といった具合である。

29)ノイズジェネレータ
上で述べた様に、ノイズを作るには乱数を発生させる信号ジェネレータを使えば良い。マニュアルのSIGNAL GENERATORSの項目の下には、
kr rand xamp[, iseed]
kr randh kamp, kcps[, iseed]
kr randi kamp, kcps[, iseed]
ar rand xamp[, iseed]
ar randh xamp, xcps[, iseed]
ar randi xamp, xcps[, iseed]
などがある。
これらは、+ampから-ampまでの間でランダムナンバーを発生する。
これらのうち、randは一様に分布するランダムナンバーを発生するが、その他はパラメータcps の指定によって、サンプリングまたはコントロールレイトよりも小さい周波数でランダム数列を生成するので、バンドリミテッドなノイズを作る事ができる。
randhはこれらの値をホー?泣hし、randi は隣接する値の間を線形のインターポレーションを行う。iseedはオプショナルで、ゼロから1までの間の値を指定すると初期値がkamp * iseedになる。マイナスの値は、再初期化をスキップする。ディフォールトは0.5である。

30)ノイズ楽器を作る
では手始めに、randi でバンドリミテッドなホワイトノイズを発生させ、これにlinsegをコントロール信号として使いリニアなエンヴェロープを持ったノイズ音響を作る。
randiのフォーマットは、上に示した通りである。一方linsegのフォーマットは、
   kr linseg ia, idur1, ib[, idur2, ic[...]]
である。ここで
iaは開始の値、
ib, ic,,,はdur1 秒後の値
idur1は 最初のセグメントの持続の秒数
idur2, idur3,,, は2番目以降の秒数
であるが、これらはすべてアルファベットのiで始まるので音符毎に初期化されるパラメータである。そこで、全体の音の長さをスコアのi 文?フp3で指定すれば、
   kr linseg 0, 0.01, 10000,p3-0.01,0
ar randi kr, icps,0.5
は、0.01秒のアタックでアンプがゼロから10000へ立ち上がり、p3-0.01秒で再びゼロに戻るノイズになる。スコアでは、取り敢えず楽器番号1?A開始時刻0、デュレーション5秒とし、
i 1 0 5
e
としておく。フォーマットに従ってオーケストラを書くと以下の様になる。
sr=22050
kr=2205
ksmps=10
nchnls=1

instr 1
icps=10000
kenv linseg 0, 0.01, 20000, p3-0.01, 0
asig randi kenv, icps,0.5
out asig
endin
これらのファイルにそれぞれnoise1.orcとnoise1.scoと名前を付けてセーヴしCsoundを実行すれば、ノイズの入ったサウンドファイルnoise1.sndが作られ、ノイズ音が聞こえるはずである。

31)フィルタ
Csoundで使えるフィルタの一つににresonがある。フォーマットは以下の通りである。
   ar reson asig, kcf, kbw[, iscl, istor]
パラメータは以下の通りである。
kcfは中心周波数をコントロールする。
kbwはバンド幅 をコントロールする。
istor はメモリの初期値で、ゼロに設定すればメモリがクリアされる。ディフォールトはゼロである。
iscl は、フィルタに対するスケーリングファクタを指定する数値である。
 0ならば、信号に対するスケーリングを行わない。
  後でbalanceを行う。ディフォールトはゼロである。
 1はピークレスポンスファクタが1である事を意味する。
  kcf 以外の周波数成分は、応答曲線に従ってアッテニュエイトされる。
 2では、レスポンスファクタが上昇し、全体的なRMSの値が1に等しい。
  すべての周波数が存在すれば入力と出力のパワーが等しくなる。
  ホワイトノイズに対して最も適用できる。
複雑な複数のピークを持つ応答は、適当なフィルタバンクを直列につなげば作る事ができる。

32)サウンドファイルを読む
既に存在しているサウンドファイルから信号を引き出してオーケストラへ読み込むには、soundinを使う。フォーマットは以下の通りである。
a1 soundin ifilcod[, iskiptime][, iformat]
ifilcodはダブルクオートで囲まれたサウンドファイル名またはsoundin.nへの整数サフィックスnの部分である。オプションでフルパスネーム?w定しても良い。フルパスでない場合には、システムはサウンドファイルを現在のディレクトリで、次に環境変数でSFDIRとして指定されたディレクトリで探す。
iskptim (optional) は スキップされるサウンドファイルの秒数。ディフォールトはゼロ。 iformat (optional) はオーディオデータファイルのフォーマット。ディフォールトはゼロで、その場合にはサウンドファイルのヘッダ情報に?]う。例えば、1.5秒目からのsoundin.5のデータを使う場合には、
a1 soundin 5, 1.5
とすれば良い。

33)フィルタ楽器を作る
ではnoise1.sndを、例えば以下の図の様に時間的に中心周波数とバンド幅が変化するバンドパスフィルタに通してみよう。下図では縦軸が周波数を、横軸は時間を表わす。図の横方向へ伸びる3本の線のうち、中心線がフィルタの中心周波数で、上下の線は通過する周波数帯域である。
"       <バンドパスフィルタの中心周波数とバンド幅>
図のデータをオーケストラに書き込めば、以下の様になる。
sr = 22050
kr = 2205
ksmps = 10
nchnls = 1
instr 2
anoi soundin "noise1.snd", 0
kcf linseg 250,1,600,1,100,1,525,1,800,1,900
kbw linseg 100,1,400,1,0,1,1050,1,200,1,1800
ares reson anoi, kcf, kbw, 1
out ares
endin
soundinを使う場合でもスコアは必要で、楽器番号、開始時刻、デュレーションを以下の様に指定する。
i 2 0 5
e
これらをそれぞれセーヴしてcsoundを実行すれば良い。イメージ通りの音になっただろうか?

34)リヴァーブとグローバル変数
Csoundが用意しているリヴァーブユニットには以下の3種類がある。
ar comb asig, krvt, ilpt[, istor]
ar alpass asig, krvt, ilpt[, istor]
ar reverb asig, krvt[, istor]
これらへの入力はkrvt秒間リヴァーブされ、オーディオ信号として出力される。combでは色づけされたリヴァーブになり、alpassではフラット、reverbでは自然な室内の周波数応答がそれぞれ得られる。パラメータは以下の通りである。
ilptはループ時間の秒数で、エコー密度を決める。コームの場合には、ゼロから sr/2までの間を等間隔でilpt * sr/2個のピークになる。
istor はディレイループの初期位置。ディフォールトはゼロ。
reverb出力には1/20秒程度のディレイが伴なうだけでなく、出力レベルがオリジナルの信号よりも小さいので、ソースの信号を適度にスケーリングしリヴァーブとミックスして出力する事が普通である。またリヴァーブはソースが消えた後でも続くので、ソースのオーディオを通過させる別な楽器としてデザインする必要がある。従ってソースのオーディオ信号をグローバル変数として受け取れる様にしておき、ソースがある限りリヴァーブ楽器をオンに設定すれば良い。楽器は番号順に実行されるので、他の楽器から信号を受け取るリヴァーブ楽器には、オーケストラ中で最大の番号を与えておく。この場合のグローバル変数はすべての楽器から参照され、楽器間でのオーディオ信号の授受に使われるので、楽器の音符が重複しても信号が損なわれる事はない。グローバルな変数の宣言は initを使ってヘッダで行う。変数の先頭はgで、その後にこの信号の種類を表わすi, k, aを続ける。例えば、
ga1 init 0
がヘッダに置かれていれば、グローバルなオーディオ信号を格納する変数ga1 が初期化され、すべての楽器から参照できる様になる。

35)ノイズ→フィルタ→リヴァーブ
以上で学んだ事を最終的な楽器の形にまとめてみよう。ただしここでは、音符(ノイズ音)を3個とし、これらを重複させる。音符毎にアンプとバンドパスフィルタの中心周波数を独立に変化させる。バンド幅の大きさは中心周波数に対して一定の割合を保つが、その割合は音符毎に変えて設定する。ここでは、これら全体の音符に対して一定のルームリヴァーブをかけるが、音符毎にリヴァーヴの量を変更する事も可能である。音符のパラメータは、スコアのpフィールドから指定する。
楽器が重複する部分のオーディオ信号の計算は以下の様に行われる。まずグローバル変数がヘッダでクリアされる。次にコントロール周期毎にフィルタの出力とリヴァーブの出力が加算されるが、楽器が重複していればフィルタからの出力も重複した音符の部分に対して計算され、この出力にたいしてさらにリヴァーブ信号が加算される。この計算が終わるとグローバル変数は再びゼロにセットされ、次のコントロール周期の部分のオーディオ信号が同様に計算される。従って、重複する信号にリヴァーブを加える場合には、アンプがレンジを超えないように注意する必要がある。オーケストラは、例えば以下の様になる。
sr = 22050
kr = 2205
ksmps = 10
nchnls = 1
garev init 0
instr 3 ; Filter Instrument
iamp=p4
anoi soundin "noise1.snd", 0
kcf linseg p6,1,p7,1,p8,1,p9,1,p10,1,p11
kbw linseg p6*p5,1,p7*p5,1,p8*p5,1,p9*p5,1,p10*p5,1,p11*p5
ares reson anoi, kcf, kbw, 1
out ares*iamp*0.5
garev = garev + ares
endin
instr 31 ; Reverb Instrument
irvbtime = p4
arev reverb garev, irvbtime
out arev*0.6
garev = 0
endin
soundinを使う場合でもスコアは必要で、楽器番号、開始時刻、デュレーションを以下の様に指定する。
; p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11
; ins strt dur amp kbw kcf1 kcf2 kcf3 kcf4 kcf5 kcf6
i3 0 5 0.8 0.2 2000 300 800 100 7000 500
i3 2 5 1.2 1 300 1300 500 15000 700 5000
i3 3.5 5 0.5 0.5 7000 400 1500 200 8700 300
リヴァーブのスコアについては、デュレーションを最後の音符が鳴り終わる時刻+リヴァーブ時間とする。そうしないと、最後のリヴァーブが?ソき終わる前にリヴァーブ楽器がオフになってしまう。
; p1 p2 p3 p4
; ins strt dur revtime
i 31 0 11.5 3
e

36)スコア生成言語言語としてのPerl
さて、様々な音響的アイディアは楽器と簡単なスコアを書けばテストできる事が分かった。自分の気に入る音響素材を生成する楽器が少しづつ増えて来ると、今度はそれを使って短い音響作品を作ってみたい気分になってくる。そうそう、その調子!次の課題は、どうやってスコアを書くのか、という事になる。スコアが短い場合にはi文を自分で書くのも苦にならないが、多くの楽器を使ったオーケストラを長大なスコアでコ?塔gロールする場合にはちょっと面倒になる。せっかくコンピュータを使うのだから、もしも自分のアイディアをたとえ部分的であっても簡潔?ネ形で記述できれば面白いだろう。テキストの生成や細部のパラメータの設定その他は、その記述に従ってコンピュータに実行させれば良い。?アの方法は、何か特定のアイディアに従ってディーテイルを徹底的に追及し、複雑な響きの構造を作り出す場合には非常に効果的である。この?lな作品制作へのアプローチを、アルゴリズミック・コンポジションと呼ぶ。Csoundは、この目的のためにSCOTを用意している。またAppendix 1のCSOREも使える。もちろんこれらを使っても良いが、スコアがテクストの形を持ったデータである事を考えると、テクスト・データを試行錯誤しながら手軽に処理する一般的な言語はないかと誰でもが思い始める。そんな時、Perlという非常にお誂え向きの言語がある事を知人が教えてくれた。字面は何となくC言語に似ているが、一々変数を宣言する必要もコンパイルの必要もないので便利である。Lispの様に対話型で気楽?ノ使える点が気に入り、私はすぐにPerlのファンになってしまった。ただしPerlはUNIXの環境で本領を発揮するので、マックユーザ向きではな?「かも知れないが。Perlに関しては既に数冊の解説書が出ている。これらを章末の文献リストに載せておくので、関心を持った読者はぜひこれ?轤Q照すると良いだろう。

参考文献
Barry Vercoe, Csound Manual.word, MIT Media Lab, 1992
河野真治、    入門Perl、         アスキー出版局、  1994
Wall & Schwartz, 近藤訳、Perlプログラミング、 ソフトバンク