SuperCollider 3 Server Tutorial
SuperCollider 3 サーバーチュートリアル

To follow this tutorial you should read 
	Server-Architecture
and
	Server-Command-Reference

このサーバーチュートリアルとともに
	Server-Architecture
と
	Server-Command-Reference
も参照することをすすめる

This tutorial also assumes that you are familiar with SuperCollider version 2 since the creating a SynthDef in SC3 is very similar to creating a Synth in SC2.

このチュートリアルは、SuperCollider 2にも精通していることを前提としている。これは、SC3のSynthDef(シンセ定義)がSC2のSynth(シンセ)と共通した点が多いからである。

There are two parts to SuperCollider. One part is the language application and another is  a synthesis server that can run either inside the language application, or as a separate program on the same machine, or run on a different computer across a network connection. The language application sends command messages to the server using a subset of the Open Sound Control protocol.

SuperColliderは２つの要素から成り立っている。一つは、言語アプリケーション部分であり、もう一つは言語アプリケーションの一部としても、外部アプリケーションとしても実行できる、音響合成サーバーである。言語アプリケーションはサーバーへOpen Sound Controlプロトコルの一部をを用いてサーバーへコマンドを送信する。

Booting a Server
サーバーの起動

In order to run sound we need to start a server running. The easiest way to start a server is to click on one of the "Start Server" buttons in the server windows. Sometimes though it is useful to start a server programmatically. To do this we need to get or create a server object and tell it to "boot". Two servers, internal and local, are predefined.

SuperColliderで音を出すにはサーバーを起動する必要がある。最も簡単な方法は、サーバーウィンドウ内にある"Start Server"ボタンをクリックすることである。ただ、場合によってはプログラム内部からサーバーを起動した方が都合がいい場合もある。プログラム内部からサーバーを起動するには、サーバーオブジェクトを新たに作成するか取得し、オブジェクトに対して"boot"コマンドを送る必要がある。サーバーには"local"(ローカル)と"internal"(内部)の二つのサーバーがあらかじめ用意されている。

The internal server runs in the same process as the SuperCollider application.  It is internal to the program itself.
// set the interpreter variable s to the internal server object.
s = Server.internal;

内部サーバーはSuperColliderアプリケーションと同じプロセス内で実行される。プログラム内部に組み込まれている。
//変数 s に内部サーバーオブジェクトを割り当てる
s = Server.internal;

VERY IMPORTANT: This line must be executed for the variable 's' to be set. The mechanics are different depending on your platform. The MacOSX standard is to place the cursor anywhere on this line and press the "Enter" key on the numeric keypad. Pressing the main return key does not execute code! This allows you to write code fragments of multiple lines. To execute a multi-line block of code, select the block and press "Enter." For convenience, a code block can be enclosed in parentheses, and the entire block selected by double-clicking just inside either parenthesis. (For linux or Windows instructions, consult the documentation specific to that platform.)

重要：このコマンド行は必ず実行される必要がある。実行方法は利用しているコンピュータ環境によって異なる。Mac OS Xでの実行方法は、実行したいコマンド行のどこかにカーソルを配置し、"Enter"(エンター)キーを入力する。よく使われる"Retrun"(リターン)キーでは実行されないので注意が必要だ！この方法により、複数行にわたるコマンドも実行できる。複数行のコマンドを実行するには、実行したいコマンドを選択し"Enter"(エンター)キーを入力する。より選択しやすくするには、複数行のコマンドを括弧"( )"でくくり、括弧の部分でマウスをダブルクリックすると一括して選択できる。(LinuxとWindowsでの操作方法はそれぞれの環境に関す露ドキュメントを参照。)

The local server runs on the same machine as the SuperCollider application, but is a separate program, 'scsynth'.
// set the interpreter variable s to the local server object.
s = Server.local;

ローカルサーバーはSuperColliderアプリケーションと同じコンピュータ上で実行されるが、scsynthという別プログラムとして実行される。
//変数 s にローカルサーバーオブジェクトを割り当てる
s = Server.local;

To boot the server you send it the boot message.

s.boot;

サーバーを起動するには、bootメッセージを送る。

s.boot;

To quit the server send it the quit message.

s.quit;

サーバーを終了するには、quitメッセージを送信する。

s.quit;

We can also create a server to run. To create a server object we need to provide the IP address or the server and a port number. Port numbers are somewhat arbitrary but they should not conflict with common protocols like telnet, ftp http, etc. The IP address 127.0.0.1 is defined to mean the local host. This is the IP address to use for running a server on your own machine.

プログラムから新たなサーバーを作成することもできる。新たなサーバーオブジェクトを作るには、サーバーのIPアドレスとポート番号を指定する必要がある。ポート番号にはなにを指定してもかまわないが、telnet、ftp、httpなど一般的なプロトコルのものと重ならない番号を指定する。127.0.0.1というIPアドレスは手元のコンピュータのことをさす。このIPアドレスとを使って、自分のマシンでサーバーを実行する。

// create a server object that will run on the local host using port #58009
s = Server(\myServer, NetAddr("127.0.0.1", 58009)); 

s.boot; //start the server

s.quit; // quit the server

//手元のコンピュータの58009番ポートで動くサーバーオブジェクトを作成
s = Server(\myServer, NetAddr("127.0.0.1", 58009)); 

s.boot; //サーバーを起動

s.quit; //サーバーを終了

It is not possible to boot a server on a remote machine, but if you have one running already or you know of one running, you can send messages to it. You create the server object using the IP address of the machine running the server and the port it is using.

リモートマシンのサーバーを起動することはできないが、あらかじめサーバーが実行されていれば、サーバーオブジェクトにIPアドレスとポート番号を指定することで、メッセージを送ることができる。

// create a server object for talking to the server running on a machine　having 
// IP address 192.168.0.47 using port #57110
s = Server(\myServer, NetAddr("192.168.0.47", 57110)); 

// 192.168.0.47上のポート番号57110で動いているサーバーと接続するための
// サーバーオブジェクトを作成する
s = Server(\myServer, NetAddr("192.168.0.47", 57110)); 

Making Sound
音を作る

(note: This tutorial uses raw OSC commands as described in Server-Command-Reference, rather than the classes Synth and Group.  See those helpfiles also for some simpler ways of working with Synths.  This tutorial explains the basic underlying design of Synths and SynthDefs).

(注釈：このチュートリアルでは、SynthクラスやGroupクラスを用いずに、Server-Command-Referenceにて説明されている基本OSCコマンドを使用している。SynthクラスやGroupクラスの利用方法はそれぞれのヘルプファイルを参照。このチュートリアルではSynthとSynthDefの基本デザインについて説明していく)

Now lets make some audio. 

s = Server.local; // assign it to interpreter variable 's' 

Boot it.

s.boot;

では、なにか音を出してみよう。まずは、サーバーオブジェクトを作成する。

s = Server.local; // 変数 s にローカルサーバーオブジェクトを割り当てる 

作成したサーバーオブジェクトにbootコマンドを送る。

s.boot;

Create a SynthDef. A SynthDef is a description of a processing module that you want to run on the server. It can read audio from the server's audio buses, read control from the control buses and write control or audio back to buses. Here we will create a sine oscillator and send it to audio bus zero.

続いてSynthDef(シンセ定義)を作成する。SynthDefはサーバー上で実行する処理モジュールを定義する。SynthDefではサーバー上のオーディオバスからオーディオを、コントロールバスからコントロール値を入出力できる。ここでは、オーディオバスID 0にサイン波を出力する、サインオシレータを作成する。

(
SynthDef("sine", { arg freq=800;
	var osc;
	osc = SinOsc.ar(freq, 0, 0.1); // 800 Hz sine oscillator
	Out.ar(0, osc); // send output to audio bus zero.
}).writeDefFile;
)

(
SynthDef("sine", { // このSynthDefに sine という名称をつける
	arg freq=800;　// 引数 freq を作成し、800という値を代入
	var osc;　// 変数 osc を宣言する
	osc = SinOsc.ar(freq, 0, 0.1); // 800Hzのサイン派を出力するオシレータを作成
	Out.ar(0, osc); // 出力をオーディオバスID 0へ送る
}).writeDefFile;　// SynthDefをファイルに書き出す
)

Send the SynthDef to the server.  

s.sendSynthDef("sine");

作成したSynthDef sine をサーバーに送信する。

s.sendSynthDef("sine");

Start the sound. The /s_new command creates a new Synth which is an instance of the "sine" SynthDef. Each synth running on the server needs to have a unique ID. Here we give it an ID of 1000. Each synth needs to be installed in a Group. We install it in group zero which is the top level group.

音響生成を開始する。/s_new コマンドによって、SynthDef sine のインスタンスをSynthとして作成する。サーバー上で実行される各Synthには一意のID番号を割り当てる必要がある。ここでは、IDとして1000を割り当てている。各SynthはGroupに属している必要がある。ここでは、ツリー構造の最上位のグループである ID 0 のグループに組み込んでいる。

s.sendMsg("/s_new", "sine", 1000, 1, 0);

Stop the sound.

音響生成を停止する。

s.sendMsg("/n_free", 1000);

Stop the server.

サーバーを停止する。

s.quit;

Using Arguments
引数の使い方

It is useful to be able to specify parameters of a synth when it is created. Here a frequency argument is added to the sine SynthDef so that we can create it 

Synthが作成された後からでの特定のパラメータを操作できるのは使い勝手がよくなる。ここでは、周波数を引数として指定できるよう sine SynthDef を修正する。

s = Server.local; // assign it to interpreter variable 's' 

s.boot;

(
SynthDef("sine", { arg freq;
	var osc;
	osc = SinOsc.ar(freq, 0, 0.1); // 800 Hz sine oscillator
	Out.ar(0, osc); // send output to audio bus zero.
}).writeDefFile;
)

s.sendSynthDef("sine");

s = Server.local; // 変数 s にローカルサーバーを割り当てる

s.boot; // サーバーを起動する

(
SynthDef("sine", { // SynthDefにsineという名称をつける
	arg freq; // freq という引数を作成
	var osc;　// osc という変数を作成
	osc = SinOsc.ar(freq, 0, 0.1); // 変数 osc にサイン派を出力するユニットジェネレータを割り当てる
	Out.ar(0, osc); // 出力をID 0のオーディオバスに送る
}).writeDefFile; // SynthDefをファイルに出力すr
)

s.sendSynthDef("sine"); // サーバーに sine SynthDef を送る

Play a 900 Hz sine wave.
900Hzのサイン波を生成する。

s.sendMsg("/s_new", "sine", 1000, 1, 0, "freq", 900);  // サーバーへ ID 1000ノードとしてsineを新たに作成し、freq引数に900を渡す

s.sendMsg("/n_free", 1000); // サーバーへID 1000のノードの解放命令を送る

Play a 1000 Hz sine wave.
1000Hzのサイン波を生成する。

s.sendMsg("/s_new", "sine", 1001, 1, 0, "freq", 1000); // サーバーへ ID 1001ノードとしてsineを新たに作成し、freq引数に1000を渡す

s.sendMsg("/n_free", 1001); // サーバーへID 1001のノードの解放命令を送る

Playing three voices at once
同時に３つのサイン波を生成する。

(
s.sendMsg("/s_new", "sine", 1000, 1, 0, "freq", 800); // サーバーへ ID 1000ノードとしてsineを新たに作成し、freq引数に800を渡す
s.sendMsg("/s_new", "sine", 1001, 1, 0, "freq", 1001); // サーバーへ ID 1001ノードとしてsineを新たに作成し、freq引数に1001を渡す
s.sendMsg("/s_new", "sine", 1002, 1, 0, "freq", 1202); // サーバーへ ID 1002ノードとしてsineを新たに作成し、freq引数に1002を渡す
)

(
s.sendMsg("/n_free", 1000); // サーバーへID 1000のノードの解放命令を送る
s.sendMsg("/n_free", 1001); // サーバーへID 1001のノードの解放命令を送る
s.sendMsg("/n_free", 1002); // サーバーへID 1002のノードの解放命令を送る
)

Playing three voices at once using bundles. Bundles allow you to send multiple messages with a time stamp. The messages in the bundle will be scheduled to be performed together. The time argument to sendBundle is an offset into the future from the current thread's logical time.

同時に３つの音を合成するにはバンドルを使うと便利である。バンドルは複数のメッセージをタイムスタンプをつけて送ることができる。バンドル内のメッセージはタイムスタンプで指定した時刻に同時に実行される。sendBundleコマンドの時間(タイム)引数は、現在のスレッドの論理時間に対するオフセット時間を指定する。

(
s.sendBundle(0.2, // 0.2秒後に実行するバンドルをサーバークラスが割り当てられている s に送る
	["/s_new", "sine", 1000, 1, 0, "freq", 800], // バンドル内の最初のメッセージ
	["/s_new", "sine", 1001, 1, 0, "freq", 1001], // バンドル内の２番目のメッセージ
	["/s_new", "sine", 1002, 1, 0, "freq", 1202]); // バンドル内の３番目のメッセージ

s.sendBundle(1.2, // 1.2秒後に実行するバンドルをサーバークラスが割り当てられている s に送る
	["/n_free", 1000], // バンドル内の最初のメッセージ
	["/n_free", 1001], // バンドル内の２番目のメッセージ
	["/n_free", 1002]); // バンドル内の３番目のメッセージ
)

Controlling a Synth
Synthのコントロール

You can send messages to update the values of a Synth's arguments.
Synthの引数に対して、値変更のメッセージを送ることができる。

Play a 900 Hz sine wave.
900Hzのサイン波を生成する。

s.sendMsg("/s_new", "sine", 1000, 1, 0, "freq", 900); // サーバーへ ID 1000ノードとしてsineを新たに作成し、freq引数に900を渡す

Change the frequency using the /n_set command. You send the node ID, the parameter name and the value.

続いて、/n_set コマンドを用いて周波数を変更する。各メッセージには制御するノードID、パラメータの名称、そしてその値を指定する必要がある。

s.sendMsg("/n_set", 1000, "freq", 800); // ID 1000のノードにfreq引数として800を設定する
s.sendMsg("/n_set", 1000, "freq", 700); // ID 1000のノードにfreq引数として700を設定する
s.sendMsg("/n_free", 1000); // ID 1000ノードを解放する

Adding an Effect Dynamically
エフェクトを動的に追加

You can dynamically add and remove an effect to process another synth. In order to do this, the effect has to be added after the node to be processed.

あるSynthに対して動的にエフェクト処理を追加・解除することができる。エフェクト処理を追加するには、処理するノードの後にエフェクト処理ノードを追加する必要がある。

(
// ノイズパルスを定義
SynthDef("tish", // tishという名称のSynthDefを定義
	{ 
	arg freq = 1200, rate = 2; // 引数freqとrateを作成しそれぞれの初期値を1200と2に設定
	var osc, trg; // oscとtrgという変数を宣言
	trg = Decay2.ar(Impulse.ar(rate,0,0.3), 0.01, 0.3); // 変数trgにDecay2ユニットジェネレータの結果を割り当てる
	osc = {WhiteNoise.ar(trg)}.dup; // 変数oscにWhiteNoiseユニットジェネレータの結果を割り当てる
	Out.ar(0, osc); // オーディオバス 0 にoscの出力を送る
}).writeDefFile; // SynthDefファイルを書き出す

s.sendSynthDef("tish"); // tishという名称のSynthDefをサーバーへ送る
)

(
// エコーエフェクトを定義
SynthDef("echo", // echoという名称のSynthDefを定義
	{ 
	arg delay = 0.2, decay = 4; // 引数delayとdecayを作成しそれぞれの初期値を0.2と4に設定
	var in; // inという変数を宣言
	in = In.ar(0,2); // 変数inにユニットジェネレータInの結果を割り当てる
	ReplaceOut.ar(0, CombN.ar(in, 0.5, delay, decay, 1, in)); // ReplaceOutユニットジェネレータを使ってオーディオバス 0 の内容を置き換える
}).writeDefFile; // SynthDefファイルを書き出す

s.sendSynthDef("echo"); // echoという名称のSynthDefをサーバーへ送る
)

// パルス音を開始
s.sendMsg("/s_new", "tish", 1001, 1, 0, \freq, 200, \rate, 1.2); // tishという名称のSynthDefをID 1001のノードとして作成し引数を設定

// エフェクトを追加
s.sendMsg("/s_new", "echo", 1002, 1, 0); // echoという名称のSynthDefをID 1002のノードとして作成

// エフェクトを停止する
s.sendMsg("/n_free", 1002); // ID 1002のノードを解放する

// エフェクトを新たに追加
s.sendMsg("/s_new", "echo", 1003, 1, 0, \delay, 0.1, \decay, 4); // echoという名称のSynthDefをID 1003のノードとして作成し引数を設定

// エフェクトの停止
s.sendMsg("/n_free", 1003); // ID 1003のノードを解放する

// パルスの停止
s.sendMsg("/n_free", 1001); // ID 1001のノードを解放する

This works because we added the effect after the other node. Sometimes you will need to use groups or /n_after to insure that an effect gets added after what it is supposed to process.

エフェクト処理ノードをSynthノードの後ろに追加したことでこのように実行できる。場合によってはGroupノードを利用するか、/n_after コマンドを用いてエフェクト処理が必ず処理対象の後ろに追加されるようにする必要がある。

Chaining Effects
エフェクトの連結

Using Control Buses
コントロールバスの使い方

Mapping an Argument to a Control Bus
引数をコントロールバスに割り当てる

(
// コントローラを定義
SynthDef("line", // lineという名称のSynthDefを定義
	{ 
	arg i_bus=10, i_start=1000, i_end=500, i_time=1; // 引数としてi_bus、i_start、i_end、i_timeを作成しそれぞれ初期値を設定
	ReplaceOut.kr(i_bus, Line.kr(i_start, i_end, i_time, doneAction: 2)); // ReplaceOutを使ってi_busに設定されているノードIDのコントロールバスを置き換える
}).writeDefFile; // SynthDefファイルを書き出す
s.sendSynthDef("line"); // サーバーにlineという名称のSynthDefを送る
)

Play a 900 Hz sine wave.
900Hzのサイン波を再生

s.sendMsg("/s_new", "sine", 1000, 1, 0, "freq", 900); // sineという名称のSynthDefをID 1000のノードとして作成し引数を設定する

Put a frequency value on the control bus.
周波数の値をコントロールバスに設定する

s.sendMsg("/c_set", 10, 1000); // ID 10のコントロールバスに1000という値を設定する

Map the node's freq argument to read from control bus #10.
ノードのfreq引数にID 10のコントロールバスから値を読み込むよう設定する

s.sendMsg("/n_map", 1000, \freq, 10); // ID 1000のノードのfreq引数にコントロールバス ID 10を割り当てる

Change the value on the control bus.
コントロールバスの値を変更する

s.sendMsg("/c_set", 10, 1200); // ID 10のコントロールバスの値を1200に変更する

Start a control process that writes to bus #10. 
The EnvGen doneAction will free this node automatically when it finishes.
コントロールバスID 10へ値を書き込むSynthDefを開始する。
EnvGen(エンベロープジェネレータ)のdoneActionメソッド(コマンド)により終了時に自動的にノードが解放される

s.sendMsg("/s_new", "line", 1001, 0, 0); // lineという名称のSynthDefをID 1001のノードとして作成する

Free the node.
ノードを解放する

s.sendMsg("/n_free", 1000); // ID 1000のノードを解放する

Gating Envelopes
エンベロープの制御

Adding a GUI
GUI(Graphical User Interface)の追加

Using Buffers
バッファの使い方

Filling Wavetables
波形テーブルの使い方

Frequency Domain Processing
周波数領域での処理方法

Sequencing with Routines
ルーチンを使ったシーケンス

(
var space,offset,timer, saw, envsaw, sampler, delay; // 変数を宣言する

SynthDef("saw", // sawという名称のSynthDefを定義
	{ 
	arg out=100, pan=0, trig=0.0, freq=500, amp=1, cutoff=10000, rezz=1; // 引数とその初期値を設定
	freq = Lag.kr(freq,0.1); // 引数freqにLagユニットジェネレータの結果を割り当てる
	Out.ar(out,Pan2.ar(RLPF.ar(Saw.ar([freq,freq*2],amp),cutoff,rezz),pan)); // 
	}
).load(s); // サーバー s にSynthDefを直接送る

SynthDef("envsaw",
	{ 
	arg out=100, pan=0, dur=0.5, freq=500, amp=1, cutoff=10000, rezz=1;
	var env;
	env = EnvGen.kr(Env.perc(0.01, dur, 0.2), doneAction:0, gate:amp);
	Out.ar(out,Pan2.ar(RLPF.ar(Saw.ar(Lag.kr(freq,0.1),env),cutoff,rezz)*amp,pan));
	}
).load(s);    

SynthDef("delay",
	{ 
	arg out=0, delay = 0.4, decay = 14;
	var in;
	in = In.ar(out,2);
	Out.ar(out, CombN.ar(in, 0.5, delay, decay, 1, in));
	}
).load(s);

SynthDef("sampler",
	{ 
	arg sample, trig=1,rate=1.0,out=0,bufnum=0,pan=0,amp=1, dur=0.25;
	var env;
	env = EnvGen.kr(Env.perc(0.001, dur, 0.001), doneAction:2);
	Out.ar(out,
		Pan2.ar(
		PlayBuf.ar(1,bufnum,rate,InTrig.kr(trig),0,0)*amp,pan);
		)
	}
).load(s);

Tempo.bpm = 120;
timer = BeatSched.new;
offset = Tempo.tempo.reciprocal;

space = Buffer.read(s,"sounds/a11wlk01.wav");

saw = Synth("saw");
delay = Synth.after(saw,"delay", [\decay, 20]);

timer.sched(0,{
	var r;
	r=Routine({ var wait, freq, cutoff,rezz;
	wait = Pseq([2],inf).asStream;
	freq = Pseq([30,40,42,40],inf).asStream;
	cutoff = Pfunc({500.rand2+1000}).asStream;
	rezz = 0.5;
	inf.do({saw.set("freq", freq.next.midicps, "cutoff", cutoff.next, "rezz", rezz, "amp", 0.1, "out", 0);
    (wait.next*offset).wait});});
    timer.sched(0,r); 
});

timer.sched(0,{
	var r;
	r=Routine({ var wait, rate;
	wait = Pseq([0.25],inf).asStream;
	rate = Pfunc({0.5.rand}).asStream;
	inf.do({Synth.before(delay, "sampler", [\bufnum, space.bufnum, \trig, 1, \amp,0.1, \rate, rate.next, \dur, wait.next]);    
    (wait.next*offset).wait});});
    timer.sched(0,r); 
});

)

Sequencing with Patterns
(
//sappy emo electronica example... 
Tempo.bpm = 120;
SynthDef("patternefx_Ex", 
	{ 
	arg out, in; 
	var audio, efx;
	audio = In.ar([20,21],2);
	efx=CombN.ar(audio, 0.5, [0.24,0.4], 2, 1); 
	Out.ar([0,1], audio+efx);
	}
).load(s);

Synth.new("patternefx_Ex");

SynthDef("pattern_Ex", 
	{ 
	arg out, freq = 1000, gate = 1, pan = 0, cut = 4000, rez = 0.8, amp = 1;
	Out.ar(out,
		Pan2.ar(
			RLPF.ar(Pulse.ar(freq,0.05),cut, rez),pan) * EnvGen.kr(Env.linen(0.01, 1, 0.3), gate, amp, doneAction:2);
		) 
	}
).load(s);

SynthDef("bass_Ex", 
	{ 
	arg out, freq = 1000, gate = 1, pan = 0, cut = 4000, rez = 0.8, amp = 1;
	Out.ar(out,
		Pan2.ar(
			RLPF.ar(SinOsc.ar(freq,0.05),cut, rez),pan) * EnvGen.kr(Env.linen(0.01, 1, 0.3), gate, amp, doneAction:2);
		) 
	}
).load(s);

SynthDescLib.global.read;

Pseq([

Ptpar([
0,Pbind(\instrument,\pattern_Ex, \out, 20, \dur,Pseq([2],16), \root,[-24,-17], \degree,Pseq([0,3,5,7,9,11,5,1],2), 	\pan,1,\cut,Pxrand([1000,500,2000,300],16), \rez,Pfunc({0.7.rand +0.3}), \amp,0.12),

0.5,Pbind(\instrument,\pattern_Ex, \out, 20, \dur,Pseq([Pseq([2],15),1.5],1),  \root,-12, \degree,Pseq([0,3,5,7,9,11,5,1],2), \pan,-1,\cut,2000, \rez,0.6, \amp,0.1);
]),

Ptpar([
0,Pbind(\instrument,\pattern_Ex, \out, 20, \dur,2, \root,[-24,-17], \degree,Pseq([0,3,5,7,9,11,5,1],inf), 	\pan,1,\cut,Pxrand([1000,500,2000,300],inf), \rez,Pfunc({0.7.rand +0.3}), \amp,0.12),

0,Pbind(\instrument,\bass_Ex, \dur,1, \root,-24, \degree,Pseq([0],inf), \pan,0, \cut,128, \rez,0.1, \amp,0.3),

0.5,Pbind(\instrument,\pattern_Ex, \out, 20, \dur,2, \root,-12, \degree,Pseq([0,3,5,7,9,11,5,1],inf), \pan,-1,\cut,2000, \rez,0.6, \amp,0.1);
]);

]).play;

)