2016年6月9日木曜日

UGenの音量を調整 - Env, EnvGen

MIDIのADSRを調整することを、
SuperColliderのEnvクラスを用いて行います。

次のコードを実行すると、下の図が表示されます。

実行例:
Env.linen(0.01, 1, 1, 1, 0).plot


Envのlinenメソッドを呼び出しています。
その名前の通り、直線的に値が描かれます。

linen(attackTime, sustainTimereleaseTimelevel, curve)

です。

曲線的な動きにするならば、curveの箇所の値を変えてやると良いです。

実行例:
Env.linen(0.01, 1, 1, 0.8, -5).plot


このような図がプロットできます。

では、Envクラスを用いて発音の長さを調整してみます。
そのために EnvGenクラスを用います。

先ほど Envクラスで作成したオブジェクトをもちいて、
新しくEnvGenクラス(UGen)を作成します。


実行例:
{
  var env = Env.linen(0.01, 1, 1, 0.8, -5);
  EnvGen.ar(env)
}.plot(3)




それでは、これをSinOscと重ね合わせたのが次のコードです。


実行例:
{
  var env = Env.linen(0.01, 1, 1, 0.8, -5);
  SinOsc.ar(440) * EnvGen.ar(env)
}.plot(3)



簡単に音量調整できました。

また、Env.linenメソッド以外にも、Env.newメソッドを使って、
Envクラスを作成する方法もあります。

実行例:
Env.new([0, 1, 0.8, 0], [0.5, 1, 1], [0, 0, -5]).plot



Env.newでは、配列で

『音量』
『前の値からの経過時間』
『傾きの種類』

を指定します。

実行例:
{
  var env = Env.new([0, 1, 0.8, 0], [0.5, 1, 1], [0, 0, -5]);
  var envGen = EnvGen.ar(env);
  SinOsc.ar(440) * envGen
}.play



2016年6月8日水曜日

UGenでmulの値にUGenを用いて音量を編集する

SinOscなどUGenの引数には、
出力される値を掛ける引数がありますが、
その引数にSinOscなどを用いることで、
周期的に音量が変化するサウンドをつくれます。


実行例:
{
  var vol = SinOsc.kr(1, 0, 0.5, 0.5);
  SinOsc.ar(440, 0, vol)
}.play


波形図(with SinOsc)

周期的に音量が小さくなったり大きくなったりを繰り返します。


変数 vol に用いている SinOsc.kr(1, 0, 0.5, 0.5)は、
1Hz のサイン波に0.5をかけて 0.5 足したものです。
音量になるので、値が負の数にならないようにしています。


他のUGenを使って様々な効果がねらえます

実行例2(LFNoise2):
{
  var vol = LFNoise2.ar(1, 0.5, 0.5);
  SinOsc.ar(440, 0, vol)
}.play



波形図  ( with LFNoise2)

音量の大小の変化はランダムに変わります。


実行例3(LFSaw):
{
  var vol = LFSaw.ar(1, 0, 0.5, 0.5);
  SinOsc.ar(440, 0, vol)
}.play


波形図( with LFSaw)

無音から直線的に大きくなる・・・の繰り返しです。
※無音に戻る際にノイズが起こります。



実行例4(LFPulse):
{
  var vol = LFPulse.kr(1, 0, 0.5);
  SinOsc.ar(440, 0, vol)
}.play


波形図( with LFPulse)

オン・オフの繰り返しです。
1から0に移るタイミングでノイズが発生します。

ノイズ生成 - WhiteNoise

{WhiteNoise.ar()}.play

すべての周波数で一定の音量の出力を行う波形を出力します。


周波数値




プロット図

ノイズ生成 - PinkNoise

ピンクノイズを生成します。

{PinkNoise.ar()}.play

引数は

・掛ける値
・足す値

ですが、特に指定する必要はありません。

実行すると、
すべての周波数帯で、
高周波になるにつれて、
音量が小さくなる波形が生成されます。



周波数値


波形(プロット図)





乱数生成にも用いられたりします。

矩形波 - LFPulse

矩形波を出力するには LFPulse を用います。
引数は大体他のUGenと同じく、

・周波数
・位相
・矩形の幅
・掛ける値
・足す値

です。


波形を plot で確認してみると次のようになります。

実行例:
{LFPulse.ar(440, 0, 0.5)}.plot




+1 と -1 の値のみとります。

実際に実行してみると次のような音色になります。

実行例:
{
  var freq = XLine.kr(440, 220, 10);
  LFPulse.ar([freq, freq], 0, 0.5)
}.play

※ 440Hz から 220Hz まで 10秒かけてピッチを変えてます。


ここで、周波数値を見てみると次のような周波数になります。



LFPulse.ar(440)


奇数倍音のみ含む周波数が生成されています。
同じ奇数倍音のみ含む三角波は次のようになります。


LFTri.ar(440)

波形のピークの値の減り方が矩形波と三角波では異なることがわかります。
(三角波の方が値の減り方が大きい)


音源で比較すると次のような具合です。

実行例:
{
  var freq = XLine.kr(440, 220, 10);
  [LFPulse.ar(freq),
    LFTri.ar(freq)]
}.play




ちなみに、のこぎり波(LFSaw)と比較すると次のようになります。

実行例:
{
  var freq = XLine.kr(440, 220, 10);
  [LFPulse.ar(freq),
    LFSaw.ar(freq)]
}.play





矩形の幅


矩形波の引数にあった矩形の幅ですが、
これを調整することで音色を変えていくことができます。

実行例:
{LFPulse.ar(440, 0, width)}.plot


波形 (width = 0.1)
※ 1の割合が極端に少ない



波形(width = 0.5)
※ 1の値と0.5 の値が同じ割合


波形( width = 0.9 )
※ 1の割合が極端に多い


それぞれの音色の違いは、Line関数を用いて、
下のコードのように実行すると分かりやすいと思います。

{
  var width = Line.kr(0.0, 1.0, 5);
  LFPulse.ar(440, 0, width)
}.play

出力される周波数の確認 - FreqScope

plotscope を用いて波形を確認することができますが、
実際に出力されている周波数を確認するために、
FreqScope」クラスを用いることができます。


FreqScope は plot や scope と違って、
別に実行する必要があります。

実行例:

FreqScope.new(400, 200, 0);

引数は(ウインドウの横幅、縦幅、オーディオバスナンバー)です。
続けて背景色や線の色など指定できますが、
デフォルトで十分です。

3つ目の引数は、確認するオーディオのバスナンバーですが、
特に指定がなければで大丈夫です。




終了する際には、画面を閉じる前に、
パワー(緑色のボタン)をオフにしておくようにと、
ヘルプファイルに書いてあります。
"stop"と"start" の切り替えをうまくして、
CPUパワーを節約するようにとのことだと思います。


また、GUIでは、パワーのオン・オフの他に、

・確認するオーディオバスナンバーの指定

・周波数を対数(Log)・比例(Linear)で表示するかどうか

・確認するデジベル(指定した値以下を無視)をどうするか

などオプションが指定できます。




実行すると、(デフォルトでは)真っ黒の何もない画面が出力されます。
縦軸が音量、横軸が周波数です。

横軸・縦軸のメモリは、GUIで指定したオプションで変わってきます。



例えば、FreqAnalyzer を起動した状態で次のコードを実行すると、

{SinOsc.ar(440)}.play

対数(Log)表示にしていた場合、




このように表示されますが、比例(Linear)の場合だと、




このように横軸が変化することがわかります。


現在出力している音色の周波数を確認するのには、
もってこいの機能です。

三角波形 - LFTri

三角波を出力する UGen が LFTri です。


{LFTri.ar(440)}.play


引数は他のUGenと大体同じです。

LFTri.ar(周波数、位相、掛ける値、足す値

になります。

波形の形を plot で見ると次のようになります。


LFTri ( 440Hz )


-1 から +1 の間を直線的に移動する繰り返しです。

LFSaw と似ていますが、
LFSawが -1 から +1まで進んだ後、
すぐに -1 に値が戻るのに対し、
LFTri は +1 から -1 まで直線的に戻る点で、大きく違います。



LFSaw ( 440 Hz )




出力される周波数値でそれぞれの違いを確認すると次のようになります。


LFTri ( 440 Hz )



LFSaw ( 440 Hz )


倍音の数がこんなにも異なることがわかります。

のこぎり波(LFSaw)はすべての整数倍音を含んでおり、
三角波(LFTri)は、奇数倍音のみ含んでいるようです。

参考:
Wikipedia (https://ja.wikipedia.org/wiki/のこぎり波)
Wikipedia (https://ja.wikipedia.org/wiki/三角波_(波形))

倍音の違いで音色がこうも変わる良い例だとおもいます。

出力する際のチャンネル数

作成したコードを実行する際に、
複数チャンネルに出力(実行)することができます。


実行例:

{SinOsc.ar(440)}.play


例えば上のコードでは、
440Hz のサイン波が 1 チャンネルで出力されます。

これだと、ヘッドフォンで聴いた時には、
左チャンネル( 1ch )からしか出力されません。

複数チャンネルで実行する際には、
例えば次のようなコードにします。


実行例:

{SinOsc.ar([440, 440])}.play

このように、UGenの引数を配列で渡すと、
2チャンネルでの出力になります。
ヘッドフォンで聴いても、ステレオでの出力になるはずです。


配列の要素数を増やしていけば、
その分出力されるチャンネル数が増えていきます。

波形確認 - scope

波形の確認に用いる関数として、
plot の他に scope もあります。

plot がその時点で指定された秒の波形なのに対して、
scope は今現在の値となり、動的に表示が更新されます。



実行例:

{LFTri.ar([440])}.scope

※ 三角波( 440 Hz )の出力を確認してみます。



ステレオでの出力だと次のようになります。

実行例:

{LFTri.ar([10, 50])}.scope



オーディオレート( ar )だけでなく、
コントロールレート( kr )の値も確認できます。

波形確認 - plot

plot を用いれば、生成されている波形を確認することができます。

例えば、のこぎり波の確認をするならば、次のようなコードになります。

({LFSaw.ar(440)}).plot

これを実行すると、別ウインドウが開き、次のような結果になります。



※ SC3.7 になって plot の画面も若干変わりました。

plot( 秒) とすることで、指定した秒数の波形を確認できます。(便利)

コード例:
({LFSaw.ar(440)}).plot(1)

実行例:

ミリセカンドで引数に指定できるようです。

 コード例:
({LFSaw.ar(440)}).plot(0.5)

実行例:



ちなみにステレオの波形をみようとすると、次のようなプロットが生成されました。

コード例:
({LFSaw.ar([440, 220])}).plot(0.5)
※ 440Hz と 220Hz



上下に並んで生成されます。
上の例だと220Hzと440Hzなので、ちょうど1:2の波形ができていますね。



また、いくつかキーボードショートカットがあり、例えば、
出力されたプロットのウインドウを選択して、
"+" や "-" を入力すると、
プロット図を拡大・縮小したりできます。

他には、Alt + マウスでクリックで、値をポストウインドウに出力できたり、
描画方法を変えたりできます。

詳しくは plot のヘルプファイルにキーボードショートカットが載っています。


MIDIノートナンバーと周波数を変換 - midicps / cpsmidi

MIDIノートナンバーを周波数へ変換

69.midicps    // => 440
midicps(69)   // => 440

周波数値をMIDIの値に変換

cpsmidi(440) // => 69
440.cpsmidi   // => 69

次のコードの実行結果は同じになります。

{SinOsc.ar(440)}.play
{SinOsc.ar(69.midicps)}.play

SuperCollider 3.7

Git Hub
https://github.com/supercollider/supercollider

  • SuperCollider 3.7 was released on March 13, 2016

http://doc.sccode.org/Guides/News-3_7.html

いつの間にか SC3.7がリリースされていたので、
早速導入しました。

ぱっと見感じた部分は、

・行番号がなぜか表示されていない!
 (行を選択すると表示されるのだけど・・・)

・Shift + Enter で実行できていたのが、実行できない。
 メニューには「行を実行」とあるのだけど・・・。
 コマンド + Enter で一応実行できるもののちょっと不便。


自分の環境にのみ起こっているのではなかろうか?

2016年6月1日水曜日

変数

SuperColliderで面白い音楽を作るとき、
変数を用いていけばスマートな(分かりやすい)音楽を作っていくことができます。

宣言方法は
var 変数名 = 内容;
です。
変数名は、小文字のアルファベットから始める必要があります。

しかし、"s" はserverとして用いられているので、
使えない変数名もあります。




また、他のプログラミング言語と異なる点として、
途中で変数宣言をした際にエラーとなります。
例えば、

var a, b, c;
a=10;
b=16;
c=8;
a+b+c;
var d;
d = a+b+c;

このコードを実行すると、

ERROR: syntax error, unexpected VAR, expecting $end
  in file 'selected text'
  line 6 char 3:

  var d;
  ^^^
  d = a+b+c; 

構文エラーになってしまいます。
なので、

var a, b, c;
var d;
a=10;
b=16;
c=8;
a+b+c;
d = a+b+c;

変数の宣言は頭で行う必要があります。


変数を用いた例として、
まず、次のようなコードがあったとします。

SupperColliderBook Figure1.6より

({
Blip.ar(
TRand.kr(
100, 1000,
Impulse.kr(Line.kr(1, 20, 60))),
TRand.kr(
1, 10, Impulse.kr(Line.kr(1, 20, 60))),
Linen.kr(
Impulse.kr(Line.kr(1, 20, 60)),
0,
0.5,
1/Line.kr(1, 20, 60))
)
}.play)

実行例:


このコードは、変数のでてくるセクションの前にあるので、
変数が使われていません。


これを変数を用いて書き換えたのが次のコードです。

({
var vco, vcf, vca;
var interval = Line.kr(1, 20, 60);
var trigger=Impulse.kr(interval);
var attack = 0, sustin = 0.5;
vco = TRand.kr(100, 1000, trigger);
vcf = TRand.kr(1, 10, trigger);
vca = Linen.kr(trigger, attack, sustin, 1/interval);
Blip.ar(vco, vcf, vca)
}.play)

これで先と同じ結果(TRandを使っているので音は違いますが)になります。
しかし、このままではモノラルなので、これをステレオに変えます。

Blip.ar(vco, vcf, vca)

となっている部分を、

Blip.ar( [vco, vco] , vcf, vca)

とします。


実行例:



後から見直した時に分かりやすい変数名になるように、
また、コメントがなくとも、ある程度何をしているか分かるように、
うまくコーディングしなければならないのは、
どのプログラミング言語でも同じですね。

"ar" と "kr" の違い

UGenなどでは 引数を与えるのに、
ar( ... ) で与える場合と kr ( ... ) で与える場合があります。

arAudio Rate
krControl Rate
です。

Control Rate なのに crではなく、krなのは、
Pythonでclassが予約語になっているために、
klassと記すのと同じ理由じゃないかと思います。

ar は、マシンのサンプリングレートごとに計算が行われ、
kr は、1秒に複数回計算が行われます。

実行例:
{SinOsc.ar(440)}.plot



{SinOsc.kr(440)}.plot





よって、arよりもkrのほうが、マシンにかかる負荷が少ないため、
無駄なコストを抑えることができます。

しかし、音信号処理を行う主要な部分は、
サンプリングレートごとに計算を行う必要があるので、arでないと動きません。

{SinOsc.ar(440)}.play → 発音される

{SinOsc.kr(440)}.play → 発音されない

信号を受け取り次第ランダムな値を生成 - TRand

TRand.ar(kr) ( 範囲最小値、最大値、信号)

第3引数に信号を受け取り、
その信号が入り次第、
指定された範囲内の値をランダムに生成する関数です。

これ単体ではなく、複数のUGenと組み合わせて、
様々な音色を生み出すのに用いていくのに使います。

信号の例:
Impulse.kr( Line.kr( 1, 10, 10))

マウスで値をコントロール - MouseX, MouseY

マウスの現在位置で、
PMOscの引数の値をコントロールするプログラムです。

実行例:
{PMOsc.ar([440, 440], MouseX.kr(1, 1000), MouseY.kr(1, 1000))}.play



マウス(カーソル)の現在位置を渡すには、

横位置なら  MouseX
縦位置なら  MouseY

を用います。

また引数(kr)に、現在位置に対応する値を渡します。
MouseX.kr(最小値、最大値)

UnitGenの引数に設定すると、
それぞれの値がどのような効果を生むのか、
非常にわかりやすくなると思います。

また、初期値では、値は線形に増加しますが、
第3引数に1を設定すると、指数関数的に値が増えてきます。

2016年5月31日火曜日

ヘルプファイルの閲覧


SCのヘルプファイルは、関数などの説明が非常に充実しています。



調べたい部分を選択し、
Macならコマンド+d 、Windows環境ならF1で、
ヘルプウインドウに詳細や、実行例が表示されます。


インパルス オシレータ - Impulse

{ Impulse.ar([440, 440], 0, 0.2, 0) }.play

引数は他のオシレータと同じく、

ar(周波数、位相、掛ける値、足す値)

になります。

{Impulse.ar([440, 440], 0, 0.2, 0)}.plot




{Impulse.ar([440, 440], 0, 0.5, 0)}.scope




Band Limited ImPulse - Blip

帯域制限を用いたインパルス・ジェネレータ

Band Limited ImPulse

Blipについては次のWEBサイトが分かりやすく解説しています。



指定した倍音を重ねて出力する関数ですが、
ただ単純に重ねるのではなく、
ノイズになる無駄な部分をカットする処理を行っているようです。


{Blip.ar(440, 1, 1, 0)}.plot
440Hz で倍音を1つとして出力。



普通のサイン波です。

{Blip.ar(440, 2, 1, 0)}.plot
倍音を2つにしたときに、振幅がうまく調整されているのが分かります。


{Blip.ar(440, 3, 1, 0)}.plot



{Blip.ar(440, 5, 1, 0)}.plot




{Blip.ar(440, 10, 1, 0)}.plot



{Blip.ar(440, 100, 1, 0)}.plot



{Blip.ar(440, 200, 1, 0)}.plot




倍音の数が200ほどにもなると、
帯域制限が効いて、
それぞれの周波数の振幅が、
はっきりと調整されていることが分かります。


音源サンプル

{ Blip.ar([523.3/4, 523.3/4],Line.kr(1,100,20),0.2) }.play;


使いようで非常に面白い効果が期待できそうです。