Audio Tutorial 1 1. How to use the Synth class ■1.Synthクラスの利用 このチュートリアルではSynth classを用いてどんなことができるのかを学びます。 ■1.1 サウンドの再生方法「play」 まず、最初の簡単な例として、周波数:800ヘルツ、振幅:0.1(-20dB)のサイン波を再生します。 まず最初はコメントのない例です: Synth.play({ SinOsc.ar(800, 0, 0.1, 0) }); 次は同じ例ですがとってもたくさんのコメント付きです。 コメントをつけておくと、いろいろと便利です。 //ダブルスラッシュに続く1行はコメントとしてみなされます。 /*と*/ で、コメントを囲えば、コメントを複数行に跨いでつけることができます。 ( //上の括弧のあたりをダブルクリックするとこのサンプルプログラムを選択するのに便利です。 Synth.play( /*再生するための一番目のアーギュメントはUGenグラフを作る関数です。 UGenグラフはユニット・ジェネレータの繋がったネットワークです。 この例での"ネットワーク"は一つのユニット・ジェネレータから成っています。*/ { /* { (中括弧)でくくることにより関数は定義されます。 関数はユニット・ジェネレータのグラフを作るコードを含んでいます。 この例題では、一つのサインオシレータだけを作っています。*/ SinOsc.ar( //このSinOscクラスの'ar'メソッドはオーディオ・レイトのオシレータを作ります。 //SinOsc.arは次のような4つのアーギュメントを持ちます。 800, // 周波数を800Hzにセット 0, // 位相を0ラジアンにセット 0.1, // サイン波の振幅を0.1にセット 0 //サイン波に0を足す ) //関数は一番最後に評価された値を返します。 //この関数では一つの評価、つまりSinOsc.ar.だけです。 } //最後に中括弧を閉じて関数を終わりにします。 ); ) 次はコメントもつけず、省略できるものを省略して、なるべく短く書いてみました。 関数はplayメソッドそのものを受け入れることができます。 playメソッド自身がSynth.playを呼び出すことができるのです。 また、SinOsc.arの4つめのアーギュメントあるaddのデフォルト値は0なので、これは省略することができます。 { SinOsc.ar(800, 0, 0.1) }.play; 随分とシンプルに書くことができました。 つぎは一定時間だけ再生させてみましょう。 playメソッドのの2つめのアーギュメントで、再生時間(durarion)を指定してあげることができます。 2つめのアーギュメントを与えない場合は、コマンド-ピリオドでこのプログラムを終了するまで再生し続けます。 Synth.play({ SinOsc.ar(800, 0, 0.1) }, 1.5); // 1.5秒間再生をします ■1.2 アウトプットをプロットする「plot」 Syhthクラスでは音を出力するだけではなく、他にもいろいろなことができます。 まず、Synthのアウトプットをプロット(描画)してみましょう。 プロットするにはplotメソッドを使います。 下の例では、サイン波(周波数800、位相0、振幅0.1)を0.01秒(=10ミリ秒)プロットします。 plotの2つめのアーギュメントは、プロットする時間です。 Synth.plot({ SinOsc.ar(800, 0, 0.1) }, 0.01); プロットされたものを見てみましょう。 サイン波が8サイクル分プロットされています。 これはつまり、800サイクル/秒 × 0.01秒 = 8サイクル ということですね。 ちなみにplotは4つのアーギュメントをとります。 3つめのアーギュメントはプロット表示するウィンドウの名前、 4つめのアーギュメントはプロット表示するウィンドウのサイズや位置などを指定することができますが、これらは省略可能です。 Synth.plot({ FSinOsc.ar(80) }, 0.1, "pyon", Rect.newBy(80,80,400,200)); プロットはメモリのバッファを使用して行われるので、あまり長い時間のプロットをしないようにしましょう。 (44.1kHzで32bit実数の1時間のステレオサウンドをプロットするためには1.2GB必要になります) ■1.3 アウトプットをリアルタイムに表示する「scope」 1.2では出力のプロットを行いましたが、次は、波形をリアルタイムに表示してみましょう。 その為にはscopeメソッドを使います。 前の例のようにサイン波を表示してみましょう。 Synth.plot({ SinOsc.ar(800, 0, 0.1) }, 0.01); しかしサイン波は変化がないので、きちんとリアルタイムに表示されているのがあまりわか りません。次の例では、変化の解りやすいブラウンノイズを表示しています。BrownNoiseオシレー タはmultiplyとaddという2つのアーギュメントをとります。multiplyは0.1とし、addは省略してい ます(省略した場合はデフォルトである0になります)。 Synth.scope({ BrownNoise.ar(0.1) }, 0.01); またscopeの二つ目のアーギュメントは表示する時間です。 最初の例にあった800Hzのサイン波を0.1秒表示させてみます。 800サイクル/秒 × 0.1秒 = 80サイクル なのでサイン波が80サイクル表示されづける でしょう。 Synth.scope({ SinOsc.ar(800, 0, 0.1) }, 0.1); ■1.4 サンプルバッファつくる「collect」 サンプルをバッファに書き込むことができます。 オーディオのバッファをつくったりするにはSignalクラスを使います。 Synthクラスのcollectメソッドは、Synthの出力を指定した長さの時間分みたしたSignal クラスのインスタンスを返します。 これにより非リアルタイムのサウンド処理をすることができます。 ( var x , y; //使用する2つの変数を定義します。 //0.01秒のサイン波のバッファをつくります。 x = Synth.collect({ SinOsc.ar(800, 0, 0.1) }, 0.01); //シグナルバッファを返します。 y = x.abs; // バッファに対して処理を行います。 // ここではバッファのサイン波の絶対値にしています。 // シグナルへのほとんどの数学処理は非破壊的に行われます。 // つまりは、xのバッファはそのままで変化はせずに、yに新しいバッファが返されるのです。 // さて、元のオリジナルとそれを処理したものをウィンドウに表示させましょう。 SignalWindow.new( //SignalWindow.newでSignalを表示するためのウィンドをつくります "collect", //ウィンドの名前を付けます。ここではcollectとしました。 nil, //ウィンドの大きさを指定します。ここではnilと指定し、これはデフォルトのサイズを 使用します。 [x, y] // [x, y]という配列が渡された場合は、SignalWindowは複数のSignalを表示します。 ); ) つづいて、バッファをつかったサンプルを二つ紹介します。 次の例では、2つのバッファをつなげて、その結果を出力します。 ( var x,y,z; x = Synth.collect({ SinOsc.ar(800, 0, 0.1)}, 0.01); // Signalバッファを返します y = Synth.collect({ SinOsc.ar(1600, 0, 0.1)}, 0.01); // Signalバッファを返します z = x ++ y; // Signalxとyをつなげます。 SignalWindow.new("collect", nil, z); // //つなげたサウンドを表示します ) 次は、つないだ結果を再生してみましょう。 ( var x, y, z; x = Synth.collect({ SinOsc.ar(800, 0, 0.1) }, 0.2); y = Synth.collect({ SinOsc.ar(1600, 0, 0.1) }, 0.2); z = x ++ y; z.play; //つなげたサウンドを再生します。Singnalはループ再生をします。 ) ■1.5 サウンドファイルを書き出しましょう「write」 非リアルタイムにサウンドファイルを書き出すのはSynthクラスのwriteメソッドです。 writeメソッドは5つの引き数をとります。 1つめはユニット・ジェネレータ・グラフ関数、 2つめはファイルの長さを秒数で指定、 3つめはファイルのパス名、 4つめは書き込むファイルのヘッダフォーマットまたはタイプを指定、 5つめはサンプルのフォーマットを指定する引き数です。 使用できるファイルのヘッダフォーマットまたはタイプは以下の通りです。 デフォルトはAIFFです。 'AIFF', - Apple AIFF 'SD2', - Sound Designer 2 'RIFF', - Microsoft .WAV 'Sun', - NeXT/Sun 'IRCAM', - old IRCAM format 'none' - no header = raw data 使用できるサンプルフォーマットは以下の通りです。 デフォルトは16 big endian signedです。 '8 signed', '8 unsigned', '8 mulaw', '8 alaw', '16 big endian signed', '16 big endian unsigned', '16 little endian signed', '16 little endian unsigned', '24 big endian signed', '24 little endian signed', '32 big endian signed', '32 float big endian' '32 little endian signed', '32 float little endian' '64 double big endian' '64 double little endian' 下の例では、ヘッダフォーマットとしてAIFFを、サンプルフォーマットとして16 big endian signedを指定しています。 これを実行しますと、SCフォルダにsine800というAIFFファイルができるでしょう。 ( // ディスクへサウンドを書き込みます Synth.write( { SinOsc.ar(800, 0, 0.1) }, /// ユニット・ジェネレータ・グラフ関数 2, // 2秒間のファイルを作る "sine800", /// パス名 'AIFF', // ヘッダフォーマット '16 big endian signed' // サンプルフォーマット ) ) AIFFと16 big endian signedはデフォルトなので、省略することができます。 上の例もっとシンプルに書くことができます。 ( Synth.write( { SinOsc.ar(800, 0, 0.1) }, 2, "sine800" ) ) ■1.6 ディスクからサウンドファイルを再生しましょう「SoundFile.play」 ファイルを書き出せたところで、次は、ディスクからファイルを再生しましょう。 その為にはSoundFileクラスのplayメソッドを利用します。 最初の引き数はファイルのパス名です。 先ほどの例で、作成したsine800というファイルの再生をしてみましょう。 SoundFile.play("sine800"); ループ再生をしたい場合は、ループフラグをtrueにします。 SoundFile.play("sine800", loop: true); ■1.7 再生中のサウンドファイルをディスクへ書き出す「record」 Synth.writeでは音を聞きながらサウンドファイルを書き出すことができませんでした が、Synthクラスのrecordメソッドでは、音を聞きながらファイルを書き出すことがで きます。 recordメソッドの引き数はwriteメソッドの引き数と同じものです。 ( // ディスクへサウンドを書き込みます Synth.record( { SinOsc.ar(900, 0, 0.1) }, /// ユニット・ジェネレータ・グラフ関数 2, // 2秒間のファイルを作る "sine800", /// パス名 'AIFF', // ヘッダフォーマット '16 big endian signed' // サンプルフォーマット ) ) writeメソッドと同様にAIFFと16 big endian signedはデフォルトなので、省略すること ができます。 上の例をもっとシンプルに書くことができます。 ( Synth.record( { SinOsc.ar(900, 0, 0.1) }, 2, "sine800" ) ) サウンドファイルの再生は、1.6章で説明したのと同様にできます。 SoundFile.play("sine900"); |