見出し画像

ちょっと気の利いたオシレーター

タイトルが謎かもしれないですが・・・今日も書きます。
個人的に「気が利いてるなぁ」とか「便利だなぁ」と思っているクラスについてです。
5つほどピックアップします。


(まずcommand+bでサーバ起動して音を出す準備をします。)
(メニューからBootSeverを選択してもOKです。)


SyncSaw


これ、オシレーターシンクができるノコギリ波です。
オシレーターシンクとは・・・
AとBふたつのオシレーターを使いオシレーターAの波形周期をオシレーターBの周期で強制的にリセットする手法で、ひとつのノコギリ波だけでは得られない独特な倍音を得られる機能です。
多くのアナログシンセに搭載されていて、メーカーによってハードシンクとも呼ばれます。


オシレーターシンクのしくみ


SyncSawのパラメータを見てみると、下記のようになっていて、freqを入れる箇所が2箇所あります。
SyncSaw.ar(syncFreq: 440.0, sawFreq: 440.0, mul: 1.0, add: 0.0)

ひとつ目が音色をつくる用(syncFreq)、もうひとつが周期を決定する用(sawFreq)です。

*注意*
sawFreqのほうがsyncFreqよりも大きい数値である必要があるとヘルプに書かれています。

双方の周波数を固定値にしてもよいのですが、どちらかを可変させたほうが面白い音が出ます。ヘルプのExampleにいい例があったので転記します。

{ SyncSaw.ar(100, Line.kr(100, 800, 12), 0.3)!2 }.play;

12秒かけて倍音が変化していきます。

この変化尺を下記のように1秒くらいにすると「あ、この音色聴いたことある」になるのではないでしょうか。(アナログシンセでこんなアタック感の音作りがよくあったと思います。)

{ SyncSaw.ar([220, 221], Line.kr(900, 221, 1), 0.3)!2 }.play;

※ひとつ目の周波数は220にしてもよかったのですが、LとRで少しずらしてステレオコーラス感が出るようにしました。

LineではなくSinOscでモジュレートしてもいい感じです。

{ SyncSaw.ar([220, 221], SinOsc.kr(1).range(221, 900), 0.3)!2 }.play;

rangeを狭くしたり広くしたりすることで倍音変化量をコントロールできます。またSinOscの周期の1を他の値にすることで音色変化の速さを変えられます。


VarSaw


LFPulseにwidthパラメータ(duty cycle)があるのと同様に、VarSawはノコギリ波でありながらduty cycleのパラメータを持っています。

VarSaw.ar(freq: 440.0, iphase: 0.0, width: 0.5, mul: 1.0, add: 0.0)

widthの部分がそれです。
widthを0から1に変化させると、波形上のノコギリ波の頂点がずれていきます。

{VarSaw.ar(220, 0, 0)}.plot;
{VarSaw.ar(220, 0, 0.25)}.plot;
{VarSaw.ar(220, 0, 0.5)}.plot;
{VarSaw.ar(220, 0, 0.75)}.plot;
{VarSaw.ar(220, 0, 1)}.plot;


0から数値が増えるにつれ倍音が下がっていき、
widthが0.5のときは三角波が出力されることになります。
そこから数値が増えるにつれてまた倍音が上がっていき1になると逆向きのノコギリ波に。

余談ですがこれ、Alesisのionやmicronについていた機能なんですよね。
(というかion / micronのほうがSuperColliderより後発ですが・・・)
Alesis ion / micron はいいシンセですねー。モジュレーションのルーティングも自由すぎだしFMできてフィルターもたくさんあってオーディオインもついていて。

サイン波で揺らしてやるとこんな感じです。
LRで違う周期で揺らしてみました。

{VarSaw.ar(220, 0, SinOsc.kr([0.4, 0.3]).range(0,1), 0.3)}.play;


SinOscFB


SinOscFBには普通のサイン波にフィードバック入力がついています。
下記はヘルプドキュメントの表記です。

SinOscFB.ar(freq: 440.0, feedback: 0.0, mul: 1.0, add: 0.0)

このSinOscFB単体で、ヤマハなどで言うところのFMシンセのこの状態がシミュレートできることになります。

ヘルプに下記の説明がありますので、feedbackに入れる数値は0〜2piなのかなと思うのですが
The second argument is the amplitude of phase feedback in radians.

pi
//実行すると3.1415926535898と出力されます。

実際のところfeedbackの値が1.2あたりでノコギリ波に近い波形になり、
{SinOscFB.ar(220, 1.2)}.plot;

それ以上の値だとどんどんノイズ化していきます。
{SinOscFB.ar(220, 2)}.plot;

なので0〜1.2くらいの値で使うのが現実的かなぁと思います。


PMOsc


PMOscは「モジュレーションの回」でも少し触れたのですが
2OPのFMシンセのシミュレーションができます。

こういうオペレータ2段積み状態を模していると思われ、まさにFMシンセを思わせる音色が出ます。

ヘルプに書かれているパラメータは下記の通りです。
PMOsc.ar(carfreq, modfreq, pmindex: 0.0, modphase: 0.0, mul: 1.0, add: 0.0)

単純にパラメータの数値をいじるだけで音色変化を色々と楽しめます。
ただ、3番目のパラメータpmindexが0のままだと何の効果も得られません。
その場合carfreqに応じたピッチのサイン波が鳴るだけです。

{PMOsc.ar(220, 220, 0, 0, 0.3)!2}.play;

これだと220Hzのサイン波。

また、4番目のパラメータmodphaseは開始位相なので(SinOsc.arの2番目phaseと同じ役目)、音質そのものは左右しません。PMOscをモジュレータとして使うときなどに威力を発揮するパラメータです。

3番目のpmindexはモジュレータの音量と捉えてよさそうなパラメータです。
実験してみると0から50くらいまでは有効な感触です。

{PMOsc.ar(220, 220, Line.kr(0, 50, 2), 0, 0.3)!2}.play;

modfreqをcarfreqの整数倍にすればちゃんと音程が定まりますし

{PMOsc.ar(220, 440, 3)!2}.play;

非整数倍にすれば非整数倍音を得られます。

{PMOsc.ar(220, 585, 3)!2}.play;


PMOsc単体でも面白いですが、PMOscで他のオシレーターをモジュレートするのもヤバイ感じになります。

{SinOsc.ar(220 + PMOsc.ar(440, SinOsc.kr(0.1, 0, 110), 20, 0, 440), 0, 0.3)!2}.play;



COsc


COscはオシレーターというよりエフェクターです。

Signal.sineFill()の回」でウェーブテーブルを自作して鳴らすことをやりましたが、その時に自作音色を鳴らすのにOscというクラスを使っていました。

例えばこんな感じに。

//	wavetable作成
(
~bfs1 = Buffer.alloc(s, 2048);
~sig1 = Signal.sineFill(1024, [1, 0.5, 0.3, 0.25, 0.2]);
~wt1 = ~sig1.asWavetable;
~bfs1.loadCollection(~wt1);
)

//	鳴らす
{Osc.ar(~bfs1.bufnum, 220, 0, 0.3)!2}.play;


COscクラスはOscクラスにコーラス効果をかけた状態で鳴らすことができます。
なので下記のように書けば先ほどの音色にコーラスがかかります。(結構軽めのコーラス効果です。)

{COsc.ar(~bfs1.bufnum, 220, 0.6, 0.1)!2}.play;

Oscの3番目のパラメータは開始位相ですが、
COscの3番目のパラメータはコーラス効果のうねり(Hz)です。そこがちょっと注意点です。
数値が0だとうねらないです。

また、COscは内部的にはOscをふたつダブらせて再生するしくみのようなので(ヘルプドキュメントより)、音量が少し大きくなります。なので上記コードではmulを0.1に絞りました。

左右チャンネルでうねりの周期に差をつけるといい感じになります。

{COsc.ar(~bfs1.bufnum, 220, [0.6, 0.7], 0.1)}.play;


Oscクラスを使って鳴らすものなら何でもCOscに置き換えることができるので「Buffer.sineの回」で作った波形も同様ですし

// wavetable作成
(
~bfs2 = Buffer.alloc(s, 2048);
~bfs2.sine2([1.25, 4.15, 6.25, 10.15, 12.25, 16.15, 18.25], [1, 1/4, 1/2, 1/8, 1/4, 1/16, 1/8], asWavetable:true);
)

// 鳴らす
{Osc.ar(~bfs2.bufnum, 220, 0, 0.3)!2}.play;

// ステレオコーラス
{COsc.ar(~bfs2.bufnum, 220, [0.6, 0.7], 0.1)}.play;


Env.new().asSignalの回」で作った波形も同様です。

// wavetable作成
(
~bfr = Buffer.alloc(s, 2048);
~sig = Env([0, 1, -1, 0], [0.01, 0.1, 1.0], [4, 0, -4]).asSignal(1024);
~wt = ~sig.asWavetable;
~bfr = ~bfr.loadCollection(~wt);
)

// 鳴らす
{Osc.ar(~bfr.bufnum, 220, 0, 0.3)!2}.play;

// ステレオコーラス
{COsc.ar(~bfr.bufnum, 220, [0.6, 0.7], 0.1)}.play;



<目次へ>
https://note.com/sc3/n/nb08177c4c01

この記事が気に入ったらサポートをしてみませんか?