グローバル変数

グローバル変数
変数としてこれまで扱ってきたものが、実は2種類ある。1つは通常の変数、もう1つはアル
ファベット1文字で表される変数である。
通常、変数は実行するコード全体の冒頭で宣言しておかないと、使うことができない。しかも、
いったん実行してしまったら、その後で宣言した名前の変数にアクセスすることはできない。つまり、
その変数の値を後から変えることもできなければ、その変数の値を知ることすらできないのである。
こうした性質は、アルファベット1文字の変数になると異なってくる。アルファベット1文字の
変数の場合、宣言することなく用いることができる。さらに、いったんコードを実行した後で、その
中で使われているアルファベット1文字の変数にアクセスすることができる。
アルファベット1文字の変数の持つ、こうした性質を使って、前回までの例では音の載ってい
るノードのID番号や、メロディーを演奏させるためのRoutineなどに用いてきた。それより前から、既
にServer.localで与えられるサーバには、sという変数が当てはめられている。
こうした変数を不必要に多用するのは、コンピューターの処理効率上、推奨されない。さらに、
アルファベットの数には限りがある。しかし、扱わなければならないノードのID番号やRoutineなど
が増えてくると、同様の特徴を持つ変数がもっと必要になるだろう。
そこで用意されているのが、グローバル変数である。グローバル変数は ~ (チルダー)で始め、
その後に適当な文字を続けて、名前を付ける。これをあらかじめ宣言しておく必要はなく、一度作っ
てしまえば、SuperColliderの起動中、ずっとそのまま扱うことができる。
変数の種類
宣言
有効期間
通常の変数
必要あり
コード実行の瞬間のみ
アルファベット1文字の変数、及びグローバル変数
必要なし
SuperColliderの起動中
例えば、
~melody1 = Routine.new({
loop({
...
})
});
~melody1.play;
として、演奏を始めたRoutineを
~melody1.stop;
として途中で停止させたり、またその後で
~melody1.reset;
~melody1.play;
として演奏を開始させたりすることができる。
[問題1]
Routineでメロディーを演奏させながら、その音にディレイをかけるまでのプログラムに関して、s 以外
のアルファベット1文字の変数を、全てグローバル変数に書き直して実行しなさい。
バッファを使う(1)──加算合成
音に含まれる様々な周波数の中でも、基本となる周波数(基音)の整数倍にあたる周波数は、
「倍音」と言われ、重要な音の成分と見なされる。SuperColliderでは、基音と倍音の大きさを制御す
ることによって波形を合成し、音作りを行なうことができる。これを「加算合成」と呼ぶ。
まず、倍音を持たず、基音のみで構成されるサイン波の波形は、下のようになる。
これに対し、基音に加えて、基音の2倍の周波数の音が基音の半分の大きさで、さらに基音の3
倍の周波数の音が基音の4分の1の大きさで含まれるサイン波の音は、下のようになる。
このように合成された音を出そうとする場合、合成した波形のグラフをいったんコンピュー
ター上に記憶させておき、音を出す際にそのグラフを呼び出して用いることとなる。その、グラフを
記憶しておく場所のことを「バッファ」と言う。
音の波形のグラフを使うとなると、そのグラフがどの程度の精度を持つのかが問題となる。例
えば、波形を表すため1秒間を何コマかに分割して捉えようとすれば、そのコマ数が多ければ多い程、
グラフとしての精度は高まる。
この、1秒間を何コマにするかを示した数値を「サンプリング・レート」と言う。現在、一般
的なオーディオCDにおいては、44100Hzのサンプリング・レートが規格として統一されている。
さて、実際にSuperColliderで倍音の加算合成を行なうプロセスを見てみることにしよう。まず、
加算合成で波形のグラフを元に音を出すには、その音源としてOscクラスの.arメソッドを使う。
Osc.ar( グラフの記憶されたバッファ, 周波数, 位相, 増幅値, 加減値 )
最初の引数が独特だが、後はSinOsc.arの引数がそのまま入る。そして、波形を記憶するバッ
ファを用意しなければならない。
Buffer.alloc( サーバ, フレーム数 )
サーバとは、バッファを用意するサーバのことで、ローカル上に設ける場合には s が入る。
フレーム数とは、1周期分の波形のグラフを描くのに用いる、コマ数のことである。
用意されたバッファにサイン波の音を重ねていくには、.sine1メソッドを使うことができる。
.sine1( [増幅値の配列] )
増幅値の配列は、
[ 基音の増幅値, 2倍音の増幅値, 3倍音の増幅値, 4倍音の増幅値, 5倍音の増幅値, ... ]
といった具合に、加えたい倍音の数まで増やすことができる。
バッファを使い終わったら、他の処理のために使用していた領域を開放しておく必要がある。
そのためには、.freeメソッドを用いる。
以上の道具を使って、次のように音を出すことができる。
SynthDef.new( \addSyn1, { arg freq, amp, pos, buffer;
var src, env, out;
src = Osc.ar(
buffer,
freq
);
env = EnvGen.kr(
Env.new(
[0, 1, 0.3, 0],
[0.01, 0.2, 0.25]
),
levelScale: amp,
doneAction: 2
);
out = Pan2.ar( src*env, pos );
Out.ar( 0, out )
}).send(s);
~buf = Buffer.alloc( s, 512 ); // フレーム数が512のバッファを用意する
~buf.sine1( [ 1, 0.6, 0.4, 0.3, 0.1 ] );
// 基音の大きさ1に対して、2倍音が0.6、3倍音が0.4、4倍音が0.3、5倍音が0.1の大きさ
// となるように、グラフを描く
s.sendMsg( \s_new, \addSyn1, n=s.nextNoodeID, 0, 1, \buffer, ~buf );
// 音を鳴らす
~buf.free;
// 使い終わったバッファを開放する
[問題2]
倍音の加算合成に加え、その位相の値を-piからpiまでの間で変調させ、さらにそれに何らかのフィル
ターをかけた音を出すためのSynthDefを作り、その音を鳴らしなさい。
リモートサーバ
ここまで、音を鳴らすための音響合成は、SCLangを扱うのと同じコンピューター内の
SCSynth、すなわちs = Server.local が行なってきた。
しかし、ネットワークで繋がった他のコンピューター上でも、SCSynthさえ起動していれば、
そこへ向けてコマンドを送ることができ、つまりはそのコンピューターから音を出すことができる。
そのように、ネットワークで繋がった他のコンピューター上のSCSynthのことを、「リモート
サーバ」と呼ぶことにする。
リモートサーバは、次のようにServerクラスとNetAddrクラスを使って特定することができる。
Server.new( サーバの名前, NetAddr.new( “IPアドレス”, 57110 )
サーバの名前は、\ (バックスラッシュ)で始めて、適当な名前を付ければ良い。
ここで、リモートサーバとはLANの内部で繋がっているものと仮定すれば、IPアドレスはロー
カルのアドレスとなる。57110は、サーバ間でOSCのデータをやりとりする際のポート番号である。
実際にリモートサーバで音を鳴らすまでを見てみよう。
~remoteSvr = Server.new( \remote1, NetAddr.new( “192.168.1.10”, 57110 ) );
SynthDef.new( \test, { arg freq, … ;
…
} ).send( ~remoteSvr );
~remoteSvr.sendMsg( \s_new, \test, … );
[問題3]
い。
[問題2]で作った音でメロディーを奏でるRoutineを作り、それを特定のリモートサーバから鳴らしなさ