1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
|
title:: 09
summary:: Mark Polishook tutorial (JP)
categories:: Tutorials>Mark_Polishook_tutorial>Japanese_version
related:: Tutorials/Mark_Polishook_tutorial/00_Introductory_tutorial
section::2項演算
1つのUGenの後にオペレータとオペランドが続く2項演算は、通常は、単項演算によって生成されるよりもより複雑なシンセシス・プロセスを作り出します。
2項演算の例としては、ほんのいくつか例を挙げると、加算、乗算、減算、割算といったものがあります。
一般的なパターンは
table::
## OBJECT || OPERATOR || OPERAND
::
オブジェクト オペレータ オペランド
であり、例えば次の様に
code::
2 * 3
::
オブジェクト、2項演算子、オペランド、となります。
UGenに対して適用することのできる2項演算の多くのリストを見るには、SuperColliderのヘルプ・システムでHelp/BinaryOpsを参照して下さい。
////////////////////////////////////////////////////////////////////////////////////////////////////
section::ミキシング=加算
2つ、またはそれ以上のUGenをミックスするには加算します。
code::
(
// 2つのノコギリ波をミックスする
{
Saw.ar(500, 0.05) // オブジェクト
+ // オペレータ
Saw.ar(600, 0.06) // オペランド
}.scope;
)
::
加算の結果は1つのBinaryOpUGenになります。
////////////////////////////////////////////////////////////////////////////////////////////////////
次の例は、3つのUGenが加算を通して合体することによって何が起きるのかを示します。最初に、2つのUGenが1つのBinarOpUGenに合体します。その結果に加算演算子ともう1つのUGen(オペランド)が続き、もう1つのBinaryOpUGenを生成します。
code::
(
{
// 最初の2つのUGenは1つのBinaryOpUGenに合体する
Saw.ar(500, 0.05)
+
Saw.ar(600, 0.06)
+
// このUGenはBinaryOpUGenに対するオペランドと‘+’オペレータ
Saw.ar(700, 0.07)
}.scope;
)
::
////////////////////////////////////////////////////////////////////////////////////////////////////
MixというUGenを用いることで前の例と同じ結果になります。
code::
(
{
// ミックスしたいUGenを配列の中に入れる
Mix.ar(
[
Saw.ar(500, 0.05),
Saw.ar(600, 0.06),
Saw.ar(700, 0.06)
]
)
}.scope
)
::
////////////////////////////////////////////////////////////////////////////////////////////////////
もしくは、Mix.arFillを使って似た様な結果を生成することもできます。この関数が実行される時には毎回、アーギュメントiはインクリメントされます。つまり、1回目に関数が実行される時にはiは0に等しく、2回目には1、3回目には2、という様になります。
code::
{ Mix.arFill(3, { arg i; Saw.ar(500 + ((i+1) * 100), 0.05) }) }.scope;
::
////////////////////////////////////////////////////////////////////////////////////////////////////
section::スケーリング=掛算
低い周波数のオシレータを用いる次の例は、WhiteNoiseジェネレータに対してエンベロープを適用します。これは、1つのUGenを他のUGenと掛算することにより、双方をスケーリングするということをデモするものです。
code::
{ WhiteNoise.ar(0.1) * SinOsc.kr(1, 1) }.scope;
::
次の例は、2つのノイズを生成するUgenがサイン波でスケーリングされてBinaryOpUGenを生成し、それがまた別のBinaryOpUGenに加算されるというものです。
code::
(
// ... 汽車のまね?
{
(WhiteNoise.ar(0.1) * SinOsc.kr(1, 1))
+
(BrownNoise.ar(0.1) * SinOsc.kr(2, 1))
}.scope;
)
::
////////////////////////////////////////////////////////////////////////////////////////////////////
section::エンベロープ
UGenの任意のアスペクト、例えば、周波数、位相、振幅といったものをダイナミックに変調するにはエンベロープを使います。
code::
// 振幅を変調する
{ SinOsc.ar(440, 0, 0.1) * EnvGen.kr(Env.sine(1), doneAction: 2) }.scope;
::
doneActionアーギュメント(コントロール)を2にセットすると、SuperColliderはSinOscとEnvGenのインスタンスを保持するために要求されていたメモリを解放することを確約します。アーギュメントがキーワードのスタイルで与えられていることに注意して下さい。キーワードのスタイルとは、アーギュメントの名前の後にコロン(‘:’)が続き、コロンの後に値が続く、というものです。
キーワードはコードをより読みやすいものにします。また、これによってアーギュメントを任意の順番で書くことができる様になります。
////////////////////////////////////////////////////////////////////////////////////////////////////
EnvGenのtimeScaleアーギュメント(コントロール)は、エンベロープの継続時間を変調します。
code::
(
SynthDef("timeScale", { arg ts = 1;
Out.ar(
0,
SinOsc.ar(440, 0, 0.4) * EnvGen.kr(Env.sine(1), doneAction: 2, timeScale: ts)
)
}).add;
)
Synth("timeScale", [\ts, 0.1]); // timeScaleコントロールはエンベロープの継続時間
::
////////////////////////////////////////////////////////////////////////////////////////////////////
code::
// ... エンベロープの時間をシンセが作られるたびに毎回違ったものにスケーリングする
(
r = Routine({
loop({
Synth("timeScale", [\ts, 0.01.rrand(0.3)]);
0.5.wait;
})
});
)
r.play
::
////////////////////////////////////////////////////////////////////////////////////////////////////
section::加算合成
加算合成とはその名が示す通りのものです。コンポーネントはお互いに加えられ(または合計され)ます。
code::
(
{ // 関数を12回実行する
var n = 12;
Mix.arFill(
n,
{
SinOsc.ar(
[67.0.rrand(2000), 67.0.rrand(2000)],
0,
n.reciprocal * 0.75
)
}
)
*
EnvGen.kr(Env.perc(11, 6), doneAction: 2)
}.scope
)
::
////////////////////////////////////////////////////////////////////////////////////////////////////
section::それぞれのコンポーネントにエンベロープを与える
加算合成に期待されて来たこととは、求められる周波数成分に従ってサイン波を加算することで、想像しうるサウンドを生成または再現することができるということでした。
加算合成の問題点とは、サウンドの正確な周波数成分を知る必要があるということで、それには必要とされる数のサイン波のそれぞれが理想的なエンベロープで制御されることによって初めて可能になるのです。
どちらにせよ、前の例のそれぞれのコンポーネントに別々のエンベロープを与えることによって、より微妙なテクスチャーを生成することができます。
code::
(
{ var n = 12;
Mix.arFill(
n, // n個のサイン波を生成する
{
SinOsc.ar( // それぞれがlow.rrand(high)の範囲内で起こりうる周波数
[67.0.rrand(2000), 67.0.rrand(2000)], // ... 実数の値
0,
n.reciprocal // それぞれのサイン波の振幅をスケーリングする
// nの値に従って
)
*
EnvGen.kr( // サイン波のそれぞれにエンベロープを与える
Env.sine(2.0.rrand(17)),
doneAction: 0 // サウンド全体が完了した時にだけ
// エンベロープを解放する(なぜ?)
)
}
)
* // パッチ全体に対してエンベロープを与える
EnvGen.kr(
Env.perc(11, 6),
doneAction: 2,
levelScale: 0.75
)
}.scope
)
::
(もしくはlink::Classes/Klang:: ugenを用いることで同じ様な結果が得られます)
////////////////////////////////////////////////////////////////////////////////////////////////////
section::リング変調
2つのUGenを掛算することでリング変調を生成します。
code::
// キャリアの振幅を低周波オシレータ(LFO)で変調
{ SinOsc.ar(440, 0, 0.571) * SinOsc.kr(2.reciprocal) }.scope
// LFOの周波数を可聴帯域にすることで追加の周波数成分を生成する
{ SinOsc.ar(440, 0, 0.571) * SinOsc.kr(880) }.scope
// 低周波のオシレータ(lfo)でモジュレータの振幅を変調する
(
{
SinOsc.ar(440, 0, 0.571)
*
(SinOsc.kr(880) // モジュレータとlfoを括弧の中に包み込む
* // なぜ?
SinOsc.kr([6.99, 8.01].reciprocal)
)
}.scope
)
::
////////////////////////////////////////////////////////////////////////////////////////////////////
section::振幅変調
2つのUGenを掛算する際にモジュレータの値を正の値に制限することで、Charles Dodgeが「クラシック」振幅変調と呼ぶものを生成します。
モジュレーター、もし低周波のオシレータである場合には、その出力が正の値に制限されているか正の値に制限されていないかの違いは、変調の振幅のみに表れます。UGenを正の値のみに制限するために.absメッセージを使っています。
code::
// 低周波のオシレータ(lfo)でキャリアの振幅を変調する
{ SinOsc.ar(440, 0, 0.571) * SinOsc.kr(2.reciprocal).abs }.scope
// lfoを用いてモジュレータの振幅を変調する
(
{
SinOsc.ar(440, 0, 0.571)
*
(SinOsc.kr(880).abs // モジュレータとlfoを括弧の中に包み込む
* // なぜ?
SinOsc.kr([6.99, 8.01].reciprocal)
)
}.scope
)
::
////////////////////////////////////////////////////////////////////////////////////////////////////
モジュレータの出力を正の値に制限して低周波のオシレータの周波数を上げることにより、(サイドバンドを生成することによって)著しく音色が変化させます。
code::
// lfoの周波数を可聴帯域にして.absメッセージをモジュレータに適用する
{ SinOsc.ar(440, 0, 0.571) * SinOsc.kr(880).abs }.scope
// 前の例をリング変調(.absメッセージの無いもの)と比較せよ
// ... 何が違うだろう?
{ SinOsc.ar(440, 0, 0.571) * SinOsc.kr(880) }.scope
::
////////////////////////////////////////////////////////////////////////////////////////////////////
go to link::Tutorials/Mark_Polishook_tutorial/Japanese_version/10::
|