sc3onlinuxの日記 sc3onlinux Hatena::Blog hatenablog://blog/17680117127138687531 SC IDEでたよ hatenablog://entry/17680117127138687650 2012-10-09T23:23:20+09:00 2019-05-17T20:20:13+09:00 sc3.6alphaが公開されましたが、3.6からIDEが実装されます。こんな画面でSCコーディング。scvimとかscelなんていらなかったんや! 基本 補完やシンタックスハイライトがデフォで実装されていますが、ファイルは.scdを使用しないとダメです。新規にファイル作成した場合は.scdファイルが作成されます。htmlファイルはソース表示、rtfファイルはプレーンテキストに変換されます。今後は、.scd使ってね、ということらしいです。 undoとかredoとかは今までどおりのcmd+z、cmd+shift+zとかデフォルトショートカット。ただし、ことえりのキーバインドは使用できないので注意… <p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/sc3onlinux/20121009231152" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sc3onlinux/20121009/20121009231152.png" alt="f:id:sc3onlinux:20121009231152p:image:w640" title="f:id:sc3onlinux:20121009231152p:image:w640" class="hatena-fotolife" style="width:640px" itemprop="image"></a></span><br /> sc3.6alphaが公開されましたが、3.6から<a class="keyword" href="http://d.hatena.ne.jp/keyword/IDE">IDE</a>が実装されます。こんな画面でSCコーディング。scvimとかscelなんていらなかったんや!</p> <div class="section"> <h4>基本</h4> <p>補完や<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%F3%A5%BF%A5%C3%A5%AF%A5%B9">シンタックス</a>ハイライトがデフォで実装されていますが、ファイルは.scdを使用しないとダメです。新規にファイル作成した場合は.scdファイルが作成されます。htmlファイルはソース表示、rtfファイルはプレーンテキストに変換されます。今後は、.scd使ってね、ということらしいです。<br /> undoとか<a class="keyword" href="http://d.hatena.ne.jp/keyword/redo">redo</a>とかは今までどおりのcmd+z、cmd+shift+zとかデフォルトショートカット。ただし、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%B3%A4%C8%A4%A8%A4%EA">ことえり</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AD%A1%BC%A5%D0%A5%A4%A5%F3%A5%C9">キーバインド</a>は使用できないので注意しましょう。</p> </div> <div class="section"> <h4>セッション</h4> <p>新規にセッションというものが追加されています。これは、画面のレイアウトやファイルを開いている状態を保持する単位。要は、プロジェクトみたいなものですかね。<br /> デフォルトでの保存はメニューからのみ、後述する設定にてショートカット割り当て可能。セッションの切り替えは、cmd+shift+Q。名前の変更や削除は、Session -> Manage Sessionから<br /> 他の<a class="keyword" href="http://d.hatena.ne.jp/keyword/IDE">IDE</a>には普通にある機能ですが便利っすね!</p> </div> <div class="section"> <h4>ビュー</h4> <p>表示画面全般ね。お待ちかね、エディタのタブ化!ファイルを複数開くと勝手にタブを追加して開いてくれます。<br /> タブを複数開いているときは、マウスじゃなくて、キーボードで切り替えたいよね。タブの切り替えは、cmd+opt+→かcmd+opt+←。<br /> View -> Docsにてヘルプブラウザを表示できる。cmd+fで検索窓を開ける、置換はcmd+rな。<br /> <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%DE%A5%F3%A5%C9%A5%E9%A5%A4%A5%F3">コマンドライン</a>もcmd+eで開ける!<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%DE%A5%F3%A5%C9%A5%E9%A5%A4%A5%F3">コマンドライン</a>で{SinOsc.ar()}.playとか書いてreturnすると音が鳴るぜ!<br /> これらはTool Panelって呼ばれるらしい、邪魔になったらescキーで削除だ。<br /> エディタのフォントサイズを変えたい場合は、cmd++とかcmd+-な。今まで通りだ。Show Spaces and Tabsを有効にすると、タブが→、スペースが・とか表示されて気持ち悪いぜ!</p> <div class="section"> <h5>画面分割</h5> <p>cmd+p 2で下に分割、cmd+p 3で右に分割。cmd+p押して離して、すかさず3を押す!<br /> 分割したビューを戻すにはcmd+p 1だ。勢い余って分割しすぎたら、cmd+p 0で全部戻せますよ。<br /> 分割したビューにフォーカスして、タブの切り替え(ドキュメントの切り替えね)のcmd+opt+→とかやってみよう。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%E9%A5%C3%A5%AF%A5%D1%A5%C3%A5%C9">トラックパッド</a>やマウスなんていらないんや。</p> </div> <div class="section"> <h5>フルスクリーン表示もできるでよ!</h5> <p>cmd+shift+f。プレゼンとかする場合は全画面でお願いします。左下になんかデジタル時計も表示されますよ!戻すには、もうっかいcmd+shift+f。</p> </div> </div> <div class="section"> <h4>参照</h4> <p>クラスの実装とか確認したい場合は、文字列を選択して、cmd+iです。リファレンスはcmd+u。試しに、SynthDefを選択して、cmd+i。Look Up Implementationsウィンドウなんてものが表示されます。チラ見して、ドキュメントを閉じる場合は、cmd+w。<br /> ヘルプ確認したい場合は、今まで通りcmd+d。ただし、Post Windowと同じ場所にヘルプブラウザ開いている場合は、自動的にフォーカスしてくれないから、マウスでクリックして選択するんだ。面倒。。。</p> </div> <div class="section"> <h4>実行</h4> <p>じゃあ、補完しまくりつつコード書いたら実行しよう。<br /> まずは、サーバのブートしましょう。cmd+bでをブート(なんかショートカット削除されていたので、たぶん)。<br /> ()で囲った部分をするには、cmd+shift+rだ。(の近くじゃなくても構わないです。選択されたらすかさず、cmd+return。ctl+cとかは使えなくなっているので注意しましょう。</p> </div> <div class="section"> <h4>ショートカット</h4> <p>当然、編集できます。Preferences(cmd+,)を開いて、Shortcuts。例えばセッションを保存するショートカットを作成するには、Filterでsesionとか絞って、Save Session As...を選択。Customにチェックいれて、cmdとshift押しながらsを押すと反映されます。他のショートカットと被ってしまうので、慎重に設定しましょう。</p> </div> <div class="section"> <h4>レイアウト</h4> <p>好きなようにpost windowとかヘルプブラウザを配置出来ます。試しにpost windowというバー部分をドラッグして、右端に移してみましょう。好きに配置かえてね、ってことです。</p> </div> <div class="section"> <h4>いじょう</h4> <p>cmd+mとかも押してみましょう。SCも少しフレンドリーになりましたね!</p> </div> sc3onlinux SuperColliderのエラー出力を理解した気になろう! hatenablog://entry/17680117127138687825 2012-06-03T14:23:40+09:00 2019-05-17T20:20:14+09:00 なんとなくコードを書いていたり、とりあえずコピペしてみて、いざ実行、でエラーが出力されると、エラーなんて読む気がなく、諦めてボケーッとどっかのサイト見てたりして気づいたら、もうこんな時間か!だったりしますよね。そうなる前になんとなくでも良いのでエラー出力を読んでみましょう。 まずは {SinOsc.ar()}}.play; よくやるのが、}を閉じ忘れたり、なんか1個多かったりですね。これは親切にマッチしないよ?と言ってくれるので、修正しやすいです。 /* unmatched '}' in file 'selected text' line 1 char 14 ・ ERROR: Parse er… <p>なんとなくコードを書いていたり、とりあえずコピペしてみて、いざ実行、でエラーが出力されると、エラーなんて読む気がなく、諦めてボケーッとどっかのサイト見てたりして気づいたら、もうこんな時間か!だったりしますよね。そうなる前になんとなくでも良いのでエラー出力を読んでみましょう。</p> <div class="section"> <h4>まずは</h4> <pre>{SinOsc.ar()}}.play; </pre><p>よくやるのが、}を閉じ忘れたり、なんか1個多かったりですね。これは親切にマッチしないよ?と言ってくれるので、修正しやすいです。</p> <pre class="code" data-lang="" data-unlink>/* unmatched &#39;}&#39; in file &#39;selected text&#39; line 1 char 14 ・ ERROR: Parse error in file &#39;selected text&#39; line 1 char 14: {SinOsc.ar()}}.play; ^ ----------------------------------- ・ ERROR: Command line parse failed nil */</pre><p>}がマッチしなくて、それは何番目の文字か、を出力してくれますので、探しやすいですね。</p> <pre>{SinOsc,ar()}.play; </pre><p>タイポするとパースエラーを返してくれるので、これの間違った部分がわかりやすいですね。</p> <pre class="code" data-lang="" data-unlink>/* ・ ERROR: Parse error in file &#39;selected text&#39; line 1 char 8: {SinOsc,ar()}.play; ^ */</pre><p>これも何番目の文字がダメかを出力してくれます。<br /> この手の軽微なミスは間違いを見つけやすいので良いとして、内部のエラーの場合で、かつコードが長くなってくるとどこを修正していいのかさっぱり分からなかったりします。</p> </div> <div class="section"> <h4>きほん</h4> <p>SC3がユーザに返すエラーは3つに分類できます。<br /> 1. エラーメッセージ<br /> 2. エラーを引き起こしたメソッドのレシーバ、もしくはメソッドを呼んだ引数<br /> 3. コールスタック<br /> ※コールスタックについてはググってください。</p><p>例えば、下の<a class="keyword" href="http://d.hatena.ne.jp/keyword/bleach">bleach</a>メソッドを実行してみましょう。なんかpostウィンドウにエラーメッセージが出力されます。結論から書くと、blechメソッドをレシーバである'1'がもっていないということが分かります。</p> <pre class="code" data-lang="" data-unlink>1.blech //1.blech(2)</pre><pre class="code" data-lang="" data-unlink>/* ERROR: Message &#39;blech&#39; not understood. RECEIVER: Integer 1 ARGS: PATH: xxx CALL STACK: DoesNotUnderstandError:reportError 0x104ca2798 arg this = &lt;instance of DoesNotUnderstandError&gt; Nil:handleError 0x104ca29a8 arg this = nil arg error = &lt;instance of DoesNotUnderstandError&gt; Thread:handleError 0x104ca2a58 arg this = &lt;instance of Thread&gt; arg error = &lt;instance of DoesNotUnderstandError&gt; Object:throw 0x104ca2c68 arg this = &lt;instance of DoesNotUnderstandError&gt; Object:doesNotUnderstand 0x104ca2f28 arg this = 1 arg selector = &#39;blech&#39; arg args = [*0] Interpreter:interpretPrintCmdLine 0x116a92368 arg this = &lt;instance of Interpreter&gt; var res = nil var func = &lt;instance of Function&gt; var code = &#34;1.blech &#34; var doc = &lt;instance of CocoaDocument&gt; Process:interpretPrintCmdLine 0x116998148 arg this = &lt;instance of Main&gt; For advice: [http://supercollider.sf.net/wiki/index.php/DoesNotUnderstandError#blech] */</pre><p>ここで、ちょっと復習してみましょう。レシーバ.メッセージ;というのが基本の文となります。この文は"レシーバ"というオブジェクトに対して、"メッセージ"という命令を実行させます。<br /> 要は、"レシーバちゃん"に対して、「おう、お前"メッセージ"しろよ!」と極悪<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B0%A5%E9%A5%DE">プログラマ</a>がいっているわけですね。ここで問題となるので、"レシーバちゃん"が"メッセージ"という行動を理解しているかどうかです。<br /> ・"レシーバちゃん"が聡い場合<br /> 極悪<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B0%A5%E9%A5%DE">プログラマ</a>に"メッセージ"しろと言われた"レシーバちゃん"は"メッセージ"という行動(メソッド)を理解しているため、<br /> 命令された後に"メッセージ"という行動(メソッド)をします。極悪<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B0%A5%E9%A5%DE">プログラマ</a>が望んだ結果が返ってくるわけですね。<br /> ・"レシーバちゃん"が残念な場合<br /> 極悪<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B0%A5%E9%A5%DE">プログラマ</a>に"メッセージ"しろと言われた"レシーバちゃん"は"メッセージ"という行動(メソッド)を理解できないため、<br /> 命令されても"ふぇぇ"とかいって、わけがわからないことを言い出しはじめます。<br /> うん、お前は何を書いているんだ?と。ここでは"ふぇぇ"はpostウィンドウに出力されるエラー内容ですよ。"レシーバちゃん"がわからなかった内容を詳細に教えてくれているわけですね。ここでは"1"が"レシーバちゃん"で、"blech"が”メッセージ”のに該当します。"1"が"blech"メソッドを持っていれば、なんらかの結果が返ってきますが、持っていなければpostウィンドウにエラーメッセージが出力されます。</p> </div> <div class="section"> <h4>よむ</h4> <pre>ERROR: Message 'blech' not understood. </pre><p>ですが、これは素直に"レシーバちゃん"が理解出来なかったことが出力されます。"blech"ってなに、わかんない?ってことです。</p> <pre>RECEIVER: Integer 1 </pre><p>は、"レシーバちゃん"は何者?ということ。<br /> ここでは整数の1が"レシーバちゃん"の正体であるとわかりますね。</p> <pre>ARGS: </pre><p>"メッセージ"の引数です。<br /> 今回は"メッセージ"に引数がないので、ARGS:以下な何も表示されません。1.<a class="keyword" href="http://d.hatena.ne.jp/keyword/bleach">bleach</a>(2);とか実行してみると</p> <pre>ARGS: Integer 2 </pre><p>と出力されます。</p> <pre>PATH: xxx </pre><p>これは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>の場所ですね。気にしなくてもいいです。</p> <pre>CALL STACK: </pre><p>コールスタックが逆順に表示されています。一番上のスタックは一番最近の呼び出し命令ってことですね。<br /> 大抵上から4つはの同じ呼び出し結果を表示させます。まあ、上から4つは無視していいってことです!<br /> DoesNotUnderstandError:reportError<br /> <a class="keyword" href="http://d.hatena.ne.jp/keyword/Nil">Nil</a>:handleError<br /> Thread:handleError<br /> Object:throw<br /> ですね。</p><p>コードブロックを選択して、ハイライトさせて、コードを実行しますよね。そうすると、コードはSCの裏側でごにょごにょされているんですけれど、その一部で<a class="keyword" href="http://d.hatena.ne.jp/keyword/Interpreter">Interpreter</a>クラスのinterpretPrintCmdLineが呼び出されてたりします。<br /> Process:interpretPrintCmdLine<br /> Interpret:interpretPrintCmdLine<br /> の部分も無視していいかと思います。呼び出されなかったりもしますが、ここでは気にしないで下さい。</p><p>で、コールスタックの内容が一番のキモなわけですが、まあ親切すぎてわかりにくいんですよ。</p> </div> <div class="section"> <h4>もうちょいよむ</h4> <pre class="code" data-lang="" data-unlink>Routine({ var a; a = 5; loop { var b; b = 20.rand; b.postln.ecky_ecky_phtang; // &#34;NI!!!!&#34; a.wait; } }).play;</pre><pre class="code" data-lang="" data-unlink>/* a Routine 12 ERROR: Message &#39;ecky_ecky_phtang&#39; not understood. RECEIVER: Integer 12 ARGS: PATH: xxx</pre><p>上記参考</p> <pre class="code" data-lang="" data-unlink>CALL STACK: DoesNotUnderstandError:reportError 0x12064f6d8 arg this = &lt;instance of DoesNotUnderstandError&gt; Nil:handleError 0x11be47ea8 arg this = nil arg error = &lt;instance of DoesNotUnderstandError&gt; Thread:handleError 0x11be4a448 arg this = &lt;instance of Thread&gt; arg error = &lt;instance of DoesNotUnderstandError&gt; Thread:handleError 0x1208b51c8 arg this = &lt;instance of Routine&gt; arg error = &lt;instance of DoesNotUnderstandError&gt; Object:throw 0x120966ee8 arg this = &lt;instance of DoesNotUnderstandError&gt;</pre><p>とりあえず無視</p> <pre class="code" data-lang="" data-unlink> Object:doesNotUnderstand 0x120a81a18 arg this = 12 arg selector = &#39;ecky_ecky_phtang&#39; arg args = [*0]</pre><p>ここでエラーが発生しました。thisに12、selectorに'ecky_ecky_phtang'、argsに[*0]がそれぞれ代入されています。このオブジェクトは12で、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BB%A5%EC%A5%AF%A5%BF">セレクタ</a>として'ecky_ecky_phtang'、引数はないよ、ってことです。で、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BB%A5%EC%A5%AF%A5%BF">セレクタ</a>の'ecky_ecky_phtang'は12がもっていないので、エラーになると。</p> <pre class="code" data-lang="" data-unlink> &lt; FunctionDef in closed FunctionDef &gt; 0x12045d7a8 var b = 12</pre><p>ここではbという変数に12が代入されています。変数に代入される処理があると、< FunctionDef in closed FunctionDef >が呼び出されるようです(たぶん)。</p> <pre class="code" data-lang="" data-unlink> Function:loop 0x120936c78 arg this = &lt;instance of Function&gt;</pre><p>ここでは、Functionのloopメソッドが実行されています。</p> <pre class="code" data-lang="" data-unlink> Routine:prStart 0x1206de328 arg this = &lt;instance of Routine&gt; arg inval = 2421.955160245</pre><p>この部分が、コードを実行したときに一番始めに処理されます。RoutineのprStartが実行されていることが分かります(prStartってなに?ですが、Routineクラスのメソッドですよ)。prStartの引数であるinvalに2421…が代入されていることが分かります。</p> <pre class="code" data-lang="" data-unlink>For advice: [http://supercollider.sf.net/wiki/index.php/DoesNotUnderstandError#ecky_ecky_phtang] */</pre><p>たんなる参考ですね。</p><br /> <p>CALL STACK以下の内容をもうちょっと細かくみてみましょう。CALL STACKは、下から上に沿って実行結果が出力されます。まず、XXX:YYY という部分ですが、これは "ClassName:MethodName"です。Routine:prStartはRoutineクラスのprStartメソッドだということですね。postウィンドウの"ClassName:MethodName"をダブルクリックして、cmd+jすると、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>の該当メソッドを開いてくれます。<br /> エラーになった部分の、Object:doesNotUnderstandですが、実はObjectクラスはdoesNotUnderstandメソッドを持っています。このメソッドを追っていくと、ERRORクラスが呼ばれてpostウィンドウになんかpostlnしているってことが分かったりします。<br /> この"ClassName:MethodName"の下に、インデントされたargが数個出力されています。まず、大抵arg thisがありますが、オブジェクトはなにかを示していると思ってください。Routine:prStart部分ではRoutineの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>、Object:doesNotUnderstandでは数字の12。this以降にさらにargがある場合は、MethodNameの引数になにが代入されているか、を示しています。prStartメソッドには引数としてinvalが内包されています。doesNotUnderstandメソッドにはselectorが。</p> </div> <div class="section"> <h4>おまけ</h4> <p>SCではエラー出力に、ErrorクラスかErrorクラスのサブクラスの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>である、Errorオブジェクトを使います。<br /> Error("This is a basic error.").throw;<br /> これを実行するとERROR: This is a basic errorを出力されます、ERRORの部分に出力させるメッセージを自分でいじれるってことです。<br /> 他の言語と同じくtry、protect文を使って例外処理も書けますよ。</p> <pre class="code" data-lang="" data-unlink>try { 1.blech; } { |error| error.postln }; protect { 1.blech } { |error| error.postln };</pre> </div> sc3onlinux Returns: SC3 on Linux hatenablog://entry/17680117127138688071 2012-01-03T23:37:07+09:00 2019-05-17T20:20:16+09:00 帰ってきたりなっくす! 昨年は爆発的にSCユーザが増えた年となり、かなりの方がSCに興味を持ち、触ってみて、挫折したのではないでしょうか?max6もリリースされ、SCなんていらなかったんや!との気持ちもなきにしもあらずです。 今年一発目は仮想環境上にSC on Linux環境を構築する方法を記載しました。もうこれでmac持ってないよ?とか言い訳はできませんね!linuxで音を扱う際にはなめてかかってはいけません。相当苦労するはめになります。SCをリポジトリからインスコしたからといって音がでるわけではありません。 環境は、仮想化ソフトとしてvirtualbox4.1.8、仮想マシンとしてubun… <p>帰ってきたりなっくす!<br /> 昨年は爆発的にSCユーザが増えた年となり、かなりの方がSCに興味を持ち、触ってみて、挫折したのではないでしょうか?max6もリリースされ、SCなんていらなかったんや!との気持ちもなきにしもあらずです。<br /> 今年一発目は仮想環境上にSC on <a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a>環境を構築する方法を記載しました。もうこれで<a class="keyword" href="http://d.hatena.ne.jp/keyword/mac">mac</a>持ってないよ?とか言い訳はできませんね!<a class="keyword" href="http://d.hatena.ne.jp/keyword/linux">linux</a>で音を扱う際にはなめてかかってはいけません。相当苦労するはめになります。SCを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>から<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%B3">インスコ</a>したからといって音がでるわけではありません。<br /> 環境は、仮想化ソフトとしてvirtualbox4.1.8、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%BE%C1%DB%A5%DE%A5%B7%A5%F3">仮想マシン</a>としてubuntu11.10になります。<a class="keyword" href="http://d.hatena.ne.jp/keyword/vmware">vmware</a>でも構いませんが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/virtualbox">virtualbox</a>だとデフォで実機側に音を渡せます。また、SC開発版は結構仕様が変わっていますので、これを機にビルドして開発版をインストールしてみましょう!</p> <div class="section"> <h4>準備</h4> <div class="section"> <h5><a class="keyword" href="http://d.hatena.ne.jp/keyword/virtualbox">virtualbox</a></h5> <p><a href="https://www.virtualbox.org/">https://www.virtualbox.org/</a><br /> バイナリ落としてインストールする。問題ない。</p> </div> <div class="section"> <h5><a class="keyword" href="http://d.hatena.ne.jp/keyword/ubuntu">ubuntu</a></h5> <p><a href="http://www.ubuntulinux.jp/">http://www.ubuntulinux.jp/</a><br /> 日本語Remix CDイメージのダウンロード。<a class="keyword" href="http://d.hatena.ne.jp/keyword/virtualbox">virtualbox</a>の新規<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%BE%C1%DB%A5%DE%A5%B7%A5%F3">仮想マシン</a>をデフォルトで作成して、isoからインストール。最近の<a class="keyword" href="http://d.hatena.ne.jp/keyword/linux">linux</a>ディストリは驚くほど親切だ。数クリックでインストールが完了する。<a class="keyword" href="http://d.hatena.ne.jp/keyword/ubuntu">ubuntu</a>のインストールが完了したら、とりあえずアップデートしておく。インストールからアップデート完了まで結構時間がかかる。コーヒーでも淹れてこよう。ココアでも良い。<br /> なお、以降ターミナルで作業することになるが、なぜかxtermが前面にあるが使いづらいためアプリケーションの検索でterminal(端末)を探しておこう。</p> </div> </div> <div class="section"> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%B3">インスコ</a></h4> <div class="section"> <h5><a class="keyword" href="http://d.hatena.ne.jp/keyword/supercollider">supercollider</a></h5> <p>先はまだまだ長い。ダレる前にSCを入れてしまおう。</p> <pre>$ sudo apt-get install git clone --recursive git://<a class="keyword" href="http://d.hatena.ne.jp/keyword/supercollider">supercollider</a>.git.<a class="keyword" href="http://d.hatena.ne.jp/keyword/sourceforge">sourceforge</a>.net/gitroot/<a class="keyword" href="http://d.hatena.ne.jp/keyword/supercollider">supercollider</a>/<a class="keyword" href="http://d.hatena.ne.jp/keyword/supercollider">supercollider</a> $ cd <a class="keyword" href="http://d.hatena.ne.jp/keyword/supercollider">supercollider</a> $ cat README_<a class="keyword" href="http://d.hatena.ne.jp/keyword/LINUX">LINUX</a>.txt </pre><p>なにやら面倒なことが書いてあるがbuild requirements (<a class="keyword" href="http://d.hatena.ne.jp/keyword/debian">debian</a> users)に書いてあるパッケージを入れよう。</p> <pre>$ sudo apt-get install build-essential libqt4-dev libqtwebkit-dev libjack-dev libsndfile1-dev libasound2-dev libavahi-client-dev libicu-dev libreadline6-dev libfftw3-dev libxt-dev pkg-config cmake </pre><p>ここでcmakeするのはまだ早い。実は足りないものがあるので入れておこう。</p> <pre>$ sudo apt-get install <a class="keyword" href="http://d.hatena.ne.jp/keyword/emacs">emacs</a> libcwiid-dev </pre><p>これでビルドする準備は整ったはずだ。</p> <pre>$ <a class="keyword" href="http://d.hatena.ne.jp/keyword/pwd">pwd</a> xxx/<a class="keyword" href="http://d.hatena.ne.jp/keyword/supercollider">supercollider</a> $ mkdir build $ cd build $ cmake .. $ make $ sudo make install </pre><p>これでSCの最新版インストール完了。ビルドにちょっと時間がかかるけれども、SCのインストールは特に難しくはないはずだ。ただ、<a class="keyword" href="http://d.hatena.ne.jp/keyword/linux">linux</a>はそれほど甘くない!残念ながらまだまだ音は出ない。めげずに続けて必要なことをやっていこう。</p> </div> <div class="section"> <h5>さらに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%B3">インスコ</a></h5> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/linux">linux</a>で音を扱うには<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AB%A1%BC%A5%CD%A5%EB">カーネル</a>をlowlatencyかrealtimeにする必要がある。ブチブチさせたくないならな。今回選択した<a class="keyword" href="http://d.hatena.ne.jp/keyword/ubuntu">ubuntu</a>ではこの辺りが若干ごたごたしている。とくに今回いれた11.10はいまいちよく分からない部分がある。安定して、さらに日本語記事がアップされるまで気長に待とうじゃないか。<br /> ここではlowlatency<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AB%A1%BC%A5%CD%A5%EB">カーネル</a>を入れてみよう。<br /> <a href="https://wiki.ubuntulinux.jp/UbuntuStudioTips/Setup/Kernels">https://wiki.ubuntulinux.jp/UbuntuStudioTips/Setup/Kernels</a><br /> ”PPAからLowLatency<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AB%A1%BC%A5%CD%A5%EB">カーネル</a>やRealtime<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AB%A1%BC%A5%CD%A5%EB">カーネル</a>を導入する方法”に従う。</p> <pre>$ sudo add-apt-repository ppa:abogani/ppa $ sudo apt-key adv --recv-key --keyserver keyserver.<a class="keyword" href="http://d.hatena.ne.jp/keyword/ubuntu">ubuntu</a>.com F141B61E $ sudo apt-get update $ sudo apt-get install <a class="keyword" href="http://d.hatena.ne.jp/keyword/linux">linux</a>-lowlatency </pre><p>低レイテンシ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AB%A1%BC%A5%CD%A5%EB">カーネル</a>を加えたので<a class="keyword" href="http://d.hatena.ne.jp/keyword/grub">grub</a>の設定を変えておこう。</p> <pre>$ sudo vi /boot/<a class="keyword" href="http://d.hatena.ne.jp/keyword/grub">grub</a>/<a class="keyword" href="http://d.hatena.ne.jp/keyword/grub">grub</a>.cfg set default="2"に変更 </pre><p>13行めのset default="0"をset default="2"にしておく。menuentryの3つ目が先ほどいれた<a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a> 3.0.0-13-lowlatencyだからだ。一旦リブートして<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AB%A1%BC%A5%CD%A5%EB">カーネル</a>がlowlatencyに変更されたのを確認しよう。</p> <pre>$ sudo reboot ... $ <a class="keyword" href="http://d.hatena.ne.jp/keyword/uname">uname</a> -a <a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a> xxx 3.0.0-13-lowlatency </pre><p>OKだ。<a class="keyword" href="http://d.hatena.ne.jp/keyword/linux">linux</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AB%A1%BC%A5%CD%A5%EB">カーネル</a>3.0にビビるな。でもまだまだ設定は続く。</p> <pre>$ sudo adduser 自分 audio $ sudo su -c 'echo @audio -rtprio 99 >> /etc/security/limits.conf $ sudo su -c 'echo @audio -memlock 250000 >> /etc/security/limits.conf $ sudo su -c 'echo @audio -nice -10 >> /etc/security/limits.conf </pre><p>なおこれらの値は昔どこかのサイトに載っていたままなので、自分の環境に合わせて変更してほしい。なんの設定かは未だに知らない。。。</p> </div> <div class="section"> <h5>jackd</h5> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/linux">linux</a>でSCを扱う場合、jackdというソフトウェアを通すことで音の出力を可能にしている。オーディオサーバみたいなものだ。これがまた厄介だったりするが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/linux">linux</a>でSCを使う上での特徴であり、便利といえば非常に便利だ。<br /> では、設定だが横着するために<a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a>のqjackctlをいれよう。</p> <pre>$ sudo apt-get install qjackctl </pre><p>ここでなにやら変な画面に遷移するので、リアルタイム実行優先度の設定を有効にする、で、はいにしておこう。</p> <pre>$ qjackctl(もしくは、dashホームのメディア関係からqjackctl) </pre><p>なんか<a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a>が立ち上がったので、設定変更をしよう。これが大事だったりする。<br /> まず、MessagesをクリックしてMessagesウィンドウを開いておこう。なんらかのエラーがあった場合にはこのウィンドウが必要になる。<br /> 次にSetupだ。わけがわからないと思うが、問題ない。大半の人が意味不明だろう。まずは、Miscタブに遷移し、Enable <a class="keyword" href="http://d.hatena.ne.jp/keyword/D-Bus">D-Bus</a> interfaceのチェックを外そう。これは新しいものなのか私は知らないものだし、なんらかの悪さをしているようだ。続いてSettingsタブに戻り、Realtime、No Memory Lockにチェック、Periods/Bufferを3にする。さらに、右側のAudioをPlayback OnlyにしてOKボタンだ。では、Playボタンをクリックしてみよう。ポップアップが出ずに、ウィンドウの真ん中がStartedでRTがピコピコすればOKだ。OKならStopしておこう。なんらかのエラーが出たならば<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B0%A5%B0%A4%EB">ググる</a>しかない、エラーの場合相当苦労することになるかもしれないので、覚悟しておこう。<br /> なお、ここでの設定は暫定的に音を出すための設定です。入力を殺していますしちゃんとした設定があるはずです。</p> </div> <div class="section"> <h5>エディタ</h5> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/emacs">emacs</a>,<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a>,geditどれでも好きなものを選択可能だ。ここでは<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a>の使い方を紹介する。今年は<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a>が大流行すると思うのでこの機会に覚えておくのも良いかもしれない。<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a>でscを扱う場合には、scvimという<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%E9%A5%B0%A5%A4%A5%F3">プラグイン</a>を利用する、もちろん<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a>は必要だが<a class="keyword" href="http://d.hatena.ne.jp/keyword/ruby">ruby</a>も必要だ。</p> <pre>$ sudo apt-get install <a class="keyword" href="http://d.hatena.ne.jp/keyword/ruby">ruby</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a> </pre><p>scvimはscをビルドした際にインストールされるので、これで準備は完了になる。</p> </div> </div> <div class="section"> <h4>使う</h4> <p>ここまでインストール、設定にかなりの労力が必要だったかと思われる。これが<a class="keyword" href="http://d.hatena.ne.jp/keyword/linux">linux</a>だ!<br /> では早速使ってみよう。</p> <pre>$ scvim </pre><p>なんか別ウィンドウが立ち上がり、動いている。ヘルプを構築?しているらしいのでちょっと待とう。Welcome to <a class="keyword" href="http://d.hatena.ne.jp/keyword/SuperCollider">SuperCollider</a>, type :SChelp for helpと表示されればOKだ。後は音を鳴らすだけだ。</p> <pre>s.boot; {SinOsc.ar()}.play; </pre><p>と入力して、s.boot;行でF6ボタンを押してみよう(fn+F6ボタンの場合も)。次にplay行でF6ボタン。サイン波が聴こえれば完了だ。お疲れ様でした!</p> </div> <div class="section"> <h4>いじょう</h4> <p>さて、これで仮想環境でSCが実行できることになりました。別に<a class="keyword" href="http://d.hatena.ne.jp/keyword/linux">linux</a>でSCが使いたい!というわけではありません。<a class="keyword" href="http://d.hatena.ne.jp/keyword/mac">mac</a>ありますし。1台のマシンでサーバ、クライアント環境を構築したかったわけですよ。仮想上のSCをサーバとして、実機側をクライアントとして色々やれればなあ、と。サーバサイドSC実現できると良いですね!</p><p>今回は初心に返り、<a class="keyword" href="http://d.hatena.ne.jp/keyword/linux">linux</a>環境を構築してみました。なんと本ブログにメモを取り始めてどうやら4年経つようです。全くもってSC力は上がっていないのはなんなんでしょう?むしろ始めて数週間の方が書けた気がします。。</p><p>以上となります、どうぞ今年もよろしくお願い致します。</p> </div> sc3onlinux vim 4 SuperCollider hatenablog://entry/17680117127138688289 2011-12-13T18:23:35+09:00 2019-05-17T20:20:17+09:00 じゃあscvim使ってみよう。 macということで、scvimオリジナルじゃなくて、https://github.com/sbl/scvimこっち使います。linuxもそのうち試してみます。 環境はlion,vim7.3(ただし、機能をフルに使うにはmvimがいるっぽいです。http://code.google.com/p/macvim/) インスコ pathogenでplugin管理 別に使用しなくても良いですが、scvimのreadmeに使ってねとあるので。 $ mkdir ~/.vim/autoload $ mkdir ~/.vim/bundle $ cd ~/.vim/bundle $… <p>じゃあscvim使ってみよう。<br /> <a class="keyword" href="http://d.hatena.ne.jp/keyword/mac">mac</a>ということで、scvimオリジナルじゃなくて、<a href="https://github.com/sbl/scvim">https://github.com/sbl/scvim</a>こっち使います。<a class="keyword" href="http://d.hatena.ne.jp/keyword/linux">linux</a>もそのうち試してみます。<br /> 環境はlion,vim7.3(ただし、機能をフルに使うにはmvimがいるっぽいです。<a href="http://code.google.com/p/macvim/">http://code.google.com/p/macvim/</a>)</p> <div class="section"> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%B3">インスコ</a></h4> <div class="section"> <h5>pathogenでplugin管理</h5> <p>別に使用しなくても良いですが、scvimのreadmeに使ってねとあるので。</p> <pre>$ mkdir ~/.<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a>/autoload $ mkdir ~/.<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a>/bundle $ cd ~/.<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a>/bundle $ git clone git://<a class="keyword" href="http://d.hatena.ne.jp/keyword/github">github</a>.com/tpope/<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a>-pathogen.git $ ln -s ~/.<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a>/bundle/<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a>-pathogen/autoload/pathogen.<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a> ~/.<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a>/autoload/ </pre> </div> <div class="section"> <h5>scvim</h5> <pre>$ git clone git://<a class="keyword" href="http://d.hatena.ne.jp/keyword/github">github</a>.com/sbl/scvim.git ~/.<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a>/bundle/<a class="keyword" href="http://d.hatena.ne.jp/keyword/supercollider">supercollider</a> $ ln -s ~/.<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a>/bundle/<a class="keyword" href="http://d.hatena.ne.jp/keyword/supercollider">supercollider</a>/sc/SCVim.sc ~/Library/Application\ Support/<a class="keyword" href="http://d.hatena.ne.jp/keyword/SuperCollider">SuperCollider</a>/Extensions/SCVim.sc $ vi .<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a>/bundle/<a class="keyword" href="http://d.hatena.ne.jp/keyword/supercollider">supercollider</a>/plugin/<a class="keyword" href="http://d.hatena.ne.jp/keyword/supercollider">supercollider</a>.<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a> 下記のように9-12行目に,*.rtfを加える <a class="keyword" href="http://d.hatena.ne.jp/keyword/au">au</a> BufEnter,BufWinEnter,BufNewFile,BufRead *.sc,*.scd,*.rtf runtime ftplugin/<a class="keyword" href="http://d.hatena.ne.jp/keyword/supercollider">supercollider</a>.<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a> au BufEnter,BufWinEnter,BufNewFile,BufRead *.sc,*.scd,*.rtf set filetype=<a class="keyword" href="http://d.hatena.ne.jp/keyword/supercollider">supercollider</a> au BufEnter,BufWinEnter,BufNewFile,BufRead *.sc,*.scd,*.rtf let &iskeyword="@,48-57,_,192-255" <a class="keyword" href="http://d.hatena.ne.jp/keyword/au">au</a> BufEnter,BufWinEnter,BufNewFile,BufRead *.sc,*.scd,*rtf runtime indent/sc_indent.<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a> 環境によっては、31行目のF12をF7とかに変える (うちのキー配列ではfn+F12ボタンだと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C0%A5%C3%A5%B7%A5%E5">ダッシュ</a>ボートにいっちゃう) <a class="keyword" href="http://d.hatena.ne.jp/keyword/au">au</a> Filetype <a class="keyword" href="http://d.hatena.ne.jp/keyword/supercollider">supercollider</a>,<a class="keyword" href="http://d.hatena.ne.jp/keyword/supercollider">supercollider</a>_help nmap <buffer> <F7> :call SClang_thisProcess_stop()<CR> </pre> </div> <div class="section"> <h5>textutil</h5> <p>sc界隈ではrtfファイルが多いので、見られるようにしておく</p> <pre>mkdir ~/.<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a>/bundle/textutil <a href="http://www.vim.org/scripts/script.php?script_id=1432">http://www.vim.org/scripts/script.php?script_id=1432</a> textutil.<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a>を.<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a>/bundle/textutil/に置く </pre> </div> <div class="section"> <h5><a class="keyword" href="http://d.hatena.ne.jp/keyword/neocomplcache">neocomplcache</a></h5> <p>こいつがないと<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a>は始まらない!</p> <pre>$ git clone git://<a class="keyword" href="http://d.hatena.ne.jp/keyword/github">github</a>.com/Shougo/<a class="keyword" href="http://d.hatena.ne.jp/keyword/neocomplcache">neocomplcache</a>.git ~/.<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a>/bundle/<a class="keyword" href="http://d.hatena.ne.jp/keyword/neocomplcache">neocomplcache</a> </pre> </div> <div class="section"> <h5>vimrc</h5> <p>とりあえずこんな感じに。ググれば沢山例が引っかかりますので参考にしていじってみてください。</p> <pre>$ vi ~/.vimrc "基本設定 set nocompatible filetype indent plugin on set encoding=<a class="keyword" href="http://d.hatena.ne.jp/keyword/utf-8">utf-8</a> set number "colorscheme desert とか好きなヤツを syntax on set hidden set wildmenu set showcmd "タブ関係 set tabstop=4 shiftwidth=4 softtabstop=0 set autoindent smartindent "検索 set ignorecase set incsearch "カッコ <a class="keyword" href="http://d.hatena.ne.jp/keyword/imap">imap</a> {} {}<Left> <a class="keyword" href="http://d.hatena.ne.jp/keyword/imap">imap</a> <span data-unlink> </span><Left> <a class="keyword" href="http://d.hatena.ne.jp/keyword/imap">imap</a> () ()<Left> <a class="keyword" href="http://d.hatena.ne.jp/keyword/imap">imap</a> “” “”<Left> <a class="keyword" href="http://d.hatena.ne.jp/keyword/imap">imap</a> ” ”<Left> <a class="keyword" href="http://d.hatena.ne.jp/keyword/imap">imap</a> <> <><Left> <a class="keyword" href="http://d.hatena.ne.jp/keyword/imap">imap</a> “ “<Left> "全角スペースを強調 highlight zenkakuda ctermbg=7 match zenkakuda / / "pathogen設定 filetype off call pathogen#runtime_append_all_bundles() call pathogen#helptags() filetype on "textutil設定 let <a href="http://textutil.g.hatena.ne.jp/">g:textutil</a>_txt_encoding='<a class="keyword" href="http://d.hatena.ne.jp/keyword/utf-8">utf-8</a>' "<a class="keyword" href="http://d.hatena.ne.jp/keyword/neocomplcache">neocomplcache</a>設定 "~/.<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a>/bundle/<a class="keyword" href="http://d.hatena.ne.jp/keyword/neocomplcache">neocomplcache</a>/doc/<a class="keyword" href="http://d.hatena.ne.jp/keyword/neocomplcache">neocomplcache</a>.jaxのEXAMPLES 764-848行をコピペ </pre> </div> </div> <div class="section"> <h4>使い方</h4> <p>とりあえず、tkckの資料を開いてみましょう。</p> <pre>$ vi tksc#8.rtf </pre> <div class="section"> <h5>サーバ</h5> <ul> <li>立ち上げは、:SClangStart(たまにちゃんと立ち上がってくれないので、開いた別窓でctl+Dとかで<a class="keyword" href="http://d.hatena.ne.jp/keyword/bash">bash</a>を抜けると動いてくれたりします)</li> <li>停止は、:SClangKill</li> </ul><p>:scの時点でtabキー押すと候補選択できます。</p> </div> <div class="section"> <h5>コード実行</h5> <ul> <li>1行実行は、その行にカーソルを持っていき、F6キー(キー配列によってはfn+F6キー)</li> <li>ブロック実行は、Vでビジュアルモードになり、実行したいブロックをn,pキーか上下キーで選択して、F5キー</li> <li>コード停止は、上で変更したF7キー(デフォルトではF12キー)</li> </ul> </div> <div class="section"> <h5>補完</h5> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/neocomplcache">neocomplcache</a>が勝手に補完候補呼び出してくれます。sinと打つと候補として、UnaryOperatorのsin,<a class="keyword" href="http://d.hatena.ne.jp/keyword/sinh">sinh</a>があがります。tabキーかctl+p,nで選択。<br /> ただし、うちの環境ではなぜかオブジェクトを候補として出してくれないので、調査中です。~/.<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a>/bundle/<a class="keyword" href="http://d.hatena.ne.jp/keyword/supercollider">supercollider</a>/syntax/<a class="keyword" href="http://d.hatena.ne.jp/keyword/supercollider">supercollider</a>_objects.<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a>はちゃんと読み込まれているし、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%F3%A5%BF%A5%C3%A5%AF%A5%B9">シンタックス</a>ハイライトはちゃんと機能しているんですけれど。。。</p> </div> <div class="section"> <h5><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%CB%A5%DA%A5%C3%A5%C8">スニペット</a></h5> <p>デフォルトで多少~/.<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a>/bundle/<a class="keyword" href="http://d.hatena.ne.jp/keyword/supercollider">supercollider</a>/snippets/<a class="keyword" href="http://d.hatena.ne.jp/keyword/supercollider">supercollider</a>.snippetsに書かれています。<br /> 試しにsdefを打ってみて下さい。候補が出たらtabなどで選択して、ctl+kで展開されます。シンセ名にカーソルが遷移しますので、適当に変えたら、ctl+k。snd = のところに遷移します。</p> </div> </div> <div class="section"> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/gui">gui</a></h4> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/cocoa">cocoa</a>はダメポです。swingはいけますので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a>.swingにしておきましょう。<br /> [参考]<a href="http://supercollider.jp/modules/xhnewbb/viewtopic.php?topic_id=215">http://supercollider.jp/modules/xhnewbb/viewtopic.php?topic_id=215</a><br /> </p> </div> <div class="section"> <h4>いじょう</h4> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a>に慣れていれば結構便利です。ただ、初期設定は面倒ですし、<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a>に慣れていないと全く使用するメリットがないかと思われます。ちょっとオシャレで出来るヤツ風を装いたいなら、scvimだとそれっぽく見えるかもしれません。<br /> 仕事で<a class="keyword" href="http://d.hatena.ne.jp/keyword/vim">vim</a>をひたすら使っているので、当面scvimで行きたいと思います。</p> </div> sc3onlinux サーバサイドSuperCollider hatenablog://entry/17680117127138688441 2011-10-01T19:33:20+09:00 2019-05-17T20:20:18+09:00 基本 SCはaudio serverであるscsynthと、クライアントであるsclangに分かれて成り立っています。さらに、sclangはプログラム言語部分とインタプリタ部分に分かれています。sclangの機能として2つあり、サーバのクライアントとしての機能と、言語のインタプリタとしての機能です。要はコードを解釈して、サーバであるscsynthにメッセージを送るという役割を担っています。また、sclangとscsynthはOSCプロトコルを利用して情報のやり取りをしています。 SC内の一連の流れは、SCプログラミング言語で書かれたものをsclangのインタプリタが解釈しOSCメッセージに落と… <div class="section"> <h4>基本</h4> <p>SCはaudio serverであるscsynthと、クライアントであるsclangに分かれて成り立っています。さらに、sclangはプログラム言語部分と<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%BF%A5%D7%A5%EA%A5%BF">インタプリタ</a>部分に分かれています。sclangの機能として2つあり、サーバのクライアントとしての機能と、言語の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%BF%A5%D7%A5%EA%A5%BF">インタプリタ</a>としての機能です。要はコードを解釈して、サーバであるscsynthにメッセージを送るという役割を担っています。また、sclangとscsynthはOSC<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%C8%A5%B3%A5%EB">プロトコル</a>を利用して情報のやり取りをしています。<br /> SC内の一連の流れは、SC<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0%B8%C0%B8%EC">プログラミング言語</a>で書かれたものをsclangの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%BF%A5%D7%A5%EA%A5%BF">インタプリタ</a>が解釈しOSCメッセージに落とし込む。次に、そのOSCメッセージをsclangがscsynthに送信。scsynth側で送られてきたメッセージに従い処理する。となっています。なんらかの方法を用いて、scsynthにシンセを作成し、そのシンセに対して挙動を制御できれば音が鳴るってことです。じゃあ、scsynthだけ動かすサーバたてて、クライアントはsclangじゃなくてなんでも使って良いんだよね!?ClientVsServer.htmlを読むとまさにそんなことが書いてあります、もっとも、sclang使うとscsynthへSynthDefsの作成と読み込みが楽だし、sclang使ってね!と書いてありますけれど。<br /> sclangからscsynthをコン<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%ED%A1%BC%A5%EB">トロール</a>するには、Serverオブジェクトを利用します。Serverオブジェクトはクライアント(sclang)と同じマシンで動いているscsynthを表すことが多いですが、リモートマシン上のscsynthでもおkです。</p><p>なんか間違っているかも。。。</p> </div> <div class="section"> <h4>具体例</h4> <p>端末は1台でも試せますが、できれば2台端末を用意してください。サーバとして使用する側にてターミナルでifconfigして、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EB%A1%BC%A5%D7%A5%D0%A5%C3%A5%AF%A5%A2%A5%C9%A5%EC%A5%B9">ループバックアドレス</a>ではないアドレスが端末に割り振られていることを確認してください。以下は192.168.11.2が割り振られている場合の例になります。クライアントからServerオブジェクトを使えば、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%E2%A1%BC%A5%C8%A5%DB%A5%B9%A5%C8">リモートホスト</a>のscsynthをコン<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%ED%A1%BC%A5%EB">トロール</a>できると述べました。<br /> では、クライアント側から以下を実行してみてください。</p> <pre> ~myServer = Server( \test, NetAddr( "192.168.11.2", 57110 ) ); ~myServer.makeWindow; </pre><p>お、いつもと違う<a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a>が立ち上がりましたね。boot,quitボタンがありません。</p> <pre> ~myServer.boot; </pre><p>リモートでのサーバブートは許可されていないためfailedになりました。<br /> じゃあリモートサーバをbootするには、どうするのっと。<br /> scsynthを立ち上げたいサーバ(ホスト)に<a class="keyword" href="http://d.hatena.ne.jp/keyword/ssh">ssh</a>などでログインし、ターミナルにて"$ scsynth -u ポート番号"でブートさせることが可能です。ポート番号はNetAddrで指定したポートになりますよ。<br /> <a class="keyword" href="http://d.hatena.ne.jp/keyword/mac">mac</a>をサーバとしたときには、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リを/Application/<a class="keyword" href="http://d.hatena.ne.jp/keyword/SuperCollider">SuperCollider</a>に移動しておかないとエラーが出るかもしれません。<br /> もちろん、サーバ側で<a class="keyword" href="http://d.hatena.ne.jp/keyword/SuperCollider">SuperCollider</a>.appとかを立ち上げて通常通りlocalサーバをブートしても行けます。</p><p>じゃあ、早速サーバ側で音を鳴らしてみましょう。</p> <pre> ~myServer.sendMsg( "/s_new", \default, x =~myServer.nextNodeID, 0, 0 ); ~myServer.sendMsg( "/n_free", x ); </pre><p>簡単ですね。ただし、defaultシンセはあらかじめサーバ側に保存されているものです。クライアント側からシンセを定義して送りたいんだ! 送り先をデフォルトサーバのsではなく、先ほど定義したサーバを指定するだけです。</p> <pre> ( SynthDef( "network_test", { arg freq=1200; var signal,env; signal = SinOsc.ar( freq, 0, 0.5 ); env = EnvGen.ar( Env.<a class="keyword" href="http://d.hatena.ne.jp/keyword/perc">perc</a> ( 0, 1, 1, -12 ), doneAction: 2 ); Out.ar( 0, Pan2.ar( signal * env, 0 ) ); }).send( ~myServer ); ) ~myServer.sendMsg( "/s_new", \network_test, x = ~myServer.nextNodeID, 0, 0 ); ~myServer.sendMsg( "/n_free", x ); </pre><p>ちゃんと音が鳴りました!<br /> scsynthとsclangが同じ端末だと、なんか起動していないから送れないよ。とかエラーでるかもしれませんが、たぶん送れてます。<br /> サーバの終了はいつもの。</p> <pre> ~myServer.quit; </pre> </div> <div class="section"> <h4>local vs internal</h4> <p>ん?これってlocalサーバ、internalサーバ?ここでちょっと寄り道してlocalサーバとinternalサーバのお話。<br /> 何が違うの?って、ちゃんとヘルプに書いてあります。localサーバはsclangとscsynthが違う<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%C9%A5%EC%A5%B9%B6%F5%B4%D6">アドレス空間</a>で動いています。internalはsclangとscsynthが同じ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%C9%A5%EC%A5%B9%B6%F5%B4%D6">アドレス空間</a>で動いています。internalはメモリを共有しているので、scopeとかSharedIn/SharedOutが使えるよ。んで、(sclangとscsynth間での)メッセージのレイテンシが小さいよ。localサーバは別々なのでsclangがこけてもscsynthは生きているから音は出続けて<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%ED%A5%D0%A5%B9%A5%C8">ロバスト</a>だよ。らしいです、家で使うときはinternalで良いんじゃないですかね?<br /> scsynthとsclangが別端末の場合は、localサーバと同じですね。scopeは使えません!</p> </div> <div class="section"> <h4>いじょう</h4> <p>SCは構造としてサーバとクライアントが分離されており、ある意味サーバサイドであり、クライアントからコードを送ってサーバ側で音を鳴らすことができることが分かりました。<br /> ここで、問題となるのがレスポンス。残念ながらサーバ側で音が鳴るだけです。クライアント側に音を返してこそサーバサイドだ!どうやってクライアントに音を返すか?SC側に実装はされていないような気がします。じゃあ、ストリーミング?</p> </div> sc3onlinux 超意訳OSC with SuperCollider hatenablog://entry/17680117127138688604 2011-09-07T23:02:40+09:00 2019-05-17T20:20:20+09:00 OSC_communication プログラム間のOSCコミュニケーションは、あるアプリから他のアプリにメッセージを送ることでやりとりされる。違うコンピュータでアプリが走っていてもおk。OSCの基礎はUDP/TCPだよ。 SuperColliderではターゲットアプリのNetAddrと他のアプリからメッセージを受信するOSCresponderNodeを作ってコミュニケートするよ。 他のアプリにOSCメッセージを送るよ 他のアプリとコミュニケーションを確立させるには、他のアプリがどのポートでメッセージを受け取るのか知っておく必要があるよ。 例えばさ、7771ポートでリスンしているアプリがあるとす… <div class="section"> <h4>OSC_communication</h4> <p>プログラム間のOSCコミュニケーションは、あるアプリから他のアプリにメッセージを送ることでやりとりされる。違うコンピュータでアプリが走っていてもおk。OSCの基礎は<a class="keyword" href="http://d.hatena.ne.jp/keyword/UDP">UDP</a>/<a class="keyword" href="http://d.hatena.ne.jp/keyword/TCP">TCP</a>だよ。<br /> <a class="keyword" href="http://d.hatena.ne.jp/keyword/SuperCollider">SuperCollider</a>ではターゲットアプリのNetAddrと他のアプリからメッセージを受信するOSCresponderNodeを作ってコミュニケートするよ。</p> <div class="section"> <h5>他のアプリにOSCメッセージを送るよ</h5> <p>他のアプリとコミュニケーションを確立させるには、他のアプリがどのポートでメッセージを受け取るのか知っておく必要があるよ。<br /> 例えばさ、7771ポートでリスンしているアプリがあるとするよ。そんな時は、下のようにNetAddrつくってメッセージ送るんだ。</p> <pre class="code" data-lang="" data-unlink> b = NetAddr.new( &#34;127.0.0.1&#34;, 7771 ); b.sendMsg( &#34;/helle&#34;, &#34;there&#34; );</pre> </div> <div class="section"> <h5>他のアプリからOSCメッセージを受け取るよ</h5> <p>SCが他のアプリからメッセージを受け取るときは、他のアプリは<a class="keyword" href="http://d.hatena.ne.jp/keyword/SuperCollider">SuperCollider</a>のリスニングポートにメッセージを送らなくちゃダメなんだ。<br /> SCのデフォルトポートは57120だ。でもたまに違うよ、SCを立ち上げたとき既に使われちゃっていた時とかね。<br /> 今のデフォルトポートは下で取得できるから確認してね。</p> <pre class="code" data-lang="" data-unlink> NetAddr.langPort;</pre><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/IP%A5%A2%A5%C9%A5%EC%A5%B9">IPアドレス</a>も一緒に取得したいならこっちだ。</p> <pre class="code" data-lang="" data-unlink> NetAddr.localAddr;</pre><p>送られてきたメッセージを受け取るには、SC側でOSCresponderを作成しなくちゃならないんだ。<br /> メッセージ送信側アプリがメッセージを送る固定ポートを持っているなら、OSCresponderでその<a class="keyword" href="http://d.hatena.ne.jp/keyword/IP%A5%A2%A5%C9%A5%EC%A5%B9">IPアドレス</a>とポートからメッセージを受け取るように設定するんだ。これは、メッセージ送信アプリが7771番ポートにメッセージ送信しているときの例だよ。</p> <pre class="code" data-lang="" data-unlink> n = NetAddr.new( &#34;127.0.0.1&#34;, 7771 ); o = OSCresponderNode.new( n, &#34;/goodbye&#34;, { arg time, resp, msg; [ time, resp ].postln; } ).add; o.remove;</pre><p>なんでOSCresponderじゃなくて、OSCresponderNodeかって?同じメッセージ名('/aaa'とか)を受け取るOSCresponderを作ったとすると、2個目のOSCrespoderは1個目を上書きしちゃうんだ。同時に1メッセージあたり1つのOSCresponderしか作成できないってことだね。例えば、下の方でサンプルがあるけれど'/tr'を受け取る時とかは複数作成する場合があるよ。<br /> でもOSCresponderNodeはそんな制限はないんだ!同じ名前のOSCresponderNodeを共存させられるんだ。<br /> (もういらなくなった時にOSCresponderNodeを消すには作ったOSCresopnderNodeをずっと追跡していなくちゃいけないってことでもあるね)詳しくはOSCpathResponderをみ・て・ね!</p> </div> <div class="section"> <h5>複数ポートからのメッセージを受け取るよ</h5> <p>固定ポートにメッセージを送らないアプリもあるよね、問題ない、どのポートからでもメッセージを受け取れるようにOSCresponderNodeを設定できるんだ。<br /> OSCresponderNodeの第一引数としてNetAddrを指定する代わりに、<a class="keyword" href="http://d.hatena.ne.jp/keyword/nil">nil</a>だ。</p> <pre class="code" data-lang="" data-unlink> o = OSCresponderNode.new( nil, &#34;/goodbye&#34;, { arg time, resp, msg; [ time, resp ].postln; ] ).add; o.remove;</pre> </div> <div class="section"> <h5>受信<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%E9%A5%D5%A5%A3%A5%C3%A5%AF">トラフィック</a>のテスト</h5> <p>全て受信したOSCメッセージはrecvOSCmessageかrecvOSCbundleを呼ぶんだ。受信<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%E9%A5%D5%A5%A3%A5%C3%A5%AF">トラフィック</a>を見るには、recvOSCfuncを使おう。(何やっているのかよくわからないねw)</p> <pre class="code" data-lang="" data-unlink> ( thisProcess.recvOSCfunc = { arg time, addr, msg; if( msg[0] != &#39;status.reply&#39; ) { &#34;time: % sender: %\nmessage: %\n&#34;.postf( time, addr, msg ); } } ); thisProcess.recvOSCfunc = nil;</pre><p> </p> </div> </div> <div class="section"> <h4>OSCresponderNode</h4> <div class="section"> <h5>OSCresponderNode</h5> <p>あるOSCアドレスからあるコマンドを受信したときに呼び出される関数を設定する、それがOSCresponderNodeだ。OSCresponderのように同じインターフェースがあるけれども、OSCresponderNodeは同じコマンドに対して複数のレスポンスが許可されているんだ。</p><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%B9%A5%C6%A5%E0%A5%D7%A5%ED">システムプロ</a>セスでOSCresponderNodeが関数を評価することに気をつけるんだ!アプリケーションプロセスにアクセスするためには、deferメッセージを使うんだ。<a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a>のアクセスみたいにね。(なに言ってんのこれ?)</p><p>SCにメッセージを送るアプリでは、SCサーバ/SClangに送るメッセージを区別させなくちゃならない。サーバメッセージはServer-Command-Referenceに書いてあるし、SCサーバのポートに送らなきゃダメなんだ。(デフォルト値が57110でs.addr.portだね)SCサーバに送られてきたメッセージはSClang内のどのOSCresponderでも処理されないんだ。後述するけれど、SynthDefで直接OSCメッセージの送受信ができないってことなんだ。</p><p>OSCresponderで処理される外部クライアントからのOSCメッセージは、デフォルト値が57120のSClangのポートに送らなくちゃいけない。どのポートがリスン状態かはNetAddr.langPortで確認できるよ。</p> </div> <div class="section"> <h5>OSCresponderNode設定</h5> <pre class="code" data-lang="" data-unlink> /* 受信側設定 */ //NetAddr.new( hostname, port ) newメッセージは省略できるよ! n = NetAddr( &#34;127.0.0.1&#34;, 57120 ); //OSCresponderNode.new( addr, cmdName, action ) o = OSCresponderNode( n, &#39;/chat&#39;, { arg t, r, msg; ( &#34;time:&#34; + t ).postln; msg[1].postln; } ).add; /* 送信側設定 */ //NetAddr.new( hostname, port ) m = NetAddr( &#34;127.0.0.1&#34;, 57120 ) //sendMsg( args… ) send a message without timestamp to the addr. //第一引数でOSCコマンドを指定して、第二引数のメッセージをOSCコマンドに送るよ。 m.sendMsg( &#34;/chat&#34;, &#34;Hello App 1&#34; ); //sendBundle(timestamp, args… ) send a bundle with timestamp to the addr. //タイムスタンプと一緒に複数メッセージを送るよ。詳しくはServerのヘルプみてね。 ( m.sendBundle( 2.0, [ &#34;/chat&#34;, &#34;hello app 1&#34; ], [ &#34;/chat&#34;, &#34;hello world&#34; ] ); m.sendBundle( 0.0, [ &#34;/chat&#34;, &#34;hello app 1&#34; ], [ &#34;/chat&#34;, &#34;hello world&#34; ] ); ) //disconnect; close TCP connection. //remove; remove and deactivate the OSCresponder //もう使わないから捨てるよ m.disconnect; n.disconnect; o.remove;</pre> </div> <div class="section"> <h5>どんなクライアントからもデータ受け取るよ</h5> <p>前述したけれど、第一引数に<a class="keyword" href="http://d.hatena.ne.jp/keyword/nil">nil</a></p> </div> <div class="section"> <h5>ポートはなんでもいいけれど、特定ホストからのみメッセージ受け取るよ</h5> <pre class="code" data-lang="" data-unlink> //NetAddrのポートを指定せずに、nilにするんだ n = NetAddr( &#34;127.0.0.1&#34;, nil ); o = OSCresponderNode( n, &#39;/test&#39;, { | t, r, msg | msg.postln; } ).add; o.remove;</pre> </div> <div class="section"> <h5>SCサーバからのメッセージを受け取るよ</h5> <p>synthdefは一旦SCサーバに保存して、SCサーバで読み込まれるんだけれど、SCサーバから直接OSCメッセージの送受信はできないんだ。だから一旦OSCresponderNodeで受信しているんだよ。外部アプリにOSCメッセージを送りたい時は、OSCresponderNode内の関数でsendMsgしてあげると上手くいくよ。<br /> ここでのsynthdefは'/tr'にDust.krタイミングで0.9の値を送っているだけのシンセだ。OSCresponderNodeで'/tr'に送られてきたメッセージを受信しているのが分かるかな。</p> <pre class="code" data-lang="" data-unlink> ( s = Server.local.boot; s.notify; ) ( SynthDef( &#34;help-SendTrig&#34;, { SendTrig.kr( Dust.kr( 1.0 ), 0, 0.9 ); }).send( s ); //これなんだけれども、OSCresponderで定義すると上書きされちゃうから&#34;this is another call&#34;しか出力されないんだ a = OSCresponderNode( s.addr, &#39;/tr&#39;, { | t, r, msg | [ t, r, msg ].postln; }).add; b = OSCresponderNode( s.addr, &#39;/tr&#39;, { | t, r, msg | &#34;this is another call&#34;.postln; }).add; x = Synth.new( &#34;help-SendTrig&#34;); )</pre> </div> </div> <div class="section"> <h4>いじょう</h4> <p>ヘルプは不親切ですなあ。なんか間違っている気もするけれど気にしない。<br /> OSCBundleはまだ使わないので、あとはOSCpathResponder知っておけばいいのかな。</p> </div> sc3onlinux SuperCollider + OSCeleton hatenablog://entry/17680117127138688751 2011-09-01T21:15:57+09:00 2019-05-17T20:20:21+09:00 ちょい前にhttp://www.kinecthacks.com/kinect-with-supercollider/がTL上に流れてきまして、ああそろそろ試すか。ってことで、OSCeletonです。たまにはkinectも使ってあげないとね! 準備 以前紹介しました、Unity3d+kinect参照に libtool,libusb-devel OpenNI NITE SensorKinect これらをインストールします。最新版であれば、lion環境でも動作します。 OSCeleton メインのOSCeletonですが、https://github.com/Sensebloom/OSCeleton… <p>ちょい前に<a href="http://www.kinecthacks.com/kinect-with-supercollider/">http://www.kinecthacks.com/kinect-with-supercollider/</a>がTL上に流れてきまして、ああそろそろ試すか。ってことで、OSCeletonです。たまには<a class="keyword" href="http://d.hatena.ne.jp/keyword/kinect">kinect</a>も使ってあげないとね!</p> <div class="section"> <h4>準備</h4> <p>以前紹介しました、<a href="http://d.hatena.ne.jp/sc3onlinux/20110531/1306845679">Unity3d+kinect</a>参照に</p> <ul> <li>libtool,libusb-devel</li> <li>OpenNI</li> <li>NITE</li> <li>SensorKinect</li> </ul><p>これらをインストールします。最新版であれば、lion環境でも動作します。</p> <div class="section"> <h5>OSCeleton</h5> <p>メインのOSCeletonですが、<a href="https://github.com/Sensebloom/OSCeleton">https://github.com/Sensebloom/OSCeleton</a>からosceleton-v1.2.1_<a class="keyword" href="http://d.hatena.ne.jp/keyword/OSX">OSX</a>.zipがDLできますので、そのままこいつ使ってしまいましょう。解凍するだけでおkです。</p> </div> </div> <div class="section"> <h4>使う</h4> <div class="section"> <h5>SC側コード</h5> <p>とりあえず、シンセの作成とfreqを変化させるだけ。</p> <pre class="code" data-lang="" data-unlink>/* * osceleton test */ /* * osc setting */ ( //receive osc messages from osceleton ~oscReceive = NetAddr(&#34;127.0.0.1&#34;, 57120); //アドレスはこいつら, /new_user, /new_skel, /lost_user, /joint //新規ユーザ発見時 OSCresponder(nil, &#39;/new_user&#39;,{ arg t, r, msg; &#34;create a new synth&#34;.speak; s.sendMsg(&#34;/s_new&#34;, \osceleton_sinosc, x = s.nextNodeID,0,0 ); [t,msg].postln; }).add; //ユーザ見失った。。。 OSCresponder(nil, &#39;/lost_user&#39;, { arg t, r, msg; &#34;delete a synth&#34;.speak; s.sendMsg(&#34;/n_free&#34;, x); [t,msg].postln; }).add; //ここから各種ジョイントのx,y,z取得して、諸々のシンセにパラメータを振っていく、など好きな処理を記述していく。[/joint, 体の部位, ユーザ番号, x, y, z]のメッセージを受信するため、体の部位ごとにswitch文とかで挙動を分ければ良いかと。ぼっちなのでユーザは分けません! a = OSCresponder(nil, &#39;/joint&#39;, { arg t, r, msg; switch(msg[1], //head, neck, torso, r_shoulder, r_elbow, r_hand, l_shoulder, l_elbow, l_hand, r_hip, r_knee, r_ankle, r_foot, l_hip, l_knee, l_ankle, l_foot //head \head, { ( &#34;joint:&#34; + msg[1] + &#34;| user:&#34; + msg[2] ).post; msg[3..].postln; s.sendMsg( &#34;/n_set&#34;, x, &#34;freq&#34;, msg[3]*1000 ); }, //neck \neck, { ( &#34;joint: &#34; + msg[1] + &#34;| user : &#34; + msg[2] ).post; msg[3..].postln; } //とまあ面倒っちゃ面倒っす ); //[t,msg].postln; }).add; //check NetAddr.localAddr; ) /* * synth def */ ( SynthDef(&#34;osceleton_sinosc&#34;,{ arg pan = 0, outBus = 0, freq = 440; var signal; signal = SinOsc.ar(freq,0,0.4); Out.ar(outBus, Pan2.ar(signal,pan); ); }).store; ) /* * osc clear ? */ OSCresponder.initClass;</pre> </div> <div class="section"> <h5>OSCeleton</h5> <pre>./osceleton-v1.2.1_<a class="keyword" href="http://d.hatena.ne.jp/keyword/OSX">OSX</a> -p 57120 </pre><p>デフォだとポートが7110なのでSCデフォの57120にしてやると余計なことを考えずに済む。</p> </div> </div> <div class="section"> <h4>いじょう</h4> <p>OSCeletonだけだと映像出力がないので、位置とかがよくわかりませんw<br /> 受信するメッセージが多いのでちょっと面倒かもです。別に全部使わずに、絞って使えば良いだけですが。<br /> OSCeletonは結構CPU喰いますので注意を!</p> </div> sc3onlinux とりあえずosc4nodeとSC3 hatenablog://entry/17680117127138688886 2011-08-28T19:59:15+09:00 2019-05-17T20:20:22+09:00 そろそろブラウザからもSCにOSCメッセージ送りたいですよね?それならosc4node使いましょう!すごい簡単にOSCメッセージの送受信が実装できます、素晴らしい!! 準備 Node.jsの環境構築などはググれば沢山ありますので、割愛。 osc4nodeについては hideyukisaitoさんのblog osc4node – GitHub 使う SC側 とりあえず、OSCメッセージの送受信を実装しましょう。 /* * osc4node test */ /* * osc setting */ ( //receive osc messages from node ~oscReceive = Ne… <p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/sc3onlinux/20110828191415" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sc3onlinux/20110828/20110828191415.png" alt="f:id:sc3onlinux:20110828191415p:image:w360" title="f:id:sc3onlinux:20110828191415p:image:w360" class="hatena-fotolife" style="width:360px" itemprop="image"></a></span><br /> そろそろブラウザからもSCにOSCメッセージ送りたいですよね?それならosc4node使いましょう!すごい簡単にOSCメッセージの送受信が実装できます、素晴らしい!!</p> <div class="section"> <h4>準備</h4> <p>Node.jsの環境構築などはググれば沢山ありますので、割愛。<br /> osc4nodeについては<br /> <a href="http://hideyukisaito.com/blog/?p=696">hideyukisaito&#x3055;&#x3093;&#x306E;blog</a><br /> <a href="https://github.com/hideyukisaito/osc4node">osc4node &ndash; GitHub</a><br /> </p> </div> <div class="section"> <h4>使う</h4> <div class="section"> <h5>SC側</h5> <p>とりあえず、OSCメッセージの送受信を実装しましょう。</p> <pre class="code" data-lang="" data-unlink> /* * osc4node test */ /* * osc setting */ ( //receive osc messages from node ~oscReceive = NetAddr(&#34;127.0.0.1&#34;, 57120); o = OSCresponder(nil, &#39;/sc3/synth&#39;, { arg t, r, msg; //msg[1]にシンセ名を送っているため、ここで分岐 switch(msg[1], //kickの場合 \osc4node_kick, { s.sendMsg(&#34;/s_new&#34;,msg[1],s.nextNodeID,0,0 ); }, //sinの場合 \osc4node_sinosc, { //シンセ作成、価変更、解放の分岐 switch(msg[2], \play, { s.sendMsg(&#34;/s_new&#34;,msg[1],x = s.nextNodeID,0,0); }, \set, { s.sendMsg(&#34;/n_set&#34;, x, &#34;freq&#34;, msg[3]); }, \free, { s.sendMsg(&#34;/n_free&#34;, x); } ); } ); [t,msg].postln; }).add; // send osc messages 2 node ~oscSend = NetAddr(&#34;127.0.0.1&#34;, 57124); //osc4node_kick1のSendReply.krにて一旦サーバ側へOSCメッセージ送信。ここでメッセージを受信する OSCresponder(nil, &#39;/scServer/4node&#39;, { arg t, r, msg; //ここでnode側にメッセージ送信 ~oscSend.sendMsg(&#39;/sc3/2node&#39;, msg[3]); [t,msg].postln; }).add; //check NetAddr.localAddr; ) /* * synth def */ ( SynthDef(&#34;osc4node_kick&#34;,{ arg pan = 0, outBus = 0, clip_amp = 1.0, white_amp=0.0, filter_freq=1.0; var env_mul, env_freq, signal, outSend; env_mul = Env.new([0.5, 1, 0.5, 0], [0.005, 0.06, 0.26], [-4, -2, -4]); env_mul = EnvGen.ar(env_mul ,doneAction:2); env_freq = Env.new([110, 59, 29], [0.005, 0.29], [-4, -5]); env_freq = EnvGen.ar(env_freq).midicps; signal = SinOsc.ar(env_freq, 0, env_mul); signal = signal + PinkNoise.ar(white_amp); signal = LPF.ar(signal, env_freq*filter_freq, env_mul); signal = signal + SinOsc.ar(env_freq,0.5,env_mul); outSend = signal * clip_amp; outSend.clip2(1); //一旦scサーバに値を送る SendReply.kr(Impulse.kr(20), &#34;/scServer/4node&#34;,[outSend.()]); //outSend.poll(Impulse.ar(20),&#34;/sc3/4node&#34;,1); //pollで/trにugenの出力値を送ったりもできるけれど、受信後の処理が面倒かも Out.ar(outBus, Pan2.ar(outSend, pan) ); }).store; SynthDef(&#34;osc4node_sinosc&#34;,{ arg pan = 0, outBus = 0, freq = 440; var signal; signal = SinOsc.ar(freq,0,0.4); Out.ar(outBus, Pan2.ar(signal,pan); ); }).store; ) /* * osc clear ? */ OSCresponder.initClass;</pre> </div> <div class="section"> <h5>Nodeサーバ側</h5> <p>osc4nodeの詳しい使い方は、@hideyukisaitoさんに直接聞くか、READMEとexampleを参照しましょう。socket.ioのバージョンによってちょっと書き方が違うっぽいです。<br /> express使っていますので、app.jsとかです。</p> <pre class="code" data-lang="" data-unlink> /** * osc4node test by ksy. */ var express = require(&#39;express&#39;), socketIO = require(&#39;socket.io&#39;), osc = require(&#39;osc4node&#39;); var app = module.exports = express.createServer(); // Configuration app.configure(function(){ app.set(&#39;views&#39;, __dirname + &#39;/views&#39;); app.set(&#39;view engine&#39;, &#39;ejs&#39;); app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(app.router); app.use(express.static(__dirname + &#39;/public&#39;)); }); app.configure(&#39;development&#39;, function(){ app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); }); app.configure(&#39;production&#39;, function(){ app.use(express.errorHandler()); }); // Routes app.get(&#39;/&#39;, function(req, res){ res.render(&#39;index&#39;, { title: &#39;osc4node for sc3&#39; }); }); app.listen(3000); console.log(&#34;Express server listening on port %d in %s mode&#34;, app.address().port, app.settings.env); // osc4node setting var oscserver = new osc.Server(57124,&#39;127.0.0.1&#39;); var oscclient = new osc.Client(&#39;127.0.0.1&#39;,57120); //socket.io var io = socketIO.listen(app); ////connection io.sockets.on(&#39;connection&#39;, function(socket){ console.log(&#34;connection&#34;); socket.on(&#39;message&#39;, function(data){ console.log(data); io.sockets.emit(&#39;message&#39;, { value :data.value }); }); //oscmessage send 2 sc socket.on(&#39;oscmessage&#39;, function(data){ io.sockets.emit(&#39;oscmessage&#39;, { address: data.address,message: data.message }); var mes = new osc.Message(data.address,data.message); oscserver.send(mes, oscclient); }); //oscmessage receive from sc oscserver.on(&#39;oscmessage&#39;, function(msg, rinfo){ io.sockets.emit(&#39;oscreceive&#39;,{ address: msg._address, typetag: msg._typetag, value: msg._args[0].value, args: msg.argments }); }); //disconnect socket.on(&#39;disconnect&#39;, function(){ console.log(&#34;disconnection&#34;); }); });</pre> </div> <div class="section"> <h5>Nodeクライアント側</h5> <p>./public/<a class="keyword" href="http://d.hatena.ne.jp/keyword/javascript">javascript</a>/xx.jsとか。かなり適当。スライダー使うため、途中で<a class="keyword" href="http://d.hatena.ne.jp/keyword/jQuery">jQuery</a>に切り替えてます。。。これに合わせて、view/*.ejsも作成します。</p> <pre class="code" data-lang="" data-unlink>$(function(){ //自分の環境に var socket = io.connect(&#39;xxx.xxx.xxx.xxx:3000&#39;); socket.on(&#39;connect&#39;, function(msg){ console.log(&#34;client: connection&#34;); document.getElementById(&#34;connectMsg&#34;).innerHTML = &#34;your sessisonID is:&#34; + socket.socket.transport.sessid; }); socket.on(&#39;message&#39;, function(msg){ document.getElementById(&#34;receiveMsg&#34;).innerHTML = msg.value; }); socket.on(&#39;oscmessage&#39;, function(msg){ document.getElementById(&#34;receiveMsg&#34;).innerHTML = &#34;address from client:&#34; + msg.address + &#34;| message:&#34; + msg.message; }); // receive message from sc socket.on(&#39;oscreceive&#39;, function(msg){ osc_address = msg.address; switch(osc_address){ case &#34;/sc3/test&#34;: $(&#39;#receiveFromSc&#39;).html(&#34;address from sc:&#34; + msg.address + &#34; | value: &#34; + msg.value); break; case &#34;/sc3/2node&#34;: $(&#39;#receiveFromSc&#39;).html(&#34;address from sc:&#34; + msg.address + &#34; | value: &#34; + msg.value); break; default: break; } }); //send osc message 2 SC $(&#39;#playKick&#39;).click(function(){ socket.send(&#39;message&#39;, { message: &#34;test send&#34;}); socket.emit(&#39;oscmessage&#39;, { address: &#34;/sc3/synth&#34;,message: [ &#34;osc4node_kick&#34;,&#34;play&#34;] }); }); $(&#39;#playSin&#39;).click(function(){ socket.emit(&#39;oscmessage&#39;, { address: &#34;/sc3/synth&#34;,message: [ &#34;osc4node_sinosc&#34;,&#34;play&#34;] }); }); $(&#39;#freeSin&#39;).click(function(){ socket.emit(&#39;oscmessage&#39;, { address: &#34;/sc3/synth&#34;,message: [ &#34;osc4node_sinosc&#34;,&#34;free&#34;] }); }); function discon(){ socket.emit(&#39;message&#39;, { value: &#34;client: discon&#34; }); socket.disconnect(); }; //UIs $(&#34;.slider&#34;).slider({ max:880, min:440, step:10, value:440, orientation:&#39;vertical&#39;, slide: function( event, ui ){ $(&#34;#slideAmount&#34;).val(ui.value); socket.emit(&#39;oscmessage&#39;, { address: &#34;/sc3/synth&#34;,message: [ &#34;osc4node_sinosc&#34;,&#34;set&#34;, ui.value] }); } }); $(&#34;#slideAmount&#34;).val($(&#34;.slider&#34;).slider(&#34;value&#34;)); }); </pre> </div> </div> <div class="section"> <h4>いじょう</h4> <p>とりあえず暫定で。<br /> <a class="keyword" href="http://d.hatena.ne.jp/keyword/canvas">canvas</a>とかを使用していかした<a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a>作ってから載せようと思いましたが、面倒なので全然いじっていません。exampleにいかした<a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a>サンプルがあります!<br /> これでブラウザからoscの送受信がさくっとできますので、あとはweb audio <a class="keyword" href="http://d.hatena.ne.jp/keyword/api">api</a>かなんかでストリーミングできれば面白いかとー。</p><p>たとえば、</p> <ul> <li>ライブ会場とかでお客さんに<a class="keyword" href="http://d.hatena.ne.jp/keyword/iPhone">iPhone</a>とか使ってパラメータいじってもらうにはクライアントソフトが必要でした。しかし、これならブラウザがあればおkですから準備不要ですね。</li> <li>数人でライブする場合、リアルタイムで値が反映されますので状況把握しやすいかと。</li> <li>SCなら<a class="keyword" href="http://d.hatena.ne.jp/keyword/linux">linux</a>でも動きますので、サーバ建ててオンラインで色々できそうですね!</li> </ul> </div> sc3onlinux SC3 on Lion hatenablog://entry/17680117127138689040 2011-07-20T00:09:27+09:00 2019-05-17T20:20:23+09:00 リリースされたので、とりあえずインスコしてみましたよ。 確認テスト バージョン SuperCollider ver 3.4.4 (環境は英語に) 確認項目 localhost server internal server SynthDefと中身諸々 SCFreqScopeWindow SynthDescLib いじょう 人柱までに。GUIも大丈夫っぽいです。他は知らんですよ! <p>リリースされたので、とりあえず<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%B3">インスコ</a>してみましたよ。</p> <div class="section"> <h4>確認テスト</h4> <div class="section"> <h5>バージョン</h5> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/SuperCollider">SuperCollider</a> ver 3.4.4 (環境は英語に)</p> </div> <div class="section"> <h5>確認項目</h5> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/localhost">localhost</a> server<br /> internal server<br /> SynthDefと中身諸々<br /> SCFreqScopeWindow<br /> SynthDescLib<br /> <br /> </p> </div> </div> <div class="section"> <h4>いじょう</h4> <p>人柱までに。<a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a>も大丈夫っぽいです。他は知らんですよ!</p> </div> sc3onlinux SC3 こーどりーでぃんぐ2 hatenablog://entry/17680117127138689121 2011-07-03T17:12:53+09:00 2019-05-17T20:20:24+09:00 前回に続いて、snare,hatを読んでみよう。わからないところはさらっとすっ飛ばしていますよ。 snare 08091500Acid309 by_otophiliaより SynthDef("snare", { arg outBus=0, amp=0.8; var env0, env1, env2, env1m, oscs, noise, out; env0 = EnvGen.ar(Env.new([0.5, 1, 0.5, 0], [0.005, 0.03, 0.10], [-4, -2, -4])); env1 = EnvGen.ar(Env.new([110, 60, 49], [0.0… <p>前回に続いて、snare,hatを読んでみよう。わからないところはさらっとすっ飛ばしていますよ。</p> <div class="section"> <h4>snare 08091500Acid309 by_otophiliaより</h4> <pre class="code" data-lang="" data-unlink>SynthDef(&#34;snare&#34;, { arg outBus=0, amp=0.8; var env0, env1, env2, env1m, oscs, noise, out; env0 = EnvGen.ar(Env.new([0.5, 1, 0.5, 0], [0.005, 0.03, 0.10], [-4, -2, -4])); env1 = EnvGen.ar(Env.new([110, 60, 49], [0.005, 0.1], [-4, -5])); env1m = env1.midicps; env2 = EnvGen.ar(Env.new([1, 0.4, 0], [0.05, 0.13], [-2, -2]), doneAction:2); oscs = LFPulse.ar(env1m, 0, 0.5, 1, -0.5) + LFPulse.ar(env1m * 1.6, 0, 0.5, 0.5, -0.25); oscs = LPF.ar(oscs, env1m*1.2, env0); oscs = oscs + SinOsc.ar(env1m, 0.8, env0); noise = WhiteNoise.ar(0.2); noise = HPF.ar(noise, 200, 2); noise = BPF.ar(noise, 6900, 0.6, 3) + noise; noise = noise * env2; out = oscs + noise; out = out.clip2(1) * amp; Out.ar(outBus, out.dup); }).send(s);</pre> </div> <div class="section"> <h4>snareを読む</h4> <pre>env0 = EnvGen.ar(Env.new([0.5, 1, 0.5, 0], [0.005, 0.03, 0.10], [-4, -2, -4])); </pre><p>通常のenv。アタック音用</p> <pre>env1 = EnvGen.ar(Env.new([110, 60, 49], [0.005, 0.1], [-4, -5])); env1m = env1.midicps; </pre><p>通常のenvだけど、<a class="keyword" href="http://d.hatena.ne.jp/keyword/midi">midi</a>値へ変換。この時点でfreq用だとわかる。</p> <pre>env2 = EnvGen.ar(Env.new([1, 0.4, 0], [0.05, 0.13], [-2, -2]), doneAction:2); </pre><p>残響ノイズ用。こちらの方がevn0よりも値の減少が緩やかに設計されている。env0,env2ともにplotして確認してみるとわかりやすい。値が0になるタイミングは同じなので、env0,env2どちらにdoneAction:2つけても良いと思われるが、感覚的にはenv2が終了した時点でシンセ解放がしっくりくる。</p> <pre>oscs = LFPulse.ar(env1m, 0, 0.5, 1, -0.5) + LFPulse.ar(env1m * 1.6, 0, 0.5, 0.5, -0.25); oscs = LPF.ar(oscs, env1m*1.2, env0); oscs = oscs + SinOsc.ar(env1m, 0.8, env0); </pre><p>メイン波形、アタック音。freqをずらしたものを足し合わせることで厚みを出す。他の引数も異なるが、mul,addなので微調整だろう。ローパスのカットオフは*1.2でごっそり削っている。最後にサイン波を足しさらに厚みを増す。相変わらず位相をずらしている。理由は不明。</p> <pre>noise = WhiteNoise.ar(0.2); noise = HPF.ar(noise, 200, 2); noise = BPF.ar(noise, 6900, 0.6, 3) + noise; noise = noise * env2; </pre><p>こちらは残響ノイズ波形。ハイパス<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%AB%A4%DE%A4%B7">かまし</a>たノイズをさらにバンドパスして一部強調?それに元のハイパス<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%AB%A4%DE%A4%B7">かまし</a>たノイズを足している。最後に*env2しているため、終了後にシンセが解放される。なぜこう作っているのかさっぱりわからないが、これだけでスネアっぽさがでるのだから凄い。</p> <pre>out = oscs + noise; out = out.clip2(1) * amp; </pre><p>clip2で多少歪ませた後に出力値を調整している、細かいがこの順番は大事だろう。アタック音がoscs、残響ノイズがnoise。どちらか一方削って実行してみると理解しやすい。アタック音と残響音を分けてつくり、最後に足し合わせる手法は真似したい。シンセを作成するうえで基本的なことだが、なぜかSCやっていると忘れがち。</p> </div> <div class="section"> <h4>hat 08091500Acid309 by_otophiliaより</h4> <pre class="code" data-lang="" data-unlink>SynthDef(&#34;hat&#34;, { arg outBus=0, amp=0.3; var env1, env2, out, oscs1, noise, n, n2; n = 5; thisThread.randSeed = 4; env1 = EnvGen.ar(Env.new([0, 1.0, 0], [0.001, 0.2], [0, -12])); env2 = EnvGen.ar(Env.new([0, 1.0, 0.05, 0], [0.002, 0.05, 0.03], [0, -4, -4]), doneAction:2); oscs1 = Mix.fill(n, {|i| SinOsc.ar( ( i.linlin(0, n-1, 42, 74) + rand2(4.0) ).midicps, SinOsc.ar( (i.linlin(0, n-1, 78, 80) + rand2(4.0) ).midicps, 0.0, 12), 1/n ) }); oscs1 = BHiPass.ar(oscs1, 1000, 2, env1); n2 = 8; noise = WhiteNoise.ar; noise = Mix.fill(n2, {|i| var freq; freq = (i.linlin(0, n-1, 40, 50) + rand2(4.0) ).midicps.reciprocal; CombN.ar(noise, 0.04, freq, 0.1) }) * (1/n) + noise; noise = BPF.ar(noise, 6000, 0.9, 0.5, noise); noise = BLowShelf.ar(noise, 3000, 0.5, -6); noise = BHiPass.ar(noise, 1000, 1.5, env2); out = noise + oscs1; out = out.softclip; out = out * amp; Out.ar(outBus, out.dup); }).send(s);</pre> </div> <div class="section"> <h4>hatを読む</h4> <pre>n = 5; </pre><p>メイン波形でMixを使用しており、その重ねる回数を定義。このシンセではsin波を5回重ねている。</p> <pre>thisThread.randSeed = 4; </pre><p>ランダムシード定義。thisThreadは調べていないが、このコード内のスレッドって意味かと思われ。</p> <pre>env1 = EnvGen.ar(Env.new([0, 1.0, 0], [0.001, 0.2], [0, -12])); env2 = EnvGen.ar(Env.new([0, 1.0, 0.05, 0], [0.002, 0.05, 0.03], [0, -4, -4]), doneAction:2); </pre><p>いつものenv</p> <pre>oscs1 = Mix.fill(n, {|i| SinOsc.ar( ( i.linlin(0, n-1, 42, 74) + rand2(4.0) ).midicps, SinOsc.ar( (i.linlin(0, n-1, 78, 80) + rand2(4.0) ).midicps, 0.0, 12), 1/n ) }); </pre><p>ハットのメイン波形。まず、Mixは複数チャンネル(配列)を一つのチャンネルに落とし込む。波形を足し合わせているという認識でおk。<br /> freqをちょっと詳しくみてみよう。サイン波を引数ごと分けると以下となる。</p> <blockquote> <p>freq: ( i.linlin(0, n-1, 42, 74) + rand2(4.0) ).midicps<br /> phase: SinOsc.ar( (i.linlin(0, n-1, 78, 80) + rand2(4.0) ).midicps, 0.0, 12)<br /> mul: 1/n</p> </blockquote> <p>まだわかりにくい。linlinが原因かな。linlinはUGenのヘルプ参照するよーに。linlin(inMin, inMax, outMin, outMax, clip)だ<br /> freqのrand2とmisicpsを外して.postlnを付けて値を出力し、それらを配列にいれてplotしてみる。次にmidicpsをつけて、最後にrand2をつけてplot。</p> <blockquote> <p>[42,50,58,66,74].plot;<br /> [92.498605677909,146.8323839587,233.08188075904,369.99442271163,587.32953583482].plot;<br /> [98.263516145654,125.48249990264,257.11842831899,335.51069863238,690.38826095162].plot;</p> </blockquote> <p>本来linlinで42-72まで値が線形に出力されるが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/midi">midi</a>値に変換しており、さらにrand2加えているので結構がたついたplotが確認できる。きれいに並べるよりも多少汚した方がリアルになるとの考えだろうか。</p> <pre>oscs1 = BHiPass.ar(oscs1, 1000, 2, env1); </pre><p>最後にフィルター<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%AB%A4%DE%A4%B7">かまし</a>てアタック音の完成</p> <pre>n2 = 8; noise = WhiteNoise.ar; noise = Mix.fill(n2, {|i| var freq; freq = (i.linlin(0, n-1, 40, 50) + rand2(4.0) ).midicps.reciprocal; CombN.ar(noise, 0.04, freq, 0.1) }) * (1/n) + noise; noise = BPF.ar(noise, 6000, 0.9, 0.5, noise); noise = BLowShelf.ar(noise, 3000, 0.5, -6); noise = BHiPass.ar(noise, 1000, 1.5, env2); </pre><p>ノイズも基本的にメイン波形と同じ作り方。が、freqを逆数にしていたり、よくわからないフィルター<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%AB%A4%DE%A4%B7">かまし</a>たりしている。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%BB%B6%C1%B9%A9%B3%D8">音響工学</a>に基づいて作成しているのだろうか。とりあえず、変数freqをpostlnしてplotしてみよう。</p> <blockquote> <p>[0.025,0.023529411764706,0.022222222222222,0.021052631578947,0.02,0.02,0.02,0.02].plot;<br /> [0.025102866412683,0.024835818361551,0.021720987467888,0.021087916441834,0.019894677979736,0.021583178205406,0.020957042037079,0.019790472120955].plot;<br /> [0.012250345692431,0.011950968549663,0.0085616529455822,0.0079047203612541,0.0067071490182452,0.0084175066708027,0.0077706562061599,0.0066053916708074].plot;</p> </blockquote> <p>こちらのノイズも謎である。</p> <pre>out = noise + oscs1; out = out.softclip; out = out * amp; </pre><p>snareと同じくアタックと残響用のノイズをわけている。こちらもnoiseを外したり、oscsを外したりして確認してみるとよくわかる。softclipはまんまソフトなクリップという認識で良いかと。</p> </div> <div class="section"> <h4>いじょう</h4> <p>ノイズを制するものはパーカッションを制す。<br /> (やはりフィルターがよくわかっていない、誰か分かりやすい解説をしてくれるまで待ってます!)</p> </div> sc3onlinux SC3 こーどりーでぃんぐ1 hatenablog://entry/17680117127138689280 2011-07-02T19:57:13+09:00 2019-05-17T20:20:25+09:00 とりあえずキック部分のメモ書きです。snare,clapもほぼ同様かな。hatは結構複雑。 短いコードの中にも多くの学ぶべきことが詰まっています。supercolliderにおいては人によって書き方が全然違いますが、基本的な部分さえ押さえておけばある程度は読めるはずです。さらに、自分なりの書き方に落とし込めばコーディング力向上間違い無しです! 08091500Acid309 by_otophiliaより SynthDef("kick", { arg outBus=0; var env0, env1, env1m, out; env0 = EnvGen.ar(Env.new([0.5, 1, 0… <p>とりあえずキック部分のメモ書きです。snare,clapもほぼ同様かな。hatは結構複雑。<br /> 短いコードの中にも多くの学ぶべきことが詰まっています。<a class="keyword" href="http://d.hatena.ne.jp/keyword/supercollider">supercollider</a>においては人によって書き方が全然違いますが、基本的な部分さえ押さえておけばある程度は読めるはずです。さらに、自分なりの書き方に落とし込めばコーディング力向上間違い無しです!</p> <div class="section"> <h4>08091500Acid309 by_otophiliaより</h4> <pre class="code" data-lang="" data-unlink>SynthDef(&#34;kick&#34;, { arg outBus=0; var env0, env1, env1m, out; env0 = EnvGen.ar(Env.new([0.5, 1, 0.5, 0], [0.005, 0.06, 0.26], [-4, -2, -4]), doneAction:2); env1 = EnvGen.ar(Env.new([110, 59, 29], [0.005, 0.29], [-4, -5])); env1m = env1.midicps; out = LFPulse.ar(env1m, 0, 0.5, 1, -0.5); out = out + WhiteNoise.ar(1); out = LPF.ar(out, env1m*1.5, env0); out = out + SinOsc.ar(env1m, 0.5, env0); out = out * 1.2; out = out.clip2(1); Out.ar(outBus, out.dup); }).send(s);</pre> </div> <div class="section"> <h4>読む</h4> <pre>env0 = EnvGen.ar(Env.new([0.5, 1, 0.5, 0], [0.005, 0.06, 0.26], [-4, -2, -4]), doneAction:2); </pre><p>なんてことないenv定義。ただし、こいつは波形のmulとして使用される。そのため、このenvが終了した時点でシンセを解放してやればいい。という理由でdoneAction:2を加えている。</p> <pre>env1 = EnvGen.ar(Env.new([110, 59, 29], [0.005, 0.29], [-4, -5])); env1m = env1.midicps; </pre><p>こちらも同じくnewで定義しているなんてことないenv。次の行にてenv1を<a class="keyword" href="http://d.hatena.ne.jp/keyword/midi">midi</a>値へ変換しているが、波形のfreqとして使用されるため。</p> <pre>out = LFPulse.ar(env1m, 0, 0.5, 1, -0.5); </pre><p>freqとして、先ほどのenv1を<a class="keyword" href="http://d.hatena.ne.jp/keyword/midi">midi</a>値にしたものを使用。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%B9%A5%C9%A5%E9%A5%E0">バスドラム</a>など破裂音の周波数は高から低へ瞬間的に遷移するという、正しい理解に基づいた音作り。これは凄い!</p> <pre>out = out + WhiteNoise.ar(1); </pre><p>ここでホワイトノイズをうっすらと加える。ちょっと汚したい時によくやる手法であり覚えておきたい。フィルターで余計な部分をカットしないとダメなので、忘れないように。</p> <pre>out = LPF.ar(out, env1m*1.5, env0); </pre><p>ローパス。カットオフ周波数にenv1を<a class="keyword" href="http://d.hatena.ne.jp/keyword/midi">midi</a>値にしたもの*1.5を使用している。このようにして、ノイズの余計な部分をカットする。さらに、mulにenv0を使用して、もとのLFPulseとそろえている。元の音から外れた余計なノイズが混じらないようにだろう。</p> <pre>out = out + SinOsc.ar(env1m, 0.5, env0); </pre><p>厚みを増すためにサイン波を加えている。ここでも周波数にenv1m、mulにenv0を使用しそろえることで余計な音がかぶらないようにしている。位相をずらしているがなぜだろう?</p> <pre>out = out * 1.2; out = out.clip2(1); </pre><p>ここも面白い。出力を*1.2と無理矢理あげておいてからclip2(1)で出力を1に押さえることで歪ませている。これは使いたい手法。</p> <pre>Out.ar(outBus, out.<a class="keyword" href="http://d.hatena.ne.jp/keyword/dup">dup</a>); </pre><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/dup">dup</a>は配列を返す。デフォ値が2であり、ステレオ出力させたい時によく使う。SC140において有用。</p> </div> <div class="section"> <h4>こんな感じでテンプレ化</h4> <p>シンセ定義した場合はすぐに音が確認できるように。パラメータの数はあまり増やさないように注意。</p> <pre class="code" data-lang="" data-unlink> ( SynthDef(&#34;sc3read_otophilia_kick&#34;,{ arg pan = 0, outBus = 0, clip_amp = 1.0, white_amp=0.0, filter_freq=1.0,sin_phase=0.0; var env_mul, env_freq, signal, outSend; env_mul = Env.new([0.5, 1, 0.5, 0], [0.005, 0.06, 0.26], [-4, -2, -4]); //env_mul.plot; env_mul = EnvGen.ar(env_mul ,doneAction:2); env_freq = Env.new([110, 59, 29], [0.005, 0.29], [-4, -5]); //env_freq.plot; env_freq = EnvGen.ar(env_freq).midicps; //メイン波形。これに色々加えていったり削ったりする。 signal = SinOsc.ar(env_freq, 0, env_mul); //ノイズをどの程度加えると良いか確認してみましょう signal = signal + PinkNoise.ar(white_amp); //cutoff周波数もいじってみましょう signal = LPF.ar(signal, env_freq*filter_freq, env_mul); //厚みを増したい場合には別波形を足す。ノイズ系でもいいかも。位相もいじってみましょう! signal = signal + SinOsc.ar(env_freq,sin_phase,env_mul); //どの程度クリップさせると良いか確認してみましょう outSend = signal * clip_amp; outSend.clip2(1).scope; Out.ar(outBus, Pan2.ar(outSend, pan) ); },metadata: (specs: (clip_amp: [0, 2, \lin],white_amp: [0, 3, \lin], filter_freq: [0, 4, \lin], sin_phase: [0, 1, \lin])) ).store; SynthDescLib.global[\sc3read_otophilia_kick].makeWindow; )</pre> </div> <div class="section"> <h4>いじょう</h4> <p>メモだけど、アウトプット、アウトプット。</p> </div> sc3onlinux Unity3d + kinect hatenablog://entry/17680117127138689366 2011-05-31T21:41:19+09:00 2019-05-17T20:20:26+09:00 はじめに ゲーム開発環境なら余裕でkinect接続できるよね?ってことでunityのフォーラム見ていたら、win,macともにOpenNIがいけるようです。ちょっとごちゃっているので簡単にまとめました。 macOSX10.6ですよ。 準備 libtool,libusb-develが必要なようです。 macportで入れましょう。 port installed | grep libusb-devel (すでにインストールされていた場合は削除しましょう。sudo port unistall libusb-devel) sudo port libtool sudo port libusb-devel… <div class="section"> <h4>はじめに</h4> <p>ゲーム開発環境なら余裕で<a class="keyword" href="http://d.hatena.ne.jp/keyword/kinect">kinect</a>接続できるよね?ってことでunityのフォーラム見ていたら、win,<a class="keyword" href="http://d.hatena.ne.jp/keyword/mac">mac</a>ともにOpenNIがいけるようです。ちょっとごちゃっているので簡単にまとめました。<br /> macOSX10.6ですよ。</p> </div> <div class="section"> <h4>準備</h4> <p>libtool,libusb-develが必要なようです。<br /> macportで入れましょう。</p> <pre class="code" data-lang="" data-unlink>port installed | grep libusb-devel  (すでにインストールされていた場合は削除しましょう。sudo port unistall libusb-devel) sudo port libtool sudo port libusb-devel +universal</pre><p> +universal付け忘れるなよ!とのことです。</p> </div> <div class="section"> <h4>おとす</h4> <p>色々DLします。リンク変わっていたらごめんなさい(2011/09/01修正)</p> <ul> <li>OpenNI <ul> <li><a href="http://www.openni.org/downloadfiles/opennimodules/openni-binaries/20-latest-unstable">http://www.openni.org/downloadfiles/opennimodules/openni-binaries/20-latest-unstable</a> <ul> <li>Build for <a class="keyword" href="http://d.hatena.ne.jp/keyword/MacOSX">MacOSX</a></li> </ul></li> </ul></li> <li>SensorKinect <ul> <li><a href="https://github.com/avin2/SensorKinect">https://github.com/avin2/SensorKinect</a></li> </ul></li> <li>NITE <ul> <li><a href="http://www.openni.org/downloadfiles/opennimodules/openni-compliant-middleware-binaries/33-latest-unstable">http://www.openni.org/downloadfiles/opennimodules/openni-compliant-middleware-binaries/33-latest-unstable</a> <ul> <li>Build for <a class="keyword" href="http://d.hatena.ne.jp/keyword/MacOSX">MacOSX</a></li> </ul></li> </ul></li> </ul><p>ここまでは<a class="keyword" href="http://d.hatena.ne.jp/keyword/mac">mac</a>でOpenNI使う場合と同じです。unityで使用する場合はunitywrapperもDLします。</p> <ul> <li>UnityWrapper <ul> <li><a href="https://github.com/tinkerer/UnityWrapper">https://github.com/tinkerer/UnityWrapper</a></li> </ul></li> </ul> </div> <div class="section"> <h4>いれる</h4> <p>インストールします。</p> <div class="section"> <h5>OpenNI</h5> <p>解凍した<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リにいって</p> <pre class="code" data-lang="" data-unlink>sudo ./install.sh</pre><p>します。</p> </div> <div class="section"> <h5>SensorKinect</h5> <p>同じく解凍した<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リ配下のBin<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リにいき、SensorKinect-Bin-<a class="keyword" href="http://d.hatena.ne.jp/keyword/MacOSX">MacOSX</a>-xxxを解凍。解凍先の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リにいって</p> <pre class="code" data-lang="" data-unlink>sudo ./install.sh</pre><p>します。</p> </div> <div class="section"> <h5>NITE</h5> <p>これも同じ。ライセンスの入力を求められます。<a href="http://www.openni.org/downloadfiles/opennimodules">http://www.openni.org/downloadfiles/opennimodules</a> のOpenNI Compliant Middleware Binariesの部分の太字をコピペしましょう。</p> <pre class="code" data-lang="" data-unlink>sudo ./install.sh Please enter your PrimeSense license key: </pre> </div> <div class="section"> <h5>UnityWrapper</h5> <p>こいつは解凍するだけ</p> </div> </div> <div class="section"> <h4>確認</h4> <p>とりあえず、<a class="keyword" href="http://d.hatena.ne.jp/keyword/kinect">kinect</a>が動作するか確認しておきましょう。NITE<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リ配下のSample/Bin/以下をターミナルから適当に実行してみましょう。</p> </div> <div class="section"> <h4>Unity</h4> <p>ようやく環境が整ったのでUnity側に移りましょう。UnityのOpen Projectから先ほど解凍したUnityWrapper<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リを開きましょう。<a href="http://planetmatt.com/integrate-kinect-unity3d-on-mac/">http://planetmatt.com/integrate-kinect-unity3d-on-mac/</a> を参考にサンプルを動かしてみましょう。</p> <div class="section"> <h5>サンプルを試す</h5> <ol> <li>WalkRunIdleBlendを開きます。</li> <li>もともとHiearchyにあるsoldierはなんか見えないので削除</li> <li>ProjectのSoldierをHiearchyにD&D</li> <li>ちっちゃいのでSoldierのScaleを200,200,200に変更</li> <li>テクスチャが欲しいので、Projectのsoldier_blueをSceneのSoldierにD&D</li> <li>ついでに、bridgegroundstones_layersもCubeにD&D</li> <li>CubeのInspectorのMono Behaviourをいじります <ol> <li>ScriptをNiteにします</li> <li>Right_HandをR_Handにします</li> <li>Right_ElbowをR_Elbowにします</li> <li>以下それっぽいものを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%B5%A5%A4">アサイ</a>ンします(Left_Elbowを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%B5%A5%A4">アサイ</a>ンしないとなぜか落ちます)</li> <li>カメラにSmooth Follow<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>も追加しますか。main cameraを選択して、Component>Camera-Control>Smooth Follow。適当にtargetとか変更。</li> </ol></li> <li>playボタンで起動します <ol> <li>New User Foundとコンソールに表示されるまで<a class="keyword" href="http://d.hatena.ne.jp/keyword/kinect">kinect</a>の前で待ちます</li> <li>Soldierがそれっぽく動きます</li> </ol></li> </ol> </div> </div> <div class="section"> <h4>いじょう</h4> <p>動いた!ま、そんだけです。game objectがまだ全然分かっていないのでなにも出来ませんが、パーティクルかなにかに右手<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%B5%A5%A4">アサイ</a>ンしてOSCでSCに値返してエフェクタ制御とか、そんな感じですかね。</p> </div> sc3onlinux SuperCollider + Unity3d hatenablog://entry/17680117127138689505 2011-05-28T18:07:17+09:00 2019-05-17T20:20:27+09:00 はじめに Unityというゲーム開発環境があります。UbuntuのUIじゃないですよ。機能制限はありますが、フリーです。iOSのゲーム開発にも使用されているようで、日本語の情報も結構あります。UnityではC#でスクリプト書けるとのことでしたので誰かOSC使えるようにしてるだろ、とググったら引っかかりましたので、ちょっといじってみました。 プロジェクトサンプルをゲット http://forum.unity3d.com/threads/16882-MIDI-or-OSC-for-Unity-Indie-users でプロジェクトサンプルをUPしてくれている方がいるので、使わさせてもらいましょう。… <div class="section"> <h4>はじめに</h4> <p>Unityというゲーム開発環境があります。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ubuntu">Ubuntu</a>のUIじゃないですよ。機能制限はありますが、フリーです。<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>のゲーム開発にも使用されているようで、日本語の情報も結構あります。Unityでは<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%23">C#</a>で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>書けるとのことでしたので誰かOSC使えるようにしてるだろ、とググったら引っかかりましたので、ちょっといじってみました。</p> </div> <div class="section"> <h4>プロジェクトサンプルをゲット</h4> <p><a href="http://forum.unity3d.com/threads/16882-MIDI-or-OSC-for-Unity-Indie-users">http://forum.unity3d.com/threads/16882-MIDI-or-OSC-for-Unity-Indie-users</a><br /> でプロジェクトサンプルをUPしてくれている方がいるので、使わさせてもらいましょう。<a class="keyword" href="http://d.hatena.ne.jp/keyword/MacOSX">MacOSX</a>、Unity3.3.04fの環境では、UDPPacketIO.csを</p> <blockquote> <p><del>using System.IO.<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ports">Ports</a>;</del><br /> using System.IO;</p> </blockquote> <p>に変更しないとダメです。</p> </div> <div class="section"> <h4>試してみる</h4> <div class="section"> <h5>Unity側</h5> <p>HiearchyのOSCEmptyオブジェクトをクリック。<br /> 右枠にInspectorが開くので、OSCReciverのRemote IP,portを自分の環境に。<br /> Unity側の再生ボタンを押します。</p> </div> <div class="section"> <h5>SC側</h5> <p>"/1/toggle1"に適当に数値送ります。</p> </div> <div class="section"> <h5>確認する</h5> <ul> <li>オブジェクトが動く</li> <li>Unityのコンソールにメッセージ名と値が流れる</li> </ul> </div> </div> <div class="section"> <h4>いじる</h4> <p>詳しく調べる気はないので、handler.SetAddressHandler("メッセージ名", 関数名);でOSCメッセージ名、関数を指定、OSCメッセージ値を関数内で変数に代入、Update関数でGameObjectのパラメータを更新させる。<br /> という処理を丸パクリして、追加したゲームオブジェクトをいじってみる。うーむ、楽です。</p> </div> <div class="section"> <h4>いじょう</h4> <p>3D映像をSCから制御したい場合、oF、P5でコーディングするよりも、<a class="keyword" href="http://d.hatena.ne.jp/keyword/blender">blender</a>、Unity使うと圧倒的に楽かと。相変わらずSCはよく分かりませんが、Unity側をもうちょっといじってみようかと思います。<br /> OSCなので、SCからだけじゃなくてMax/PDからも制御できますよ。</p> </div> sc3onlinux SuperColliderのクラスメモ hatenablog://entry/17680117127138689591 2011-02-28T20:53:02+09:00 2019-05-17T20:20:28+09:00 単なるメモ 特に難しいことはないかと クラスファイル側 /* 0. はじめに */ MyClassPre{ } /* 1. 変数 */ /* 変数の宣言はいつもどおりvar <でゲッター、ゲッターはオブジェクトの外側から変数の値を取得できるようにする >でセッター、セッターはオブジェクトの外側から変数の値を設定できるようにする */ MyClassVar { var <>x; var y; } /* 2. メソッド */ MyClassMethod { var <>x; /* *付きでクラスメソッド クラスメソッドとは、インスタンスを生成しなくても直接クラスから呼び出せるメソッド */ *ne… <p>単なるメモ<br /> 特に難しいことはないかと</p> <div class="section"> <h4>クラスファイル側</h4> <pre class="code" data-lang="" data-unlink>/* 0. はじめに */ MyClassPre{ } /* 1. 変数 */ /* 変数の宣言はいつもどおりvar &lt;でゲッター、ゲッターはオブジェクトの外側から変数の値を取得できるようにする &gt;でセッター、セッターはオブジェクトの外側から変数の値を設定できるようにする */ MyClassVar { var &lt;&gt;x; var y; } /* 2. メソッド */ MyClassMethod { var &lt;&gt;x; /* *付きでクラスメソッド クラスメソッドとは、インスタンスを生成しなくても直接クラスから呼び出せるメソッド */ *new{ ^super.new //ここでのsuperはobject。help-&gt;class browserのsuperボタンを押してもわかる } /* *なしでインスタンスメソッド インスタンスメソッドとは、インスタンスから呼び出すメソッド */ postMethod { ^x.postln; } /* argで引数 ^で戻り値 */ postMethod2{ arg a,b; var c = a+b; ^c.postln; } } /* 3. ちょっと書いてみる */ //Objectは勝手に継承 SynthPlusFilter{ var &lt;&gt;mysyn,&lt;&gt;myfilter; var &gt;freq=440,&gt;q=1.0,&gt;mul=1.0,&gt;add=0.0; *new{ arg mysyn,myfilter; ^super.newCopyArgs(mysyn,myfilter); } play{ play{myfilter.ar(mysyn.ar(),freq,q,mul,add);} } } /* 4. もうちょい書いてみる */ SubSynthDef{ var &lt;&gt;defName,&lt;&gt;mysyn1,&lt;&gt;mysyn1Param,&lt;&gt;myfilter,&lt;&gt;myfilterParam,&lt;&gt;myenv; *new{ arg defName,mysyn1,myfilter,myenv; ^super.newCopyArgs(defName,mysyn1,myfilter,myenv); } def{ arg bus=0, pan=0; SynthDef(defName,{ var signal,envelope,filter,out; mysyn1Param.postln; signal=mysyn1.ar(mysyn1Param); filter=myfilter.ar(signal,myfilterParam); envelope=EnvGen.ar(myenv,doneAction:2); Out.ar(bus, Pan2.ar(envelope*filter,pan); ); }).store; } play{ Synth(defName).play; } }</pre> </div> <div class="section"> <h4>rtf側</h4> <pre class="code" data-lang="" data-unlink>/*0. はじめに*/ /* .scのファイル名でクラスファイルを作る 保存する場所は */ Platform.userExtensionDir; //保存したらmenu-&gt;Lang-&gt;compile library(もしくはpostウィンドウでcmd+K)して、下が実行できればおk MyClassPre /*1. 変数*/ ( var test =MyClassVar.new; test.x = 1; //test.x_(1);も同じ意味 test.x.postln; //test.y = 2; //NG //test.y; //NG ) /*2. メソッド*/ ( var test = MyClassMethod.new; test.x_(10); test.postMethod; test.postMethod2(1,2); //var ngTest = MyClassMethod.postMethod; //test.new; ) /* 3. ちょっと書いてみる */ //継承とか色々あるけれど、上記だけで簡単なクラスは書ける。特に意味はないクラスだけど //newは省略できる ( var test1 = SynthPlusFilter(WhiteNoise,RLPF); var test2 = SynthPlusFilter(SinOsc,RHPF); test1.freq_(220).mul_(0.5).play; test2.freq_(1000).play; test1.mysyn.postln; test2.mysyn; //以下と同じこと //{RLPF.ar(WhiteNoise.ar(),220,mul:0.5)}.play; //{RHPF.ar(SinOsc.ar(),1000)}.play; ) /* 4. もうちょっと書いてみる */ //さらに意味はないクラスだけど、ちょっとすっきり ( var test1 = SubSynthDef(&#39;subtest1&#39;, SinOsc,[440,0.8,0], RLPF,[220,1.0,1.0,0.0], Env.perc(0.01,0.4) ); var test2 = SubSynthDef(&#39;subtest2&#39;, Blip,[440,110,0.5,0], RHPF,[1000,1.0,1.0,0.0], Env.perc(0.1,1.0) ); test1.def(); test2.def(); test1.play; test2.play; )</pre> </div> <div class="section"> <h4>以上</h4> <p>継承などをうまくつかっていくと表のコードはすっきりきれいに早く書けます。<br /> でも、クラスライブラリ充実しているから別に自分で書かなくても良いと思います。ライブコーディングやる場合、あらかじめ自分でクラス書いておくと、かなり早くなりそうですね。</p> </div> sc3onlinux そろそろstartup.rtfについて書いておく #SuperCollider hatenablog://entry/17680117127138689727 2011-01-07T22:14:07+09:00 2019-05-17T20:20:29+09:00 SynthDefを1024個以上使用するSCヘビーユーザの皆様こんにちは。ヘルプのServerOptions.htmlは見たことありますか? ServerOptionsを使おう SCの初期設定ではサンプルレートが44.1kHzだったりメモリの確保がちょいと低かったりします。ローカルサーバをデフォでブートさせると、以下のように表示されますね。 SC_AudioDriver: sample rate = 44100.000000, driver's block size = 512こんなんじゃダメだ!という方のために、SCのサーバには豊富はメソッドが実装されており、色々設定を変更したりできます。サ… <p>SynthDefを1024個以上使用するSCヘビーユーザの皆様こんにちは。ヘルプのServerOptions.htmlは見たことありますか?</p> <div class="section"> <h4>ServerOptionsを使おう</h4> <p>SCの初期設定ではサンプルレートが44.1kHzだったりメモリの確保がちょいと低かったりします。ローカルサーバをデフォでブートさせると、以下のように表示されますね。</p> <pre class="code" data-lang="" data-unlink>SC_AudioDriver: sample rate = 44100.000000, driver&#39;s block size = 512</pre><p>こんなんじゃダメだ!という方のために、SCのサーバには豊富はメソッドが実装されており、色々設定を変更したりできます。サンプルレートを変更するには、sampleRateメソッドが。ブロックサイズを変更するにはblockSizeメソッドがあります。</p> <pre class="code" data-lang="" data-unlink>o = Server.local.options; o.sampleRate = 96000; o.blockSize = 128;</pre><p>など実行してからサーバをブートさせると、</p> <pre class="code" data-lang="" data-unlink>SC_AudioDriver: sample rate = 96000.000000, driver&#39;s block size = 1024</pre><p>なんとちゃんと反映されています。素晴らしい。<br /> サーバオプションのメソッドには他にもmemSize、maxSynthDefsなどなど色々あります。maxSynthDefsの初期値は1024なので、SynthDefを1024個以上使う場合は変更しておく必要があります(たぶん、試したことないで)。これらのメソッドはServerOptions.htmlに書いてあります。そのうち誰か詳細を書いてくれると思います。お願いしますw</p> </div> <div class="section"> <h4>ここでstartup.rtfの登場</h4> <p>SCを立ち上げてからいちいちコード実行して設定を変更させる、なんてのはあり得ない。そこで、SC立ち上げた時に必ず見に行くstartup.rtfにこいつらを記述しておきましょう。startup.rtfファイルは</p> <pre class="code" data-lang="" data-unlink>- On Mac OS X the path is either &#34;/Library/Application Support/SuperCollider/startup.rtf&#34; (i.e. a system-wide file) or &#34;~/Library/Application Support/SuperCollider/startup.rtf&#34; (i.e. a user-specific file). Both files can be used, where the system-wide file is executed before the user-specific file. - On Linux the path is &#34;~/.sclang.sc&#34; - On Windows the file is &#34;startup.sc&#34; and needs to be in the same directory as PsyCollider</pre><p>らしいです。そんなわけで、startup.rtfファイルに</p> <pre class="code" data-lang="" data-unlink>Server.local.options.blockSize = 128; Server.local.options.sampleRate = 96000; Server.local.boot; Document.openAutoComplete;</pre><p>などなど書いておけば、好みの設定で起動できてオートコンプリート設定でファイルを開くことができます。</p> </div> <div class="section"> <h4>以上</h4> <p>因に、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Emacs">Emacs</a>使っているとなんか読み込んでくれません。どうするんだろう?</p> </div> sc3onlinux SuperColliderを始めようと思う、エディタはEmacsっての使っておけば良いんだろ? hatenablog://entry/17680117127138689808 2011-01-06T22:30:00+09:00 2019-05-17T20:20:29+09:00 こんなスレタイがちょいと流行った。しかし、繰り返しはすぐに飽きられるのはいつの時代も変わらないだろう、もうほとんど見かけない。さて、かつて本blogではSuperCollider on Emacsの導入記事を書いたわけですが、繰り返しスパコEmacsについて書いてみようと思います。良いんだろ? (参考) ぜろから導入、cocoa emacsでSuperCollider Cocoa EmacsでSuperCollider 2 デフォルトエディタ SCのデフォルトのエディタはそんなに貧弱ではありませんので、舐めてはいけません。もしかしたら、デフォエディタを使用している人がほとんどかもしれませんし。… <p>こんな<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%EC%A5%BF%A5%A4">スレタイ</a>がちょいと流行った。しかし、繰り返しはすぐに飽きられるのはいつの時代も変わらないだろう、もうほとんど見かけない。さて、かつて本blogでは<a class="keyword" href="http://d.hatena.ne.jp/keyword/SuperCollider">SuperCollider</a> on <a class="keyword" href="http://d.hatena.ne.jp/keyword/Emacs">Emacs</a>の導入記事を書いたわけですが、繰り返しスパコ<a class="keyword" href="http://d.hatena.ne.jp/keyword/Emacs">Emacs</a>について書いてみようと思います。良いんだろ?<br /> (参考)<br /> <a href="http://d.hatena.ne.jp/sc3onlinux/20100523/1274600496">&#x305C;&#x308D;&#x304B;&#x3089;&#x5C0E;&#x5165;&#x3001;cocoa emacs&#x3067;SuperCollider</a><br /> <a href="http://d.hatena.ne.jp/sc3onlinux/20100524/1274712088">Cocoa Emacs&#x3067;SuperCollider 2</a></p> <div class="section"> <h4>デフォルトエディタ</h4> <p>SCのデフォルトのエディタはそんなに貧弱ではありませんので、舐めてはいけません。もしかしたら、デフォエディタを使用している人がほとんどかもしれませんし。フォントをちゃちゃっといじれて、そのままhtmlとして保存することもできます。コードにちょっと解説書いてupする方には便利かと。さらに、特筆すべきは、autocomplete機能でしょう。(最近まで知りませんでしたが)<br /> 使用方法は、help.htmlのAuto Completionに記載されています。</p> <pre class="code" data-lang="" data-unlink>Document.autoComplete //オートコンプリート環境の新しいウィンドウを開く Document.openAutoComplete //ファイルを指定して開く</pre><p>SinOsc.とかまで打つと、別ウィンドウが開いてメッセージ(メソッド)を表示してくれます。なんと、引数も一緒に出してくれたりします!今のご時世当たり前ですよねー。ま、デフォで補完してくれませんし新しいウィンドウを開かれると、いらっとしたりする可能性もなきにしもあらずです。たぶん、startup.rtfにここらへんを記述しておけば、デフォでおkだと思いますが。</p> </div> <div class="section"> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/Emacs">Emacs</a>の魅力とは?</h4> <div class="section"> <h5>導入</h5> <p>scelの導入は結構面倒っちゃ面倒です。導入方法の元ネタは、<br /> <a href="http://sam.aaron.name/2010/02/09/hooking-supercollider-up-to-emacs-on-os-x.html">http://sam.aaron.name/2010/02/09/hooking-supercollider-up-to-emacs-on-os-x.html</a><br /> であり<br /> <a href="http://blog.noanoa.asia/2010/05/emacssupercolliderosx.html">http://blog.noanoa.asia/2010/05/emacssupercolliderosx.html</a><br /> や本blogにも記載してあります。</p> </div> <div class="section"> <h5>それでも使う</h5> <p>そもそも<a class="keyword" href="http://d.hatena.ne.jp/keyword/Emacs">Emacs</a>は非常に強力なエディタでその拡張性は、っぱないです。vi?はあ、死ねよ。とか、好きな人はもの凄い好きなんですよね。慣れるのに時間かかりますけれど、慣れると手放せないです。慣れないと手がつけられないです。ググれば<a class="keyword" href="http://d.hatena.ne.jp/keyword/Emacs">Emacs</a>さいこー!とか死ぬほどひっかかりますので興味あればぜひ。<br /> で、SCで<a class="keyword" href="http://d.hatena.ne.jp/keyword/Emacs">Emacs</a>を使う利点は、ひゃっほー、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Emacs">Emacs</a>でSCのコードが書ける!という他に、デフォエディタでは、補完機能使うためにちょっと手間でしたが、Emcasを使うとデフォでC-c C-nかM-Tabで補完してくれます。うざい新規ウィンドウも開きません。また、デフォエディタでは()内のコードを実行するのに、ダブルクリックか&#8984;+Bとか選択してから実行と二段階で実行していましたが、Emcasだと、C-M-xをぽちっとすれば()内のどこからでも実行可能です。なんと、これは便利!ヘルプファイルも<a class="keyword" href="http://d.hatena.ne.jp/keyword/w3m">w3m</a>を入れておけば、一つのウィンドウで操作可能ですし、小さなディスプレイですと非常に有り難いです。いやいや、私はpostウィンドウが開いていないとSC書いている気がしない、などという人にはウィンドウ分割して横に表示させておけば良いだけでしょう。<br /> また、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%F3%A5%BF%A5%C3%A5%AF%A5%B9">シンタックス</a>ハイライトもデフォなのでうれしいところです。いちいち、&#8984;+'とか打たなくても良く、デフォエディタよりも見やすいです。<br /> なんだかんだで、1アクション短縮できるということは、非常に魅力的だと思います。</p> </div> <div class="section"> <h5>やっぱり使わない</h5> <p>cocoaGUIは使用出来ません。<a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a>使用するならSwingOSC一択になってしまいます。そもそも<a class="keyword" href="http://d.hatena.ne.jp/keyword/Emacs">Emacs</a>は慣れるのにちょいと時間がかかりますし、自分に最適な環境を作ろうといじりだすと、手段と目的が入れ替わります。確実に。もしかしたら、環境によっては上手く動作しないことがあるかもしれません。よくわかりません。<a href="http://bit.ly/feyIF0">http://bit.ly/feyIF0</a><br /> あと、暫く使っていないとすぐにショートカットキー忘れます。</p> </div> </div> <div class="section"> <h4>以上</h4> <p>ま、自分の好みですかねー。vi派にはscvimなんてものもありますよー。そもそも、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a>からSC使いだすと<a class="keyword" href="http://d.hatena.ne.jp/keyword/Emacs">Emacs</a>選択せざるをえないんですけれどね。win環境ではエディタが貧弱なのでつらいところです。</p> </div> sc3onlinux cinder導入メモ hatenablog://entry/17680117127138689945 2010-12-13T20:49:49+09:00 2019-05-17T20:20:31+09:00 最近、kinect関連やflight404氏のおかげで情報が増えてきましたが、macにて導入時にエラーが出力されたりして、ちょっと困ったので、メモしておきます。 インストール 非常にありがたい記事を書いてくれているので、ここを参考にインストールしましょう。boostいれる時点で結構時間がかかりますよ。 http://sora2hs.blog70.fc2.com/blog-entry-514.html boostインストール 上記にも記載してくれています。本元が見たければこちらです。 http://libcinder.org/docs/v0.8.2/_cinder_boost.html なんかエ… <p>最近、<a class="keyword" href="http://d.hatena.ne.jp/keyword/kinect">kinect</a>関連やflight404氏のおかげで情報が増えてきましたが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/mac">mac</a>にて導入時にエラーが出力されたりして、ちょっと困ったので、メモしておきます。</p> <div class="section"> <h4>インストール</h4> <p>非常にありがたい記事を書いてくれているので、ここを参考にインストールしましょう。boostいれる時点で結構時間がかかりますよ。<br /> <a href="http://sora2hs.blog70.fc2.com/blog-entry-514.html">http://sora2hs.blog70.fc2.com/blog-entry-514.html</a><br /> </p> </div> <div class="section"> <h4>boostインストール</h4> <p>上記にも記載してくれています。本元が見たければこちらです。<br /> <a href="http://libcinder.org/docs/v0.8.2/_cinder_boost.html">http://libcinder.org/docs/v0.8.2/_cinder_boost.html</a><br /> </p> </div> <div class="section"> <h4>なんかエラーがでたよ</h4> <p>ちゃんと上記に従ってインストールしていればほとんどエラーは出ませんが、メモとして。</p> <ul> <li>boost/*: No such file or directory</li> </ul><p>boostを上記に従ってインストールしましょう。</p> <ul> <li>"_AudioComponentFindNext", referenced from:</li> <li>"_AudioComponentInstanceDispose", referenced from:</li> <li>"_AudioComponentInstanceNew", referenced from:</li> </ul><p>これら3つのエラーが出力された場合、<br /> プロジェクト>プロジェクト設定を編集>ベース<a class="keyword" href="http://d.hatena.ne.jp/keyword/SDK">SDK</a>を10.6にしてみましょう。</p> <ul> <li>Command /Developer/usr/bin/g++-4.2 failed with exit code 1</li> </ul><p>エラー内容を見てみると、../../../lib/libcinder_d.a: No such file or directory とあるはずです。<br /> この場合は、cinderをビルドしていないためにlibcinder_d.aが作成されていないので、まずはビルドしましょう。解凍した<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リの配下、<a class="keyword" href="http://d.hatena.ne.jp/keyword/xcode">xcode</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リ内にfullbuild.sh<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>がありますので、こいつを実行してビルドします。もちろん、cinder.xcodeprojを開いてビルドしてもおkです。</p> <ul> <li>EXC_BAD_<a class="keyword" href="http://d.hatena.ne.jp/keyword/ACCESS">ACCESS</a></li> </ul><p>私の環境にてcinderISOのサンプルを動かそうとして、エラーが出力されました。どうやらcinderを<a class="keyword" href="http://d.hatena.ne.jp/keyword/github">github</a>経由で最新版をいれないとダメだそうです。入れ直したところ、SimpleExampleは低<a class="keyword" href="http://d.hatena.ne.jp/keyword/FPS">FPS</a>ながらちゃんと動きました。</p> </div> <div class="section"> <h4>以上</h4> <p>cinderは、最近リリースのため、フォーラム以外に情報がほとんどありませんが、だんだん日本語の情報も出てきており非常に期待できるライブラリですね。p5やoFよりもリッチな映像をプログラミングしたい場合には最適かと。結構難しそうですが。OSC、tuio、<a class="keyword" href="http://d.hatena.ne.jp/keyword/openCV">openCV</a>、<a class="keyword" href="http://d.hatena.ne.jp/keyword/kinect">kinect</a>も問題なく使えます!</p> </div> sc3onlinux SuperColliderショートカットマスターへの道2 - Syntax Shortcuts - hatenablog://entry/17680117127138690059 2010-10-11T20:38:53+09:00 2019-05-17T20:20:32+09:00 前回の続き。ちょっとはsmalltalkのオブジェクト指向に慣れて、今まで分からなかったコードも理解出来るようになった気がします。というわけで、Syntax-Shortcuts.htmlを紐解いてみたいと思います。 4. ショートカット shortcut では、ショートカット記述について、helpのsyntax shortcutから学んでいきましょう。 メッセージの2通りの記述方法 1.4.2 謎の記述方法にて、レシーバを省略するとメッセージ内の第1引数がレシーバとして認識される、ということがわかりました。別に内部でどのように認識されているのか詳しく知る必要はないかと思います。helpのMet… <p>前回の続き。ちょっとは<a class="keyword" href="http://d.hatena.ne.jp/keyword/smalltalk">smalltalk</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%D6%A5%B8%A5%A7%A5%AF%A5%C8%BB%D8%B8%FE">オブジェクト指向</a>に慣れて、今まで分からなかったコードも理解出来るようになった気がします。というわけで、Syntax-Shortcuts.htmlを紐解いてみたいと思います。</p> <div class="section"> <h4>4. ショートカット shortcut</h4> <p> では、ショートカット記述について、helpのsyntax shortcutから学んでいきましょう。<br /> </p> <div class="section"> <h5>メッセージの2通りの記述方法</h5> <p> 1.4.2 謎の記述方法にて、レシーバを省略するとメッセージ内の第1引数がレシーバとして認識される、ということがわかりました。別に内部でどのように認識されているのか詳しく知る必要はないかと思います。helpのMethod-Callsを見てみると、バイナリオペレータのメッセージは、関数形式とレシーバ形式どっちでも書けるよ!とありますね。</p> <pre class="code" data-lang="" data-unlink> //functional notation do ( 2, { arg x; x.postln } ); //receiver notation 2.do ( { arg x; x.postln } );</pre><p>というわけで、メッセージの記述方法(レシーバの指定方法)は基本的に上記の2通りです(他にbinary operator syntaxとか?)。どちらが正しいとかショートカットだとかは特にないようです。ただし、1.4.2で解説したように、上の記述方法では、関数形式ですが”2”にあたる第1引数はSC内でレシーバとして認識されているようです。上の関数形式は<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%B8%C0%B8%EC">C言語</a>ライクに、do関数に2つの実引数を渡していると読めます。一方、下の記述方法は、<a class="keyword" href="http://d.hatena.ne.jp/keyword/smalltalk">smalltalk</a>流のメッセージ式に乗っ取った記述方法で、2というレシーバにメッセージとして、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BB%A5%EC%A5%AF%A5%BF">セレクタ</a>はdo、引数は関数を送っているという解釈になります。(どちらも書けるようにしたのは、Cになれた人でも書けるよ!とかやりたかったのかなあ?)<br /> メッセージが1つなら苦労はしませんが、実際のコードでは複数のメッセージを組み合わせて使いますよね。関数内に関数を書いたり、レシーバの戻り値をレシーバとしたり。2つのメッセージでも以下のようにややこしく書けたりします。</p> <pre class="code" data-lang="" data-unlink> //完全に関数形式。これはわかりやすいですね max( min ( 10, 100 ), 1 ); //minだけレシーバ形式に変換可能です。 max( 10.min( 100 ), 1 ); //上のコードでのmaxの第1引数は10.min(100)、これはレシーバとして扱えるので”.”の前に出せます。このコードは全部レシーバ形式ですね。 10.min( 100 ).max( 1 ); //minを関数形式に戻してみる。 min( 10, 100 ).max( 1 ); </pre><p>以上のように、関数形式とレシーバ形式の両方で書け、さらに混在させることもできます。コード読むときには、どちらか好きな方に変換してみるとより理解しやすいかもしれませんね。</p> <pre class="code" data-lang="" data-unlink> //どっちが分かりやすいかはケースバイケースですね。myValをごにょごにょしたい場合は下のようにレシーバ形式にした方が直感的かなと。 var myVal=100; hypot( atan2( absdif( distort( myVal, 2), 1 ), 1 ), 20 ); var myVal=100; myVal.distort(2).absdif(1).atan2(1).hypot(20);</pre> </div> <div class="section"> <h5>アクセサメソッド</h5> <p> クラスを書く際に、変数へのアクセスをメソッドで制限することがあります。アクセサメソッドには、セッター、ゲッターがあり、それぞれ変数へ値を代入する、変数の値を参照するメソッドのことです。helpのClassesにセッター、ゲッターの説明があります。ゲッターメッセージは変数と同じ名前でレシーバに送ったときに、その変数の値を返す、セッターメッセージは変数と同じ名前プラス”_”に加え引数にその変数に代入したい値を指定するわけですよ。とか書いてあります。セッターメソッドがなければ、変数に代入できませんし、ゲッターがなければ参照できないわけですね。<br /> と、前置きはこのくらいにして、ヘルプファイルには、instead of writing: に謎の文が書いてありますが、これらは1行目に変数宣言、2行目にゲッターメソッド、3行目にセッターメソッドが定義されています。ぱっと見分かりづらいですが、^は返り値を示しているので、xメソッドはxの値を返す、x_メソッドは引数を変数xに代入する、という処理を行っています。クラスを書くとき、変数はvar 変数名と宣言します。</p> <pre class="code" data-lang="" data-unlink> ついでにセッターメソッドも定義したい場合は var &gt;x; ゲッターメソッドも定義したい場合は var &lt;x; どちらも定義したい場合は var &lt;&gt;x; と記述します。方向で処理を表しているんですね。</pre><p>instead of writing: みたいに書く人は皆無だと思いますので、<>の記述が基本だと思いますよ。</p> </div> <div class="section"> <h5>セッターメソッドの呼び出し。セッターメッセージの記述方法</h5> <p> 上でセッターの定義の記述方法について述べました。では、セッターメソッドの呼び出し方法について。instead of writing: ではセッターメソッドをx_、変数名_で記述していました。ということは、instance.x_(引数) のx_メッセージで変数xに引数を渡すことができるわけです。変数名_が基本かどうかは不明ですが、より分かりやすい記述方法があります。</p> <pre class="code" data-lang="" data-unlink> //myInstanceクラスがあるとして、var &lt;&gt;x;を宣言していると仮定してください。 //変数xに1を代入 myInstance.x_(1); //変数xに1を代入 myInstance.x = 1;</pre><p>これもどちらが良いというのはなく、下の記述方法はCライクでわかりやすいです。上の記述方法は、ある<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>の複数の変数に値を代入する際に役立ちます。</p> <pre class="code" data-lang="" data-unlink> myInstance.x_(1).y_(2).z_(3);</pre><p>とかですね。SC140で役立つと思いますよ。たぶん。<br /> </p> </div> <div class="section"> <h5>バイナリオペレータとして<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BB%A5%EC%A5%AF%A5%BF">セレクタ</a>を使う</h5> <p> なんでしょうねこの記述方法は。</p> <pre class="code" data-lang="" data-unlink> min(1,2); //functional notation 1 min: 2 //?</pre><p> 1がレシーバ、minは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BB%A5%EC%A5%AF%A5%BF">セレクタ</a>で2が引数を表しています。<a class="keyword" href="http://d.hatena.ne.jp/keyword/smalltalk">smalltalk</a>にこの記述方法があります。(参考)<a href="http://d.hatena.ne.jp/sumim/20100207/p1">http://d.hatena.ne.jp/sumim/20100207/p1</a> の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BB%A5%EC%A5%AF%A5%BF">セレクタ</a>ー</p> </div> <div class="section"> <h5>コレクションの要素にアクセス</h5> <p> これはたまに見かけますね。コードは短くなりますが、大抵の人は読めなくなるでしょう。</p> <pre class="code" data-lang="" data-unlink> z=[1,2,3,4]; x = z.at(0); y = z.at(1); x.postln; y; z=[1,2,3,4]; #x, y = z; x.postln; y; zコレクションの要素に頭からアクセスできます。</pre><pre class="code" data-lang="" data-unlink>( var a,b,c,z; z = [1, 2, 3]; //これが基本記述。直感的に理解できますね。 //a = z.at(0); b = z.at(1); c = z.at(2); //見ての通り、かなり短く書けます。でも、この書き方されると解読不可です。 #a, b, c = z; a.postln;b.postln;c; )</pre> </div> <div class="section"> <h5>Environmentの変数</h5> <p> Environmentクラスなんざ知らん!で構わないと思いますが、ちょい解説をしておきます。<br /> Environmentの変数に代入</p> <pre class="code" data-lang="" data-unlink> //envirSetじゃなくて、Putね。 &#39;globalValue&#39;.envirPut(100); //おなじみの〜と同じこと ~globalValue1 = 100; ~globalValue2 = 200;</pre><p>Environmentの変数を参照</p> <pre class="code" data-lang="" data-unlink> //シンボルにenvirGetメッセージを送る &#39;globalValue&#39;.envirGet; //~変数名での参照と同じこと ~globalValue1; ~globalValue2; currentEnvironment topEnvironment</pre><p>envirPutとかcurrentEnvironmentとかなんのこっちゃですが、どうやら”~”と関係があるようです。では、Environmentのヘルプを見てみましょう。IdentifyDictionaryを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A1%BC%A5%D1%A1%BC%A5%AF%A5%E9%A5%B9">スーパークラス</a>として、どっからでもアクセス可能にしたよ!的なことが書いてあります。よくわかりませんが、どうやらSCを立ち上げると、topEnvironment変数、currentEnvironment変数をもったEnvironment<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>が作成されるっぽいです。topEnvironmentは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%BF%A5%D7%A5%EA%A5%BF">インタプリタ</a>値(?)a,b,c...と同様などっからでもアクセスできるコレクションです。SCの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>はcurrentEnvironmentのショートカット記述として"~"をもってます。と書いてあります。</p> <pre class="code" data-lang="" data-unlink> //これらは同じ ~myvariable = 888; currentEnvironment.put(&#39;myvariable&#39;, 888); //ということは上で出てきたこれも同じ? &#39;myvariable&#39;.envirPut(888); //こっちも同じ ~myvariable; currentEnvironment.at(&#39;myvariable&#39;); //こいつも同じ? \myvariable.envirGet;</pre><p>envirGet,envirPutはどちらもsymbolクラスのメソッドです。symbol.scをみると、</p> <pre class="code" data-lang="" data-unlink> envirGet { _Symbol_envirGet ^currentEnvironment.at(this) }</pre><p>となってます。currentEnvironmentの値を参照していますね。envirPutメソッドの方も</p> <pre class="code" data-lang="" data-unlink> envirPut { arg aValue; _Symbol_envirPut currentEnvironment.put(this, aValue); ^aValue }</pre><p>currentEnvironmentのインデックスを指定して引数を渡していることがわかります。Syntax-Shortcutsでは、currentEnvironmentを省いているため、なにやっているのか不明ですが、実際はEnvironment<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>のcurrentEnvironmentに値を代入したり、参照したりしているだけです。なるほど、今まで~で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B0%A5%ED%A1%BC%A5%D0%A5%EB%CA%D1%BF%F4">グローバル変数</a>だ!とか思っていたのは、実はEnvironmentオブジェクトの変数だったわけですね。ま、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B0%A5%ED%A1%BC%A5%D0%A5%EB%CA%D1%BF%F4">グローバル変数</a>ですけど。</p><p>(おまけ) IdentifyDictionary:<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CF%A2%C1%DB%C7%DB%CE%F3">連想配列</a>のこと。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CF%A2%C1%DB%C7%DB%CE%F3">連想配列</a>とは、int型以外の型を要素のインデックスとして扱える配列のことで、辞書とも言われます。普通の配列では、a.at(1)とかインデックスはint型ですが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CF%A2%C1%DB%C7%DB%CE%F3">連想配列</a>ですと、a.at('index')といった具合にインデックスをシンボルにすることができます。ちょっと例を</p> <pre class="code" data-lang="" data-unlink> a = (); a.put(0,10); //0番目の要素に10を代入 a.put(&#39;index&#39;, 100); //’index’の要素に100を代入 a.put(&#34;test&#34;, 1000); a.at(0); //インデックスとして、&#39;シンボル&#39;はおk、&#34;文字列&#34;は駄目? a.at(&#39;index&#39;); a.at(&#34;test&#34;);</pre><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%CF%A2%C1%DB%C7%DB%CE%F3">連想配列</a>は分かったでしょうか?Environmentクラスは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CF%A2%C1%DB%C7%DB%CE%F3">連想配列</a>のサブクラスという位置づけですので、インデックスにシンボルを用いることが可能です。つまり、'a'というシンボルに100という値を代入することができます。かつ、'a'というインデックスには、どこからでもアクセスすることができます。</p> <pre class="code" data-lang="" data-unlink> //再度下記を実行してみてください currentEnvironment; //見事に連想配列ですね!しかもどこからでも、アクセスできる連想配列ですよ!</pre> </div> <div class="section"> <h5><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>作成</h5> <p> これは使いますね。</p> <pre class="code" data-lang="" data-unlink> //クラスからインスタンスを作成するときは、newメソッド Point.new(1, 2); //newメソッドは省略可能 Point(1, 2); //引数はnullでもおk a = Point(); a.set(1,1);</pre><p>newメソッドはあっても、なくてもどっちでも<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>作成できます。<br /> </p> </div> <div class="section"> <h5>コレクションの要素に代入かつ作成</h5> <p> これもよく使います。ヘルプではSetになってますが、Setは順番関係なしになるので、Arrayの方が分かりやすいかと。</p> <pre class="code" data-lang="" data-unlink> //newメソッドで定義してからaddメソッドで要素に代入しています。 Array.new.add(1).add(2).add(3); //newメソッドもすっとばして、いきなり要素に代入。 Array[1, 2, 3]; //インスタンス作成のショートカットをつかって書くとこう。特に意味はないですけれど。 Array().add(1).add(2).add(3);</pre> </div> <div class="section"> <h5>引数のブロックなくしてもいけるよ!</h5> <p> <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BB%A5%EC%A5%AF%A5%BF">セレクタ</a>の後に続く引数は()で括る必要がないということでしょうか。意味不明。誰得。</p> <pre class="code" data-lang="" data-unlink> //通常の関数形式記述 x=1; if ( x&lt;3, {&#39;abc&#39;}, {&#39;def&#39;} ); //()を省略してもおkらしい x=1; if (x&lt;3) {&#39;abc&#39;} {&#39;def&#39;}; //通常のレシーバ形式 x=1; (x&lt;3).if( {&#39;abc&#39;},{&#39;def&#39;}); //こちらも()省略できます x=1; (x&lt;3).if {&#39;abc&#39;} {&#39;def&#39;}; //helpより z=2; z.do({arg x; x.postln }); z=2; z.do { arg x; x.postln } //shortcut a=1; while( { a&lt;200 }, { a = a*2; a.postln } ); a=1; while { a&lt;200 } { a = a*2; a.postln }; //shortcut</pre><p>なんでしょうかね、この記述方法は。<a class="keyword" href="http://d.hatena.ne.jp/keyword/smalltalk">smalltalk</a>あたりにあるのでしょうか?</p> </div> <div class="section"> <h5>引数をより短く</h5> <p> 通常はargで定義しますが、||で囲んでもおkです。このとき、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BB%A5%DF">セミ</a>コロン;はいらないので付けないようにしましょう。人によっては、これ一択ですね。</p> <pre class="code" data-lang="" data-unlink> //通常は、argで引数を定義(仮引数ね) { arg x; x=2 }.value; //argの代わりに||で囲ってもおk。このとき;はつけないように注意 { |x| x=2 }.value; //もちろん初期値の代入も可能です { |x=2| x }.value; f = { |x, y| x.postln;y.postln }; f.value(1,2); f.value(x:3,y:4);</pre><p>使う人が多いので、覚えておきましょう。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ruby">Ruby</a>でもこの記述方法はあります。</p> </div> <div class="section"> <h5><a class="keyword" href="http://d.hatena.ne.jp/keyword/value">value</a>メソッドの略</h5> <p> 関数から引数に代入する<a class="keyword" href="http://d.hatena.ne.jp/keyword/value">value</a>メソッドは略せます。</p> <pre class="code" data-lang="" data-unlink> a = { arg x; var y=10; x+y}; //基本的な引数への値の渡し方 a.value(1); //valueメソッドは省略可能 a.(1);</pre><p>これは知っておかないと、え?となりますね。</p> </div> <div class="section"> <h5>シンボルの記述</h5> <p> どっちがショートカットか知りませんが、一文字短く書けます。</p> <pre class="code" data-lang="" data-unlink> &#39;symbol&#39; \symbol</pre><p>色付けると付属エディタのデフォルト値は'緑'になりますので、ぱっと見で分かると言えばわかります。</p> </div> <div class="section"> <h5>Ref</h5> <p> よくわからないのでパス。ショートカットは" ` "バッククォートです</p> </div> <div class="section"> <h5>コレクション、配列のインデックス</h5> <p> これも基本より使われています、どちらも書けた方が良いかと。</p> <pre class="code" data-lang="" data-unlink> a = Array[10, 20, 30]; //インデックス指定はatメソッド a.at(0); //[]でインデックス指定できます a[0];</pre><p>コレクション<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>作成のショートカットとごっちゃにならないように気をつけましょう。</p> </div> <div class="section"> <h5>コレクション、配列の要素へ代入</h5> <p> インデックス指定と同じです。</p> <pre class="code" data-lang="" data-unlink> a = Array[10, 20, 30]; //インデックスで要素指定して、値を代入するにはputメソッド a.put(0, 100); //[]でインデックス指定して、そこの要素に代入 a[0] = 200;</pre> </div> <div class="section"> <h5><a class="keyword" href="http://d.hatena.ne.jp/keyword/%CF%A2%C1%DB%C7%DB%CE%F3">連想配列</a>、辞書作成</h5> <p> <a class="keyword" href="http://d.hatena.ne.jp/keyword/%CF%A2%C1%DB%C7%DB%CE%F3">連想配列</a>は、インデックスを数値じゃなくて、文字とかで定義できる配列のことです。SCで<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CF%A2%C1%DB%C7%DB%CE%F3">連想配列</a>を多様する方がどのくらいいるか不明ですが。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ruby">Ruby</a>のハッシュ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%C6%A5%E9%A5%EB">リテラル</a>と同じですよ。</p> <pre class="code" data-lang="" data-unlink> //省略を使わないで連想配列を作成 z = IdentityDictionary.new.add(\a-&gt;1).add(\b-&gt;2); //newメソッドなどは省略可能 z = IdentityDictionary[ \a-&gt;1, \b-&gt;2 ]; z.at(\a).postln; z[\b]; //結果 //index: 値で連想配列を作成できます z = (a: 10, b: 20); z.at(\a).postln; z[\b]; //結果</pre><p>使うひとはいちいちIdentityDeictionaryなんて書かないでしょうから、下の記述法は知っておいた方が良いかと。</p> </div> <div class="section"> <h5>等差階級配列</h5> <p> こちらも<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ruby">Ruby</a>ライクです。*.seriesメソッドはArrayCollectionクラスのメソッドで、引数は( size, start, step )となってます。下の書き方のseriesはSimpleNumberクラスのメソッドで、引数は( this, second, last )になっていて、stepはnext-thisで算出されます。seriesメソッドでも引数が異なるので注意しましょう。ショートカット記述は一番下です。大分シンプルになりますね。</p> <pre class="code" data-lang="" data-unlink> //ArrayCollectionのseriesメソッドを使う Array.series( 10, 1, 1 ); //SimpleNumberのseriesメソッドを使う series( 1, nil, 10 ); //省略形 ( 1 .. 10 ); //ArrayCollectionのseriesメソッドを使う Array.series( 10, 1, 3 ); //SimpleNumberのseriesメソッドを使う series( 1, 4, 28 ); //省略形 ( 1, 4 .. 28 ); </pre> </div> <div class="section"> <h5>配列のコピー</h5> <p> 配列のインデックスを範囲で指定して別配列にコピーします。</p> <pre class="code" data-lang="" data-unlink> a = Array.new.add(1).add(2).add(3).add(4); a = [1,2,3,4]; //配列aのインデックス0から2まで配列bにコピーします b = a.copyRange( 0, 2 ); //配列のインデックス0から2までをbに代入 b = a[ 0 .. 2 ]; //配列aのインデックス2から最後まで配列bにコピーします b = a.copyToEnd(2); //省略形 b = a[ 2 .. ]; //配列aのインデックス0から2まで配列bにコピーします。 b = a.copyFromStart(2); //省略形 b = a[ .. 2 ];</pre><p>別にコピーメソッドは知らなくて良いと思います。参考までに、ArrayクラスのcopyRangeメソッドは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A1%BC%A5%D1%A1%BC%A5%AF%A5%E9%A5%B9">スーパークラス</a>のSequenceableCollectionクラスのメソッドを継承しています。そのまま継承しています。SequenceableCollection.scみるとcopyToEnd,copyFromStartはcopyRangeを使用して実装していますね。</p> </div> <div class="section"> <h5>performList呼び出し</h5> <p> performListってなに?</p> <pre class="code" data-lang="" data-unlink> //performListメソッドというものがあるらしい a.performList(\postln); //これと同じこと? a.postln;</pre><p>Object.scには以下と定義されていますね。</p> <pre class="code" data-lang="" data-unlink> performList { arg selector, arglist; _ObjectPerformList; ^this.primitiveFailed }</pre><p>メソッドを呼び出すメソッドってことかな?</p> </div> <div class="section"> <h5>partial application(部分適用)</h5> <p> もう、いやだ。リンク張ってごまかす。<br /> <a href="http://supercollider.jp/modules/bwiki/index.php?Partial-Application">http://supercollider.jp/modules/bwiki/index.php?Partial-Application</a><br /> </p> </div> </div> <div class="section"> <h4>以上</h4> <p>結局こうも書けるよ程度にしかならないですね。さらに、下に行くほどだれてます。SCが多様な構文を許可している理由は不明ですが、推測するに、他の言語に合わせたよ!取っ付きやすいでしょ!じゃないでしょうか。逆効果で、混乱する人が多数発生しましたけど。</p><p>次は基礎文法を修正したいと思います。そのあと、前回の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%D6%A5%B8%A5%A7%A5%AF%A5%C8%BB%D8%B8%FE">オブジェクト指向</a>を修正する予定です。最後にこの文を修正します。</p> </div> sc3onlinux SuperColliderショートカットマスターへの道 - オブジェクト指向から始めよう - hatenablog://entry/17680117127138690309 2010-09-25T01:07:08+09:00 2019-05-17T20:20:34+09:00 *全然見返していないため、プレとして出します。徐々に修正追記していきます。 TKSC#2(打ち上げの飲み)から帰ってきて、そうだ、ショートカットについてまとめようと思い、ちまちま調べたり、書いたりしていましたが、Smalltalk流のオブジェクト指向から始めないと、SCの文法、ショートカット記述を理解することは難しいということが分かりました。なあなあでコードを書いていても一応動くので、始めは良いのですが、そのうち詰まる部分がでてきます。なんでこの記述でいいんだろう?とかですね。本文を書いている最中で、私がかなり誤解していることも発覚し、当ブログでもかなりの嘘を書いてきました。すみません。それは… <p> *全然見返していないため、プレとして出します。徐々に修正追記していきます。</p><p> TKSC#2(打ち上げの飲み)から帰ってきて、そうだ、ショートカットについてまとめようと思い、ちまちま調べたり、書いたりしていましたが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Smalltalk">Smalltalk</a>流の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%D6%A5%B8%A5%A7%A5%AF%A5%C8%BB%D8%B8%FE">オブジェクト指向</a>から始めないと、SCの文法、ショートカット記述を理解することは難しいということが分かりました。なあなあでコードを書いていても一応動くので、始めは良いのですが、そのうち詰まる部分がでてきます。なんでこの記述でいいんだろう?とかですね。本文を書いている最中で、私がかなり誤解していることも発覚し、当ブログでもかなりの嘘を書いてきました。すみません。それは、棚に上げておいて、<br /> <br /> あなたは、</p> <pre class="code" data-lang="" data-unlink>SinOsc.ar( 440, 0, 1 ) ar ( SinOsc, 440, 0, 1 )</pre><p> の引数がそれぞれ何か説明できるか!?(<a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a>で嘘ついてました、ほんとすみません。)</p><p> というわけで、ショートカットへの道として、SCにおける<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%D6%A5%B8%A5%A7%A5%AF%A5%C8%BB%D8%B8%FE">オブジェクト指向</a>の解説を適当にまとめてみました。変数、引数、関数に加え、なんとなくでもおkなので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%D6%A5%B8%A5%A7%A5%AF%A5%C8%BB%D8%B8%FE">オブジェクト指向</a>、クラス、関数を知っているとすんなり理解できると思いますよ。私は、なあなあでしか分かっていませんでした。ですから、本文もかなり間違いがあるかもしれません。指摘していただければ幸いです。</p><p>じゃあ、いくよ!</p> <div class="section"> <h4>1. SCにおける<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%D6%A5%B8%A5%A7%A5%AF%A5%C8%BB%D8%B8%FE">オブジェクト指向</a> - object oriented -</h4> <p> <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%D6%A5%B8%A5%A7%A5%AF%A5%C8%BB%D8%B8%FE%B8%C0%B8%EC">オブジェクト指向言語</a>には大まかに2種類あり、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Smalltalk">Smalltalk</a>流と<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%2B%2B">C++</a>流です。SCは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Smalltalk">Smalltalk</a>の流れを汲んでいます。そのため、<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%2B%2B">C++</a>に慣れている方にとっては非常に取っ付きにくいです。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%D6%A5%B8%A5%A7%A5%AF%A5%C8%BB%D8%B8%FE">オブジェクト指向</a>に関しては、webサイトで勉強しても良いのですが、どちらの概念に基づいているかということが明記されていないことが多く、混乱の原因になります。SCにおける<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%D6%A5%B8%A5%A7%A5%AF%A5%C8%BB%D8%B8%FE%B8%C0%B8%EC">オブジェクト指向言語</a>を理解するならば、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Smalltalk">Smalltalk</a>の流れを汲んだ言語の基礎本読むのが一番手っ取り早いです。ただし、今更<a class="keyword" href="http://d.hatena.ne.jp/keyword/Smalltalk">Smalltalk</a>をやっても仕方がなさそうですから、SCに近い<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ruby">Ruby</a>をお勧めします。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ruby">Ruby</a>には日本語の本が多いですしね。もちろん、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Smalltalk">Smalltalk</a>、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ruby">Ruby</a>関係の入門サイトでもちゃんと説明は書いてありますよ。また、<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%2B%2B">C++</a>、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Java">Java</a>での<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%D6%A5%B8%A5%A7%A5%AF%A5%C8%BB%D8%B8%FE">オブジェクト指向</a>をマスターしている方は、一旦概念を横に置いておかないと、何がなんやら分からなくなり、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Smalltalk">Smalltalk</a>死ね!SC死ね!<a class="keyword" href="http://d.hatena.ne.jp/keyword/max/msp">max/msp</a>最強!!とかなりますので、ご注意を。別にmax最強でも良いんですけどね。<br /> ex) SinOsc.arは<br /> <a class="keyword" href="http://d.hatena.ne.jp/keyword/smalltalk">smalltalk</a>概念で読むと、SinOscオブジェクトにarメッセージを送る。<br /> <a class="keyword" href="http://d.hatena.ne.jp/keyword/C%2B%2B">C++</a>概念で読むと、SinOscクラスのar<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E1%A5%F3%A5%D0%B4%D8%BF%F4">メンバ関数</a>を呼び出す。<br /> のように読めます。処理結果は同じですが、ニュアンスは全然違います。</p> <div class="section"> <h5>1.1 オブジェクト object</h5> <p> オブジェクトとは、様々な属性値(周波数、振幅など)、振る舞い(大きい値を返す、別のものを加えるなど)を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CA%DD%CD%AD">保有</a>している”部品”を指します。(オブジェクトは部品、モノというニュアンスよりも目的というニュアンスの方がわかりやすいのかな?目的にメッセージを送って制御する、とか)属性値は、プロパティ(パラメータ)。振る舞いは、メソッドといいます。<br /> <a class="keyword" href="http://d.hatena.ne.jp/keyword/SuperCollider">SuperCollider</a>では、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Smalltalk">Smalltalk</a>ライクな<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%D6%A5%B8%A5%A7%A5%AF%A5%C8%BB%D8%B8%FE%B8%C0%B8%EC">オブジェクト指向言語</a>であり、全てのもの(単なる数値含め)がオブジェクトであるという位置づけとなっています。例えば、変数xを定義していた場合、xはオブジェクトとして扱われます。10という数値もオブジェクトであり、プロパティとメソッドを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CA%DD%CD%AD">保有</a>していることになります。<br /> SCでは、クラスとしてObjectクラスをもっています。Objectクラスは全てのクラスの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A1%BC%A5%D1%A1%BC%A5%AF%A5%E9%A5%B9">スーパークラス</a>であり、もっとも基本的なメソッドはObjectクラスから継承し、他のクラスでも使用できます。また、数値を含めてオブジェクトですから、数値もオブジェクトがもっているメソッドを実行することができます。(どのデータ型もObjectクラスを継承しているため、Objectクラスがもっているメソッドを実行可能、ということでただしいのかな?継承というか共有?)</p> </div> <div class="section"> <h5>1.2 処理</h5> </div> <div class="section"> <h5>1.2.1 メソッド method</h5> <p> メソッドとは、オブジェクトがもっている処理(振る舞い)のことで、postウィンドウに結果を出力する(これはpostメソッド)、というような処理のことを指します。では、オブジェクトがもっているメソッドの実行方法(呼び出し方法)です。記述方法は、次のようになります。</p> <pre class="code" data-lang="" data-unlink> レシーバ.メッセージ //レシーバがメッセージを受け取る //オブジェクト.メソッド C++ライクでは、オブジェクトのメソッド(メンバ関数)を呼び出す</pre><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/smalltalk">smalltalk</a>の流れを汲んだ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%D6%A5%B8%A5%A7%A5%AF%A5%C8%BB%D8%B8%FE%B8%C0%B8%EC">オブジェクト指向言語</a>では、メソッドの呼び出しを"レシーバにメッセージを送る"ことで実現します。この記述は、メッセージ式と呼ばれています。レシーバとは、メッセージを受け取るオブジェクトのことです。ここで混乱する箇所としては、メッセージ?メソッド?同じっすか?、かな。メッセージ式の記述では、メッセージとメソッドは別物です。メソッドは上記の通り、オブジェクトが保持している処理のことです。メッセージとは、レシーバ(オブジェクト)のメソッドを呼び出す処理のことです。メッセージには、呼び出したいメソッドの名前を示す”<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BB%A5%EC%A5%AF%A5%BF">セレクタ</a>”と<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BB%A5%EC%A5%AF%A5%BF">セレクタ</a>に渡す引数に分けられます。<br /> ”レシーバ.メッセージ”は、”レシーバ.メソッド名(引数)” or ”レシーバ.<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BB%A5%EC%A5%AF%A5%BF">セレクタ</a>(引数)”と読み替えることができ、レシーバはメッセージから、実行すべきメソッドとそれに渡す引数を受け取り、自身のメソッドを実行する。という解釈まで落とし込めます。<br /> <a class="keyword" href="http://d.hatena.ne.jp/keyword/C%2B%2B">C++</a>に慣れているとメッセージと、メソッドを同じに捉えてしまいますが、違いますよ。強引に、メソッド?ああ、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E1%A5%F3%A5%D0%B4%D8%BF%F4">メンバ関数</a>ね、とか進めていくとSCのショートカット記述で詰まる気がします。</p> </div> <div class="section"> <h5>1.2.2 メッセージ message</h5> <p> メソッド項目で書いちゃってます!オブジェクトにメソッドを実行させるための、命令のことです。</p> </div> <div class="section"> <h5>1.3 クラスと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a> class & instance</h5> <p> 前項でのオブジェクトとメソッドの基礎はよろしいでしょうか。"レシーバ.メッセージ"ですよ!前項まででクラス、クラス、おい、クラスってなんだよ?と。クラスとは、構造を定義し、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>としてオブジェクト郡の実装をするものです。要はクラスをもとに、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>と呼ばれるオブジェクトを作成します。ここでの作成とはメモリに割り当てられることを示します。<br /> クラスには継承という概念があり、親クラスが<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CA%DD%CD%AD">保有</a>しているメソッドは子クラスに継承されます。親クラスをスーバークラス。子クラスをサブクラスと呼びます。あるクラスが<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CA%DD%CD%AD">保有</a>しているメソッド、さらに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A1%BC%A5%D1%A1%BC%A5%AF%A5%E9%A5%B9">スーパークラス</a>から継承しているメソッドを確認したい場合は、クラスオブジェクトにdumpAllMethodsメッセージを送ります。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>とオブジェクトはごっちゃになりやすいです。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>=オブジェクト だ。とか書いてるサイトもありますが、違います。クラスについては、こんなもんで。(memo:要追記、修正部分)<br /> クラスの書き方とかやらねーの?と言われそうですが、理解出来ていない部分があるため、すっとばします。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>の作成は次章で。<br /> </p> </div> <div class="section"> <h5>1.4 SCでのオブジェクト、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>の使用方法</h5> <p> 前項までで、オブジェクトやクラスの概念は理解してもらえたでしょうか?え、無理?すみません。</p> </div> <div class="section"> <h5>1.4.1 基本</h5> <p> クラスという設計書から<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>という色々いじくり倒せるオブジェクトを作成します。SinOscクラスの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>を作成するには</p> <pre class="code" data-lang="" data-unlink> //SinOscクラスオブジェクトにnewメッセージを送り。SinOscクラスのnewメソッドを実行させる。ここでnewメソッドは省略できるけれど、それはまた別のお話。 a = SinOsc.new(); //確認。aはSinOscクラスから作成されてますね。classメソッドはObjectクラスのメソッドで、_ObjectClassというプリミティブメソッドを呼び出している。プリミティブメソッドとは、大元のC++で実装されている処理のこと。 a.class; </pre><p>これでaというSinOscクラスの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>が作成されました、当然、aはオブジェクトです。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A1%BC%A5%D1%A1%BC%A5%AF%A5%E9%A5%B9">スーパークラス</a>である、Ugenのメソッドも継承しているのでメッセージで呼び出して使用可能です。</p> <pre class="code" data-lang="" data-unlink> //SinOscクラスのスーパークラスはUGenクラスです SinOsc.superclass.postln; //UGenのメソッドも呼び出せる a.init; a.copy; a.madd; //UGenのスーパークラスはAbstractFunctionですね UGen.superclass.postln; //AbstractFunctionのメソッドも呼び出せる a.neg; a.reciprocal; </pre><p>ここで、クラスブラウザやOsc.scをみて、arメソッドもあるじゃん!とかいって</p> <pre class="code" data-lang="" data-unlink> //arメッセージをaオブジェクトに送り、arメソッドを実行させたい a.ar();</pre><p>とかやっても無駄です。SinOscクラスのarメソッドをみると、頭に*がくっついています。これは、クラスメソッドを意味します。(ここらへんよくわかっていないのですが)クラスメソッドとは、クラスに直接属しているメソッドでコンスト<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E9%A5%AF">ラク</a>タ的な意味をもち、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>では実行できません。*がついていないメソッドは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>メソッドであり<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>で実行可能です。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>メソッドは、実体をもっていないクラスからは実行できません。</p> <pre class="code" data-lang="" data-unlink> b = LFPulse(); //arはクラスメソッド LFPulse.ar(); b.ar(440); //signalRangeはインスタンスメソッド b.signalRange; LFPulse.signalRange;</pre><p>実行できないものは、ポストウィンドウにエラーが返ってきますが、これらは間違いというわけではありません。bというオブジェクトにarメソッドを実行しろ、というメッセージを送っているだけですからね。例えば、2行目実行後のポストウィンドウのエラーメッセージを見てください。ERROR: Message 'ar' not understood.とあるかと。arメソッドを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CA%DD%CD%AD">保有</a>していないので、そんなメッセージ理解できねーよ。と文句言っているわけですね。その下に、レシーバはLFPulseの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>だよ、ごにょごにょ。引数はIntの440。さらに下の方にselectorはarだよ。とかありますね。エラーメッセージは、基礎文法を理解していると、読めるようになります!(私は、これを書いている最中に初めてちょっと読めましたw)<br /> </p> </div> <div class="section"> <h5>1.4.2 謎の記述方法</h5> <p> もうちょいメッセージ使ったメソッドの呼び出しをみてみましょうか。Arrayクラスにpostlnメソッドは定義されていませんが、Array.new.add(1).postln; はpostlnメソッドがちゃんと実行されます。変数x、数値も同様で 2.postln; x.postln; もpostlnメソッドが実行可能です。全ての<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A1%BC%A5%D1%A1%BC%A5%AF%A5%E9%A5%B9">スーパークラス</a>であるObjectクラスのメソッドを継承しているからですね。というようなことを前項まででやってきました。もちろん単なる数値もObjectクラスのメソッドで呼び出し可能です。<br /> 次の2行を見て下さい。</p> <pre class="code" data-lang="" data-unlink> //レシーバ.メッセージ のメッセージ式 2.do( { arg x; x.postln; }); //? do(2, {arg x; x.postln; }); </pre><p>どちらも2回繰り返す処理を行います。上のdo(引数)というメッセージは、2というIntegerクラスのdoメソッドを実行させます。Integer.scには下のように定義されています。</p> <pre class="code" data-lang="" data-unlink> do { arg function; // iterates function from 0 to this-1 // special byte codes inserted by compiler for this method var i = 0; while ({ i &lt; this }, { function.value(i, i); i = i + 1; }); }</pre><p>どうやら、doメソッドの引数は関数をくれくれ、らしいので、{ }で囲ったものをdo<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BB%A5%EC%A5%AF%A5%BF">セレクタ</a>後方の引数( )内に{ }で関数を記述しています。一方、下の記述方法は何かというと、どうやらメッセージ式においてレシーバを省略すると、メッセージ内の第1引数がレシーバと認識されるようです。以下を実行して、エラーを確認してみましょう。エラーメッセージ読めると非常に捗ります。</p> <pre class="code" data-lang="" data-unlink> 1.ar(440, 0, 1); ar(1,440, 0, 1);</pre><p>上は、メッセージarがわかんね。と返され、レシーバはInt 1と解釈されていますね。下も実行してみましょう。なんと!同じエラーが返ってきました。ここで注目すべき箇所は、上下どちらもdoesNotUnderstandの引数が*3と解釈されている部分でしょう。ar( )の引数は4つではなく、3つだそうですよ。やはり、レシーバを省略したときはメッセージの第1引数がレシーバと解釈されるようです。うーむ。<br /> </p> </div> <div class="section"> <h5>1.4.3 関係ない話(情報求む)</h5> <p> バイナリオペレータのメソッドが意味不明、よくわからないんだけれど。Intクラスにはmaxメソッドなどの定義はないので1個上のSimpleNumberクラスをみてみると、</p> <pre class="code" data-lang="" data-unlink> max { arg aNumber=0.0, adverb; _Max; ^aNumber.performBinaryOpOnSimpleNumber(&#39;max&#39;, this, adverb) }</pre><p>などとある。thisはperformBinaryOpOnSimpleNumberメソッドに渡されるらしい。^はリターンだ。</p> <pre class="code" data-lang="" data-unlink> 1.max(10); //結果は10 -1.max(); //引数を省略すると結果は0、これはaNumberの初期値が0だからだと理解できる。 max(1, 10); //結果は10 max(-1); //結果は0、結果にaNumberの初期値が返ってきている。</pre><p>thisがないため、レシーバの値は_Maxに直接渡されているのだろうか?</p> <pre class="code" data-lang="" data-unlink>1.performBinaryOpOnSimpleNumber(\max, this, 10);</pre><p> これの結果はMath operation failed.と返ってくる。performBinaryOpOnSimpleNumberメソッドの定義を見てみると以下だ。</p> <pre class="code" data-lang="" data-unlink> performBinaryOpOnSimpleNumber { arg aSelector, aNumber; ^error(&#34;Math operation failed.\n&#34;) }</pre><p>aSelector,aNumberがなんだろうと、このエラーを返すらしい。ということは、_Maxのプリミティブメソッドでおkなら、perform-メソッドは実行されていないことがわかる。_Maxはどんな処理をしているのかが、どうやら鍵らしい。PryPrimitive.cppをみてみるとdefinePrimitive関数でopMax、と_Maxをひもづけているんだろう。opMaxを検索してみる、SetRawとかsc_maxがよくわからない。むり。たぶん、レシーバの値と第1引数の値だけプリミティブメソッドに渡され、ごにょごにょして返ってくるのだろう。第2引数のadverbは謎。(helpのadverbsにごちゃごちゃ書いてありますね。そのうち読んでみます!)</p> </div> <div class="section"> <h5>1.5 まとめ</h5> <pre class="code" data-lang="" data-unlink> SinOsc.ar( 440, 0, 1 );</pre><p> ふふん、SinOscクラスオブジェクトにメッセージとして、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BB%A5%EC%A5%AF%A5%BF">セレクタ</a>ar、引数440,0,1送っているのさ。arメソッドはクラスメソッドだから、SinOscクラスオブジェクトから実行可能なんだぜ!</p> <pre class="code" data-lang="" data-unlink> ar( SinOsc, 440, 0, 1 );</pre><p> しっ、見ちゃだめです!(えっ?</p><p> 以上で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%D6%A5%B8%A5%A7%A5%AF%A5%C8%BB%D8%B8%FE">オブジェクト指向</a>を終わります。ちょっとは理解深まりましたか?<br /> ・SCでは、全てがオブジェクト。<br /> ・<a class="keyword" href="http://d.hatena.ne.jp/keyword/Smalltalk">Smalltalk</a>流の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%D6%A5%B8%A5%A7%A5%AF%A5%C8%BB%D8%B8%FE">オブジェクト指向</a>。<br /> ・エラーメッセージを読み解くことで、理解できることもある。<br /> ・やっぱり謎<br /> 用語<br /> オブジェクト:プロパティ、メソッドを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CA%DD%CD%AD">保有</a>した部品のこと<br /> クラス:構造を定義し、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>として実体化される設計書のこと<br /> <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>:クラスをもとにメモリ上に領域を確保し、いじれるようにしたオブジェクトのこと<br /> プロパティ:変数によって決められているオブジェクトの値<br /> メソッド:オブジェクトが<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CA%DD%CD%AD">保有</a>している、処理のこと。クラスメソッドと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>メソッドがあります<br /> メッセージ:オブジェクトに命令すること<br /> レシーバ:メッセージで命令されるオブジェクトのこと<br /> メッセージ式:レシーバ.メッセージ と”ドット”でつなげ、レシーバにメッセージを送り、メソッドを実行させる記述方法<br /> </p> </div> </div> <div class="section"> <h4>2. 関数 function</h4> <p> 前章では、オブジェクトについて書きましたので、おまけ的に関数も書いておきます。<br /> </p> <div class="section"> <h5>2.1 関数の記述方法</h5> <p> オペレーション(演算、働き)を定義し、”<a class="keyword" href="http://d.hatena.ne.jp/keyword/value">value</a>”メッセージを受け取ると動作します。関数を定義するには”{}”で括ります。引数の定義は”{”の後、変数の定義は引数の後、変数の後に処理を定義します。要は、<br /> function = { arg 引数; var 変数; 処理 } で定義して<br /> function.<a class="keyword" href="http://d.hatena.ne.jp/keyword/value">value</a>(第1引数、第2引数) と引数に値を渡します。<br /> これが基本ですね。変数、処理の記述は問題ないとして、引数の書き方は色々あるので注意しましょう。</p> <pre class="code" data-lang="" data-unlink> //最も基本的な書き方 var fun; fun = { arg a,b,c; a.postln; b.postln; c }; fun.value(1,2,3); //引数は||ブロックで囲ってもおk。これでも書けるよ!的な書き方 var fun; fun = { | a, b, c | a.postln; b.postln; c }; fun.value(1,2,3); //引数に配列を用いるには ”...” var fun; fun = { arg ... a; a }; fun.value(1,2,3,4,5); var fun; fun = { arg a,b ... c; a.postln; b.postln; c }; fun.value(1,2,3,4,5,6,7);</pre><p> 関数はこんなとこでしょう。<br /> </p> </div> </div> <div class="section"> <h4>3. もうちょい具体的に</h4> <p> 前章までで、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%D6%A5%B8%A5%A7%A5%AF%A5%C8%BB%D8%B8%FE">オブジェクト指向</a>の基本、おまけに関数について記載しました。でも、具体例やらんと身に付かないですよねー。ひとつひとつ、解読していくと理解が深まるんじゃね?しかし、これがまた難しい。<br /> </p> <div class="section"> <h5>3.1 解読</h5> <p> SCらしく、SynthDefでの一般的なシンセ定義を解読してみましょうか。”レシーバ.メッセージ”のルールに従って読んでみます。<br /> tksc#1の4. シーケンスを書いてみる、より</p> <pre class="code" data-lang="" data-unlink> ( SynthDef.new( &#39;melo&#39;, { arg frq = 785, amp = 0.5, atk = 0.005, rel = 0.2; var env, snd; env = EnvGen.kr( Env.perc( atk, rel ), doneAction: 2 ); snd = SinOsc.ar( frq , 0, amp * env ); Out.ar( 0, Pan2.ar ( snd ) ); } ).store; )</pre><p> ちょっと変更していますが、これを分析していきます。まず、一番外から見てみるとSynthDefクラスオブジェクトに送っているメッセージは2つあります。newとstoreです。まず、SynthDefクラスはnewメッセージを受け取りnewメソッドで<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>を作成します。このときSynthDefが受け取る引数は二つで、シンボル'melo'と{}で括られた関数です。では、newメソッドの処理内容を見てみましょうか。SynthDef.scには以下のように記述されています。</p> <pre class="code" data-lang="" data-unlink> *new { arg name, ugenGraphFunc, rates, prependArgs, variants, metadata; ^this.prNew(name).variants_(variants).metadata_(metadata) .build(ugenGraphFunc, rates, prependArgs) }</pre><p>第1引数はname、第2引数はugenGraphFuncですね。^はリターン、thisはレシーバとなります。newメソッドの処理では、まずSynthDefクラスオブジェクトに、nameを引数としてprNewメッセージを送っています、さらにugenGraphFuncはbuildメッセージの第1引数として送っていますね。variants_()とmetadata_()に関してはSynthDefのクラス変数variantsとmetadataに()内の値を代入しています。ここでは空ですね。では、prNewメソッドを見てみましょうか。</p> <pre class="code" data-lang="" data-unlink> *prNew { arg name; ^super.new.name_(name.asString) }</pre><p>ここでは、'melo'を引数nameに代入し、SynthDefの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A1%BC%A5%D1%A1%BC%A5%AF%A5%E9%A5%B9">スーパークラス</a>であるObjectクラスの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>をnewメッセージで作成、'melo'はasStringメッセージを受けシンボルから文字列に変換するasStringメソッドを実行します。文字列として返ってきた"melo"を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A1%BC%A5%D1%A1%BC%A5%AF%A5%E9%A5%B9">スーパークラス</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>の変数nameに代入しています。(変数nameがあやしいなあ、これはSynthDefの変数nameかな)</p> <pre class="code" data-lang="" data-unlink>(参考) SynthDef.superclass &#39;melo&#39;.asString.class</pre><p>buildメソッドはbuildUgenGraphメソッドを呼び、さらにこいつがaddControlsFromArgsOfFuncメソッドを呼んでいます。buildメソッドの処理については、@OsamuTakahashi氏が詳しく解説しています。凄い人だなあ、全然レベルが違う。さて、上のnewメソッドまで戻りますと、prNewで文字列を変数に代入したり、buildでごにょごにょしたSynthDefオブジェクトが返ってくるようです。この返ってきたSynthDefオブジェクトにstoreメッセージを送っています。storeメソッドは.scsyndefという名前でシンセ定義ファイルを作成し、さらにsendメソッドと同じ処理をします。</p><p> 大枠の処理は以上となっています。大雑把ではありますが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%D6%A5%B8%A5%A7%A5%AF%A5%C8%BB%D8%B8%FE">オブジェクト指向</a>の基礎知識があれば多少読めるかと思います。続いて、newメッセージの第2引数である関数の中身を見てみましょう。関数の基本は”{引数; 変数; 処理; }”ですよ。1行目は、引数ですね。基本的な書き方ですね。2行目は変数、これも問題ないと思いますが宣言しておかないと次の行からの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>が格納できません。次の処理にいきます。変数envにはEnvGen<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>を入れます。EnvGenクラスはUGenを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A1%BC%A5%D1%A1%BC%A5%AF%A5%E9%A5%B9">スーパークラス</a>とし、他のUGenクラスを親とするクラスと似たようなクラスです。EnvGen.scを見てみると他のよくわからんクラスもありますが、横に置いておきましょう。arメソッドには、初期値がない引数envelopeとその他もろもろがあります。ここで解読すべきは、envelopeでしょう。まず、arメッセージの引数でEnvGenクラスオブジェクトに何を渡しているのか見てみましょう。Env.<a class="keyword" href="http://d.hatena.ne.jp/keyword/perc">perc</a>( atk, rel )ですね。これはいうまでもなく、Envクラスオブジェクトに<a class="keyword" href="http://d.hatena.ne.jp/keyword/perc">perc</a>メッセージを送っているだけですね。ということは、envelopeにはEnvオブジェクトが入ることになります。arメソッドに戻ります。envelopeはmultiNewListメッセージの引数である配列の最後の要素に使われていますね。なんか”`”が頭についています!バ、バッククォートだと!?どうせショートカット記述だろ、とsyntax-shortcutのヘルプを見てみるとcreating a Refの部分でyou can writeに”`”を見つけました!でも、Refクラスなんて知りませんよ、と。Refヘルプを見てみると a reference to a <a class="keyword" href="http://d.hatena.ne.jp/keyword/value">value</a> とありますがさっぱり意味がわかりません。情報求む。</p> <pre class="code" data-lang="" data-unlink> //オブジェクトを格納するのか? a = Ref(Env.perc( 0.1, 0.2 )) a.dereference a.value a.value_(SinOsc) a.value //おお、SinOscオブジェクトに変わった!だからなんだ!</pre><p>というわけで、終了。ダメでした。</p> </div> </div> <div class="section"> <h4>とりあえず、以上</h4> <p>実は、先にショートカット記述について書いていたのですが、どうしても理解できない部分が多く、もっと基本からやらなくちゃ!と思い、とりあえず<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%D6%A5%B8%A5%A7%A5%AF%A5%C8%BB%D8%B8%FE">オブジェクト指向</a>まで戻ってみたところ、そうだったのか!と気づくことが多く、やべ、誤解していたなあ。という箇所も多々ありました。基本からやり直すことで、結構理解が深まった気がします。<br /> 恒例ですが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/SuperCollider">SuperCollider</a>.jpにhtmlファイルをアップしたいと思います。が、それはまだまだ先のお話になりそうです。ここの修正、追記が終わったらショートカットに移り、それが完了したら、基礎文法の修正にはいります。</p> </div> sc3onlinux SuperColliderでシンセサイズ hatenablog://entry/17680117127138690562 2010-08-20T19:10:34+09:00 2019-05-17T20:20:36+09:00 はじめに SC3を使ってるよ、はじめようと思うよ、などと特殊な方々にとっては、シンセサイズの基礎なんざ極めすぎて困っているんだ!というところでしょうが、SC3用にまとめておきます。max/msp用の解説は多いのですが、パッチ見てもよくわかりませんでした。 加算合成 additive synthesis /* 加算合成とは、その名の通り波形信号を足し合わせて新たな波形信号を作り出す合成方法です。最も基本的な合成方法のひとつで、理論上はサイン波を加算合成することであらゆる波形を生成可能です。sc3上で実現するためには、"+"。要は適当に信号を足せばもう加算合成の出来上がりです。 では、ちょっと足し… <div class="section"> <h4>はじめに</h4> <p>SC3を使ってるよ、はじめようと思うよ、などと特殊な方々にとっては、シンセサイズの基礎なんざ極めすぎて困っているんだ!というところでしょうが、SC3用にまとめておきます。<a class="keyword" href="http://d.hatena.ne.jp/keyword/max/msp">max/msp</a>用の解説は多いのですが、パッチ見てもよくわかりませんでした。</p> </div> <div class="section"> <h4>加算合成 additive synthesis</h4> <p>/*<br /> 加算合成とは、その名の通り波形信号を足し合わせて新たな波形信号を作り出す合成方法です。最も基本的な合成方法のひとつで、理論上はサイン波を加算合成することであらゆる波形を生成可能です。sc3上で実現するためには、"+"。要は適当に信号を足せばもう加算合成の出来上がりです。<br /> では、ちょっと足してみましょう。<br /> */</p> <pre class="code" data-lang="" data-unlink>{ SinOsc.ar(440, 0, 0.8) }.scope; { SinOsc.ar(440,0,0.4) + SinOsc.ar(880,0,0.4) }.scope { SinOsc.ar(440,0,0.3) + SinOsc.ar(880,0,0.3) + SinOsc.ar(220, 0, 0.3) }.scope</pre><p>/*<br /> 1行目は440Hzのサイン波です。2行目は440Hzに880Hzの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C7%DC%B2%BB">倍音</a>を加えています。ちょっとオルガンぽくなりましたね。3行目ではさらにリッチになりました。スペアナのスケールをlogにして確認してみてください。周波数の山が2つ、3つとできています。上記のように基本的に加算合成では、基本周波数の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C7%DC%B2%BB">倍音</a>を加えていきます。</p><p>※信号を"+"するときには加算結果のmul(振幅)が1を超えないようにした方が耳のためになります。<br /> */</p> <pre class="code" data-lang="" data-unlink>{ SinOsc.ar( 440, 0, 0.4 ) + SinOsc.ar( 441, 0, 0.4 ) }.scope { SinOsc.ar( 440, 0, 0.4 ) + WhiteNoise.ar( 0.05) }.scope</pre><p>/*<br /> <a class="keyword" href="http://d.hatena.ne.jp/keyword/%C7%DC%B2%BB">倍音</a>以外の加算ですと別々に音が鳴っているように聴こえたり、もはやエフェクタだな、くらいになってしまいます。</p><p>また、sc3ではちまちま"+"をつかって合成する必要はありません。Mixクラスが用意されています。<br /> */</p> <pre class="code" data-lang="" data-unlink>{ Mix.ar( [ SinOsc.ar(220), SinOsc.ar(440), SinOsc.ar(880) ])*0.4 }.scope { Mix.ar( SinOsc.ar( [220, 440, 880] ) * 0.4) }.scope</pre><p>/*<br /> 上記二つのサンプルは同じ処理です。嫌がらせのようにショートカット記述が多いので自分の書き方を決めておいた方が良いかもしれません。<br /> Mixは複数の配列(チャンネル)を一つに落とし込みます。array.fillで要素を埋めた配列を用意してやると効果的に使えます。<br /> */</p> <pre class="code" data-lang="" data-unlink>( { Mix.ar( Array.fill(1000, { SinOsc.ar(800.rand) } ) //1000個のSinOsc要素を持つ配列を作成し、一つにまとめる )*1/1000 }.scope )</pre><p>/*<br /> 加算合成は最近ではほとんど使われないようです。面倒、マシンパワー喰い過ぎなどなどの理由からですね。加えていく波形に対して、それぞれ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%D9%A5%ED%A1%BC%A5%D7">エンベロープ</a>などを設定したりするため、膨大な作業量となってしまいがちです。加算合成について詳しく知りたい方は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A1%BC%A5%EA%A5%A8">フーリエ</a>合成、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A1%BC%A5%EA%A5%A8%CA%D1%B4%B9">フーリエ変換</a>でググってみて下さい。嫌になりますw<br /> */</p> </div> <div class="section"> <h4>減算合成 subtractive synthesis</h4> <p>/*<br /> アナログシンセの基本合成法です。加算合成とは逆で、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C7%DC%B2%BB">倍音</a>を沢山含んだ信号の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C7%DC%B2%BB">倍音</a>をフィルタで削って、アンプで音量などの調整を行います。ググればいっぱい情報がでてきます。自然の音は、減算合成と同じような方法で生成されています。例えば、弦楽器などでは、まずランダムな励振(excitation)を生成して、自然な共振周波数を持った楽器のボディを通して音をフィルタリング、整形します。人間の声も舌とか口の形で音を加工しているので、減算合成みたいなものです。<br /> SC3でも普通のシンセの音作りと同じでオシレータにフィルタかけて、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%D9%A5%ED%A1%BC%A5%D7">エンベロープ</a>で調整します。<br /> */</p><p>/*<br /> まずはオシレータ。<br /> ヘルプのOscillatorsの項目を見てみて下さい。アナログシンセなどで基本的に使われる波形信号は、<br /> SinOsc :サイン波<br /> Saw :ノコギリ波<br /> Pulse :パルス波<br /> LFTri :<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BB%B0%B3%D1%C7%C8">三角波</a><br /> ですね。他にも色々とありますが、あれもこれもと手をだしていると収集が付かなくなります。スペアナを確認すると、ノコギリ波、パルス波など多くの周波数成分が含まれています。こいつらをフィルタで削ってやるんですよ。<br /> */</p> <pre class="code" data-lang="" data-unlink>//SinOsc.ar(freq, phase, mul, add) { SinOsc.ar(440, 0, 0.8) }.scope //Saw.ar(freq, mul, add) { Saw.ar(440, 0.8) }.scope //Pulse.ar(freq, width, mul, add) { Pulse.ar(440, 0.8) }.scope //LFTri.ar(freq, iphase, mul, add) { LFTri.ar(440, 0, 0.8) }.scope</pre><p>/*<br /> 次にフィルタ。ヘルプのFiltersの項目を見ていただけるとお分かりかと思いますが、鬼のように沢山あります。<br /> 基本は、<br /> RLPF :ローパスフィルタ<br /> RHPF :ハイパスフィルタ<br /> BPF :バンドパスフィルタ<br /> の三つです。これ以外は、このフィルタないすか?とか思ったときに探せば良いと思います。大抵見つかります。LPF、HPFじゃないの?→LPF、HPFではレゾナンスをいじれないため大人しく”R”付きを使いましょう。<br /> ※ローパスとかハイパスとか分かりにくい、という話がCottle氏のPDFにもありますね。まー、ハ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%AB">イカ</a>ットフィルタ、ローカットフィルタとかの方が減算合成として使う分には直感的なんでしょうね。私は”パス”を強調して混乱しないようにしてます。<br /> まずはフィルタを体感してみましょう。マウスのX軸でカットオフ周波数を変化させられます。視覚化するとわかりやすいですね。<br /> */</p> <pre class="code" data-lang="" data-unlink>RLPF.scopeResponse RHPF.scopeResponse BPF.scopeResponse</pre><p>/*<br /> では、引数を説明します。<br /> RLPF.ar( in, freq, q, mul, add )<br /> RHPF.ar( in, freq, q, mul, add )<br /> BPF.ar( in, freq, q, mul, add )<br /> 引数は同じですね。<br /> in : 入力信号。フィルタをかけたい波形、信号を入力します。<br /> freq : カットオフ周波数。この周波数を境目にカットするかパスするか、が決定されます。ただし、カットといっても完全に消すわけではなく、フィルタにもよりますが、ゆるやかに減少させることになります。<br /> q : レゾナンス(または、reciprocal of q : bandwidth/cutoff frequency)。上手く説明できませんが、一般的なアナログシンセでは、カットオフ周波数を強調するのに使われます。みょーん、ってやつですね。バンドパスでは、パスする周波数帯の山の緩やかさを調整できます。(詳しくは、cottle氏のPDFを見て下さい)</p><p>実際に、以下のサンプルを実行してfreqscopeで見てみましょう。マウスのY軸でレゾナンスを調整できます、上にもっていくと周波数の山がとんがることが確認できるかと思います。<br /> */</p> <pre class="code" data-lang="" data-unlink>//cottle氏のPDFより ( { var signal, filter, cutoff, resonance; signal = PinkNoise.ar(mul: 0.7); cutoff = MouseX.kr( 40, 10000, 1 ); resonance = MouseY.kr( 0.01, 2.0 ); BPF.ar( signal, cutoff, resonance) //RLPF,RHPFでもためしてみてください }.scope(1) )</pre><p>/*<br /> 最後に、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%D9%A5%ED%A1%BC%A5%D7">エンベロープ</a>について。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%D9%A5%ED%A1%BC%A5%D7">エンベロープ</a>とは、時間軸で波形を変化させることです。アナログシンセではADSR方式の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%D9%A5%ED%A1%BC%A5%D7">エンベロープ</a>が用いられることがほとんどです。ADSRとは、アタック、ディケイ、サスティン、リリースの頭文字をとったもので、これら4つのパラメータを用います。adsrでググれば<a class="keyword" href="http://d.hatena.ne.jp/keyword/wikipedia">wikipedia</a>が引っかかるのチラ見しておくと良いかと思います。</p><p>SC3での<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%D9%A5%ED%A1%BC%A5%D7">エンベロープ</a>の基本的な作り方は、Envクラスのメソッドで形を選択し、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>(クラスの実体化のこと)を生成します。生成された<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>をenvelope generatorのEnvGenによって、再生可能な形の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%D9%A5%ED%A1%BC%A5%D7">エンベロープ</a>として生成します。(説明が違う気もします)</p><p>ま、とりあえず、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%D9%A5%ED%A1%BC%A5%D7">エンベロープ</a>を見てみましょう。<br /> */</p> <pre class="code" data-lang="" data-unlink>//基本形によるエンベロープ Env.linen.test.plot Env.triangle.test.plot Env.sine.test.plot Env.perc.test.plot //サスティンを持ったエンベロープ Env.adsr.test.plot Env.dadsr.test.plot Env.asr.test.plot Env.cutoff.test.plot</pre><p>/*<br /> SC3ではこんな感じで色々そろっています。(引数なしだとデフォのパラメータ値が割り当てられます)そんな既存のものなんかつかわねー、自分で作るんだ!という方は、.new( levels, times, curves, releaseNode, loopNode )でいかようにも作れます。一からちまちま書いてらんねーよ、な方は、SCEnvelopeView,SCEnvelopeEditを利用すると手っ取り早く書けそうです。使ったことありませんので、help見て下さい。すみません。</p><p>では、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%D9%A5%ED%A1%BC%A5%D7">エンベロープ</a>の形の作り方はおkとして、EnvGenについて。Envクラスで作った<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%D9%A5%ED%A1%BC%A5%D7">エンベロープ</a>を制御するのがEnvGenと考えて下さい。</p><p><span style="font-weight:bold;">EnvGen.ar( envelope, gate, levelScale, levelBias, timeScale, doneAction )</span><br /> envelope : Envで作成した<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>。<br /> gate : この値が0より大きい場合に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%D9%A5%ED%A1%BC%A5%D7">エンベロープ</a>をオン(使用可能)にします。固定長の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%D9%A5%ED%A1%BC%A5%D7">エンベロープ</a>を使った場合には、単にトリガーとして動作します。要は、gateを1にしたタイミングで<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%D9%A5%ED%A1%BC%A5%D7">エンベロープ</a>がオンになり、音がでるようになります。また、サスティンを持った<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%D9%A5%ED%A1%BC%A5%D7">エンベロープ</a>の場合は、gateが0になるまで<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%D9%A5%ED%A1%BC%A5%D7">エンベロープ</a>が終了しません。0になったタイミングから<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%D9%A5%ED%A1%BC%A5%D7">エンベロープ</a>のリリースが始まります。重要なのは、サスティンを持ったadsrなどでgateを0にして解放してやらない限りいつまでも音が鳴り続いてしまう、ということです。必ずどこかのタイミングでgateを0にして解放しましょう。<br /> levelScale : ここらへん使う人っているのかな?割愛<br /> levelBias : 同上<br /> timeScale : 同上<br /> doneAction : <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%D9%A5%ED%A1%BC%A5%D7">エンベロープ</a>が終了した時点、もしくはgateが0になった時点での挙動を指定します。これは使い方が色々あるのですが、とりあえずは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%D9%A5%ED%A1%BC%A5%D7">エンベロープ</a>が終了したらシンセを解放する、2を与えておけば問題ないでしょう。他には、何もしない0、同じグループの前のノードを全て解放する7、全てのシンセを解放する14とかあって、このシンセが終わったら他のシンセも解放したい、という場合に使えそうですが、グループ、ノードを極めてから、調べても遅くないです。</span><br /> EnvGenで作った<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%D9%A5%ED%A1%BC%A5%D7">エンベロープ</a>をどのようにして使うか、ですが信号に*するだけでおkです。<br /> */</p> <pre class="code" data-lang="" data-unlink>{ EnvGen.ar(Env.perc, 1.0, doneAction: 2) * SinOsc.ar }.play //doneActionの挙動が知りたい方は、まず0にして数回実行し、サーバパネルのSynthsが増えていることを確認しましょう。その後、数値を変更して実行してみてサーバパネルのSynthsの値を見てみるとちょっと分かった気になれます。</pre><p>/*<br /> <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%D9%A5%ED%A1%BC%A5%D7">エンベロープ</a>については延々と書けそうですが、ここまで。</p><p>では、どのような感じで減算合成を書いていくか、簡単なサンプルを。<br /> */</p> <pre class="code" data-lang="" data-unlink>( var signal, envelope, filter, out; { //基本の波形を決めsignalとします signal = LFTri.ar; //signal =Mix.ar( LFTri.ar( [220, 440, 880] ) * 0.5); //加算合成するとリッチに //使用するフィルタを決めます。ここで入力に上のsignalを用います filter = RLPF.ar( signal ,440, 0.8); //エンベロープをつくります envelope = EnvGen.ar( Env.linen, 1, doneAction: 2); //他のエンベロープも色々試してみて下さい //最後に、フィルタで加工した波形にエンベロープをかけて完成 out = envelope * filter; //filterをsignalに変えてみて、フィルタを通さない場合も確認 }.scope ) </pre> </div> <div class="section"> <h4>FMシンセ:周波数変調合成 frequency modulation synthesis, AMシンセ:<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%B6%C9%FD%CA%D1%C4%B4">振幅変調</a>合成 amplitude modulation synthesis</h4> <p>/*<br /> FMシンセの特徴は、少ないオシレータ数で沢山の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C7%DC%B2%BB">倍音</a>を含んだ音を合成できるため、マシンの負荷が少なくてすむ、といわれています。FMシンセの原理は簡単で、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E2%A5%B8%A5%E5%A5%EC">モジュレ</a>ータを使用して、キャリアの周波数を変調させる、といったものになります。なんのこっちゃ?<br /> オペレータ: シンセが<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CA%DD%CD%AD">保有</a>する、加工していない基本波形のこと。アナログシンセでのオシレータのこと。一般的には正弦波を用いる<br /> キャリア: 加工される側の波形のこと。オペレータを使用する<br /> <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E2%A5%B8%A5%E5%A5%EC">モジュレ</a>ータ: 加工する側の波形のこと。オペレータを使用する<br /> (この用語は<a class="keyword" href="http://d.hatena.ne.jp/keyword/yamaha">yamaha</a>語です、がもはや一般化していますので把握しておきましょう)<br /> 要は、ある波形を使用して、別の波形の周波数をいじくる、ということです。<br /> これをSC3で表現すると、以下となります。<br /> */</p> <pre class="code" data-lang="" data-unlink>{ SinOsc.ar( 440 + SinOsc.ar (4400, 0, 500, 300), 0, 0.8 ) }.scope</pre><p>/*<br /> <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E2%A5%B8%A5%E5%A5%EC">モジュレ</a>ータの周波数を高くすることで、合成された波形を別の音色としてとらえることができます。スペアナで見てみると、基本周波数の横っちょに複数の山ができていることが確認できます。こんなに簡単に沢山の周波数成分を持たせることができるのです。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E2%A5%B8%A5%E5%A5%EC">モジュレ</a>ータにあたるサイン波の周波数、mul、addを一桁づつ増やしてみるなど、色々変えて試してみて下さい。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E2%A5%B8%A5%E5%A5%EC">モジュレ</a>ータの振幅を1.0にして周波数を低くすると、ビブラートになりますね。基本は以上です。簡単ですね。</p><p>実際のFMシンセの基本形は、次の式で示します。<br /> <span style="font-weight:bold;">y = a * sin( Fc * 2pi + b * sin( Fm * 2pi ) );</span><br /> a: キャリア振幅<br /> b: 変調指数<br /> Fc: キャリア周波数<br /> Fm: <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E2%A5%B8%A5%E5%A5%EC">モジュレ</a>ータ周波数</p><p>実は単純な式でできているんですね。では、これをSC3で示すと次のようになります。<br /> */</p> <pre class="code" data-lang="" data-unlink>( var car, mod; var freq = 440, carAmp = 1.0, modAmp = 500.0, modAdd = 1000; { mod = SinOsc.ar( freq * 100, 0, modAmp, modAdd ); //mod = SinOsc.ar( freq *10 + mod , 0, modAmp, modAdd ); //モジュレータを周波数変調させてみる //mod = SinOsc.ar( freq *10 + mod , 0, modAmp, modAdd ); //もう一回 //mod = SinOsc.ar( freq *10 + mod , 0, modAmp, modAdd ); //まだまだ //mod = SinOsc.ar( freq *10 + mod , 0, modAmp, modAdd ); //さらに car = SinOsc.ar( freq + mod, 0, carAmp ); car }.scope )</pre><p>/*<br /> 大抵の解説では分かりやすくするため、キャリアを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E2%A5%B8%A5%E5%A5%EC">モジュレ</a>ータで一回周波数変調する例がほとんどですが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E2%A5%B8%A5%E5%A5%EC">モジュレ</a>ータのamp(mul)にオペレータを接続してみる、キャリアを別のキャリアに接続などなど、好き放題になんでもくっつけられます。意図した音はだせませんけれども。そうそう、AM合成はFM合成の周波数を振幅に置き換えたものです。(これで伝わりますよね?)RM合成もあります。</p><p>tutorialでは以下のようにFM合成つかってますね。<br /> */</p> <pre class="code" data-lang="" data-unlink>//Introduction tutorial 14. Frequency-Modulationより ( SynthDef(&#34;fm1&#34;, { arg bus = 0, freq = 440, carPartial = 1, modPartial = 1, index = 3, mul = 0.05; // index values usually are between 0 and 24 // carPartial :: modPartial =&gt; car/mod ratio var mod; var car; mod = SinOsc.ar( freq * modPartial, 0, freq * index * LFNoise1.kr(5.reciprocal).abs ); car = SinOsc.ar( (freq * carPartial) + mod, 0, mul ); Out.ar( bus, car ) }).load(s); ) ( Synth(&#34;fm1&#34;, [\bus, 0, \freq, 440, \carPartial, 1, \modPartial, 2.4]); Synth(&#34;fm1&#34;, [\bus, 1, \freq, 442, \carPartial, 1, \modPartial, 2.401]); )</pre> </div> <div class="section"> <h4>位相変調合成 phase modulation synthesis</h4> <p>/*<br /> もうその名の通り位相をいじります。これはPMOscクラスがあるので、こいつ使って下さい。気が向いたら追記します。<br /> */</p> </div> <div class="section"> <h4>以上</h4> <p>/*<br /> 以上、つらつらと書きましたが、sc3ではもう好きなようにオシレータでオシレータのあらゆる部分をいじくり倒せます。ごく簡単に。もちろん、収拾がつかなくなること間違い無しです!こんな感じにね。<br /> */</p> <pre class="code" data-lang="" data-unlink>( SynthDef(&#34;addSynth&#34;, { arg amp, freq=440, gate=1, pan=0, outBus=0, fxBus=10, fx=0.0, vol=1.0; var env, outSend, fxSend, scale, key; var car, mod, filter; var carAmp = 0.6, modAmp = 300.0, modAdd = 400; scale = Scale.major; key = DegreeToKey.kr( scale.as(LocalBuf), Rand(0, 12), scale.stepsPerOctave, 1,36 ).midicps; env = Env.adsr(0.01, 0.05, 0.25, 0.06 ); //シーケンスパートにてgate=0で解放しないと鳴りっぱなし。 mod = SinOsc.ar( freq * 100, modAmp, modAdd ) + SinOsc.ar( freq * 120, modAmp, modAdd ); mod = LFTri.ar( freq *100 + mod , 0, modAmp, modAdd ); //モジュレータを周波数変調させてみる car = SinOsc.ar( key + mod, 0, carAmp + Pulse.ar(4000, 0.15, 0, 0.05) ); filter = RLPF.ar( car, 800, 1.2 ); fxSend = filter * fx; outSend = filter * (1.0 - fx); Out.ar(fxBus, Pan2.ar(EnvGen.ar(env, gate, doneAction: 2) * fxSend, pan) ); Out.ar(outBus, Pan2.ar(EnvGen.ar(env, gate, doneAction: 2) * outSend, pan) ); }).store; ) ( var t, n, addsynth1, addsynth1Loop; ~effectGroup = Group.tail(s); ~synthGroup = Group.tail(s); t = TempoClock(120/60); //120bps addsynth1 = Task({ var pattern; pattern = Pseq([1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0], inf).asStream; loop({ addsynth1Loop = Synth.tail(~synthGroup, &#34;addSynth&#34;, [\amp, pattern.next] ); (t.beatDur).wait; addsynth1Loop.set(\gate, 0); //synthのenvがadsrの時はここらで解放してやります }); }); t.sched(0, { addsynth1.start }); )</pre> </div> <div class="section"> <h4>最後に</h4> <p>例のごとく、htmlファイルを<a class="keyword" href="http://d.hatena.ne.jp/keyword/supercollider">supercollider</a>.jpにアップしておきます。<a href="http://supercollider.jp/modules/bwiki/index.php?Synthsis%A4%CE%B4%F0%C1%C3">&#x3053;&#x3053;&#x306B;&#x30A2;&#x30C3;&#x30D7;&#x3057;&#x307E;&#x3057;&#x305F;</a>。お暇な方、奇特な方がいらっしゃれば追記、修正でブラッシュアップしていただければと思います。</p> </div> sc3onlinux IKEAでCD収納 hatenablog://entry/17680117127138690792 2010-08-17T23:15:08+09:00 2019-05-17T20:20:38+09:00 今更ながら、初めてIKEAに行って収納する棚などを買ってきました。かつ、ちょっとはまったので、IKEAの棚を利用したCD収納、に関してまとめておきます。ググッても引っかからなかったので参考になればと。 選択肢 IKEAで有名な棚といえば、BILLYでしょう。日本の公式サイトで検索すると、オプションも色々と揃っています。http://www.ikea.com/jp/ja/search/?query=billy 幅800mm、高さ2000mmの大きさで6000円から、と激安ですね。 他にも棚は、EXPEDIT、HEMNESなどなど色々とあります。中でもBENNOに関しては、DVDタワー、DVD/ … <p>今更ながら、初めて<a class="keyword" href="http://d.hatena.ne.jp/keyword/IKEA">IKEA</a>に行って収納する棚などを買ってきました。かつ、ちょっとはまったので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/IKEA">IKEA</a>の棚を利用したCD収納、に関してまとめておきます。ググッても引っかからなかったので参考になればと。</p> <div class="section"> <h4>選択肢</h4> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/IKEA">IKEA</a>で有名な棚といえば、BILLYでしょう。日本の公式サイトで検索すると、オプションも色々と揃っています。<a href="http://www.ikea.com/jp/ja/search/?query=billy">http://www.ikea.com/jp/ja/search/?query=billy</a> 幅800mm、高さ2000mmの大きさで6000円から、と激安ですね。<br /> 他にも棚は、<a href="http://www.ikea.com/jp/ja/search/?query=EXPEDIT">EXPEDIT</a>、<a href="http://www.ikea.com/jp/ja/search/?query=HEMNES">HEMNES</a>などなど色々とあります。中でも<a href="http://www.ikea.com/jp/ja/search/?query=BENNO">BENNO</a>に関しては、DVDタワー、DVD/ CD シェルフユニットと説明があるだけあって、奥行きが170mmとCDサイズになっています。</p><p>以上より、</p> <ul> <li>BENNO選択 <ul> <li>そのまま、CDを収納する</li> </ul></li> <li>BENNO以外を選択 <ul> <li>CDをCDボックスなどに入れて収納する</li> </ul></li> </ul><p>この2択になります。</p> </div> <div class="section"> <h4>BENNO</h4> <p>では、まずBENNOを選択した場合について</p> <div class="section"> <h5>BENNOの低い方</h5> <p>BENNOの1000mmの方は500円ほどDVDタワーよりも割高となってしまいますが、圧迫感を感じたくない方はこちらを候補として挙げるでしょう。僕もそうでした。賃貸だと壁に固定できないというのもありますしね。で、高さ半分、幅は倍ということで、DVDタワーの説明文にあるように収納数はCD180枚だろうと予測できます。</p><p>購入した2つを実際に組み立てて見ました。<br /> <a href="http://twitpic.com/2fibgy" title="&egrave;&para;&sup3;&atilde;&#65533;&#65533;&atilde;&#65533;&ordf;&atilde;&#65533;&#65533;&auml;&cedil;&#65533;&aelig;&reg;&micro;&atilde;&#65533;&#65533; on Twitpic"><img src="http://twitpic.com/show/thumb/2fibgy.jpg" width="150" height="150" alt="&egrave;&para;&sup3;&atilde;&#65533;&#65533;&atilde;&#65533;&ordf;&atilde;&#65533;&#65533;&auml;&cedil;&#65533;&aelig;&reg;&micro;&atilde;&#65533;&#65533; on Twitpic"></a><br /> で、嫌な予感満載で試しにCD収納していくと見事に1段分棚が足りませんでした。棚の枚数は4枚です。一段につき普通のCDケースが34-35枚収納できるので、現状ですと175枚が上限でしょうか。一枚棚を追加できれば、+34-35枚。<a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a>で問い合わせたところ、残念ながら追加棚は販売していないそうです。ただ、担当部署には追加棚の販売を掛け合ってくださるそうです。期待しております。</p><p>ということで、BENNOの低い方を購入すると、棚が足りないためCDで埋められません。DVDも収納するとなると、DVDに2段分、CDに3段分として、DVD40枚程度+CD102-105枚の収納力になります。こっちが想定された使い方でしょうね。</p> </div> <div class="section"> <h5>すみません</h5> <p>高さ2000mmのDVDタワーの方は、チラ見しかしておらず購入しておりませんので、参考にならないかと思います。棚の枚数が不明ですが収納数に関しては同等だと思います。</p> </div> </div> <div class="section"> <h4>BENNO以外の選択、BILLY</h4> <p>BENNO以外にはBILLYを購入したので、BILLYについて。</p> <div class="section"> <h5>これまた低い方</h5> <p>BILLYは幅800mm、高さ2000mmのものが一番メジャーで割安ですが、圧迫感を考えて幅800mm、高さ1000mmのものを購入しました。結構割高です。<br /> では、BILLYにCDを収納するとなると、どの位収納できるのでしょうか?BENNOは奥行きが170mmとCDサイズでしたが、BILLYは奥行き280mmです。ここで、実際にCDを詰めてみると奥行きに対して20mmほどはみ出てしまいますが2枚収納できます。つまり、一段に対して同じ幅のBENNOの2倍収納できるわけです。<br /> CD買ったは良いけれどもすぐに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%C3%A5%D4%A5%F3%A5%B0">リッピング</a>して、CD自体は全然取り出さないよ?ハミCDは歓迎だよ!と言う方にはBILLYの方が使い勝手が良いかもしれません。ただし、高さ1000mmのBILLYには棚が2枚しか付いてきませんので、追加棚が2枚必要になります。追加棚を3枚買ってもCDは6段分はいりません。可動棚の都合上、CD入れるには5段分が限界でしょう。それでも、幅800mm、高さ1000mmのBILLYではCD680枚程度収納可能でしょう。おそらく、700枚くらい入りそうです。取り出しやすさを考慮するならば多少収納力が下がり、コストはかかりますが、CDボックスに詰めれば問題ないでしょう。</p> </div> </div> <div class="section"> <h4>BILLY以外</h4> <p>知りません。<br /> EXPEDITは板の厚みがあり好みだったのですが、使い勝手が今ひとつな気がして購入しませんでした。CD収納には向いていないでしょう。</p> </div> <div class="section"> <h4>以上</h4> <p>じゃあ、BENNOじゃなくてBILLY買ったほうがいいんじゃね?と思うかも知れませんが、BENNOは奥行きがCDサイズなので部屋を広く使いたいならば、これはこれでありです。壁にペッタリくっついているようで、結構気に入っています。コスト的にはBILLYがお薦めですけれどね。取り出しやすさ、収納力など考えると、DISKUNIONのラック買うほうが無難かもしれませんね。</p> </div> <div class="section"> <h4>関係ない話</h4> <p>BILLYの幅800mm組み立てていて思いましたが、背板が3つ折りになっているためちゃちいです。背板を挿し込むところでかなり苦労しました。棚本体をうつ伏せにして、横にちょっと持ち上げつつ、手を後ろからツッコミなんとかいれましたけれど。多少のコスト高が許せるなら幅400mmのものがお薦めです。<br /> 安さに惹かれて購入したJANSJÖはLED周りが触れないくらい熱くなりますが、結構明るいですし安いので買いですね。<br /> LERBERGも買いましたが、結構気に入っています。</p> </div> sc3onlinux Collectionからパターンシーケンスを作るまで(途中) hatenablog://entry/17680117127138690948 2010-07-04T19:57:45+09:00 2019-05-17T20:20:40+09:00 7/10にtokyo SuperCollider #1が多摩美ハッカースペースにて開催されます。私も参加したいです。 ちょっと勘違いしていて、超初心者入門中心かなと思っておりました。ならパターンシーケンスについてちょっとまとめてみるかなと、前にまとめておいたものを修正しておりました。 しかし、どうやら発起人の@itaruさんが初心者入門をやってくださり、あとはお好きなネタをどぞって形らしいですので、初心者らしく聴く方で参加したいと思います。中途半端になっていますが、なんらかの参考になればとさっきまで書いていたものをコピペしておきます。整形していないので、rtfかなにかにコピペした方が良いかと。… <p>7/10に<a href="http://tokyosupercollider.blogspot.com/">tokyo SuperCollider</a> #1が<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C2%BF%CB%E0%C8%FE">多摩美</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%CF%A5%C3%A5%AB%A1%BC">ハッカー</a>スペースにて開催されます。私も参加したいです。<br /> ちょっと勘違いしていて、超初心者入<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CC%E7%C3%E6">門中</a>心かなと思っておりました。ならパターンシーケンスについてちょっとまとめてみるかなと、前にまとめておいたものを修正しておりました。<br /> しかし、どうやら発起人の@itaruさんが初心者入門をやってくださり、あとはお好きなネタをどぞって形らしいですので、初心者らしく聴く方で参加したいと思います。中途半端になっていますが、なんらかの参考になればとさっきまで書いていたものをコピペしておきます。整形していないので、rtfかなにかにコピペした方が良いかと。間違っている内容があるかもしれません。たぶん、あります。</p><p>実は、oFARtoolKitPlusネタでもできたらなと思いきや、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>できなかったので早々に諦めたんですけれどw</p><p>2010/07/08<br /> ちょっと追加</p> <pre class="code" data-lang="" data-unlink>/* collectionで何ができるの? collectionとstreamとpatternを使用することで、パターンシーケンスが作成可能です */ /* スパコでのコレクションとはオブジェクトの集合を指し、CollectionクラスのサブクラスにArray,Listなどなどがあります。 helpから抜粋。 Collection - abstract superclass of all Collection subclasses; many methods are inherited from this class SequenceableCollection - abstract superclass of collections whose objects can be indexed by integer ArrayedCollection - abstract superclass of Collections of fixed maximum size whose elements are held in a vector of slots Array - an ArrayedCollection whose slots may contain any object; more efficient than List RawArray - abstract superclass of array classes that hold raw data values Order - order of elements with a numerical index SparseArray - array of elements optimized for huge gaps between them LinkedList - a doubly linked list List - an expandable SequenceableCollection (compare to ArrayedCollection and Array) Collectionのメソッドは、Arrayクラス、Listクラスでも使えます。が、ArrayCollectionのメソッドはListでは使えません。さらに、同じようなメソッドが沢山ありますのでごっちゃにならないようにしましょう。 パターンシーケンスを作成するうえで非常に重要になります。なると思います。 */ /* ArrayとListの違いって? Arrayは最大サイズが固定なので、指定サイズを超えた要素は廃棄されます。 さらにArrayは最大サイズが32までです。 Listはサイズが固定ではないため、指定サイズを超えた要素は廃棄されず挿入されます。 使えるメソッドの違いはありますが、あまり深く考える必要はなさそうです。 */ ( var myArray; myArray = Array.series(31,1,1); //要素を31個 1から1づつ増やして格納 myArray.add(10); //要素を32個目にいれます myArray.at(31).postln; //32個目の要素はなあに? myArray.size.postln; myArray.add(100); //要素を一つ加えます myArray.at(32).postln; //加えた要素はどうなるのっと myArray.size; //廃棄されました ) ( var myList; myList = List.series(31,1,1); //要素を31個 1から1づつ増やして格納 myList.add(10); //要素を32個目にいれます myList.at(31).postln; //32個目の要素はなあに? myList.size.postln; myList.add(100); //要素を一つ加えます myList.at(32).postln; //加えた要素はどうなるのっと myList.size; //廃棄されません ) //というわけで、とりあえずListだけ。 /* 新規生成 */ ( //グローバル変数 ~myList; ~myNewList; ~myNewClearList; ) ( ~myList = List[1,2,3]; //直接要素を代入して生成 (&#34;myList is&#34; + ~myList).postln; ~myNewList = List.new(3); //サイズだけ指定して空で生成 (&#34;myNewList is&#34; + ~myNewList + &#34;and size is &#34; + ~myNewList.size).postln; ~myNewClearList = List.newClear(3); //サイズを指定して、要素nilで埋めて生成 (&#34;myNewClearList is&#34; + ~myNewClearList + &#34;and size is&#34; + ~myNewClearList.size).postln; 5.do({ arg i; ~myNewList.add( i ); ~myNewClearList.fill( i ); } ); ~myNewList.postln;~myNewList.size.postln;~myNewClearList; ) /* 要素追加 */ ( //末尾に要素追加 (&#34;myList before&#34; + ~myList).postln; ~myList.add(100); (&#34;myList after&#34; + ~myList).postln; //先頭に要素追加 (&#34;myNewList before&#34; + ~myNewList).postln; ~myNewList.addFirst(100); (&#34;myNewList after&#34; + ~myNewList).postln; //指定位置に要素追加 (&#34;myNewClearList before&#34; + ~myNewClearList).postln; ~myNewClearList.insert( 2, 100); (&#34;myNewClearList after&#34; + ~myNewClearList); ) /* 要素置換 */ ( (&#34;myList before&#34; + ~myList).postln; ~myList.put(1, 200); (&#34;myList after&#34; + ~myList).postln; //indexが配列の最大サイズを超えている場合は最終indexをput (&#34;myNewList before&#34; + ~myNewList).postln; ~myNewList.clipPut(10, 20); (&#34;myNewList after&#34; + ~myNewList).postln; //最初にもどる (&#34;myNewClearList before&#34; + ~myNewClearList).postln; ~myNewClearList.wrapPut( 4, 100); (&#34;myNewClearList after&#34; + ~myNewClearList).postln; //折り返し (&#34;myNewClearList before&#34; + ~myNewClearList).postln; ~myNewClearList.foldPut( 4, 200);/ (&#34;myNewClearList after&#34; + ~myNewClearList).postln; //要素全てを置換 *collectionのfillメソッドとは異なります (&#34;myNewClearList before&#34; + ~myNewClearList).postln; ~myNewClearList.fill(2); (&#34;myNewClearList after&#34; + ~myNewClearList); ) /* 要素の並べ替えなどの操作 新規リストを生成するので、元のリストは変更されません。変更したものを使い回したいなら別の変数に代入しましょう。 */ ( //逆に並べ替え (&#34;myList before&#34; + ~myList).postln; ~myList.reverse; (&#34;myList after&#34; + ~myList).postln; //スクランブルに並べ替え (&#34;myList before&#34; + ~myList).postln; ~myList.scramble; (&#34;myList after&#34; + ~myList).postln; //配列の中心要素を軸にミラー(mirror1,mirror2なら3つの要素|3つの要素 になります) (&#34;myList before&#34; + ~myList).postln; ~myList.mirror; (&#34;myList after&#34; + ~myList).postln; //要素を引数分繰り返します (&#34;myList before&#34; + ~myList).postln; ~myList.stutter(10); (&#34;myList after&#34; + ~myList).postln; //引数値だけ要素の順番をずらします (&#34;myList before&#34; + ~myList).postln; ~myList.rotate(2); (&#34;myList after&#34; + ~myList).postln; ) //他のメソッドはhelpを見てね /* コレクションの基本的な説明は上記として patternクラスを使用して、ステップシーケンスを作成してみましょう。 patternクラスも非常に多数ありますので、ごく一部だけ。 */ /* その前にちょっとStreamsの説明を SC3でのstreamとは、単なるシーケンスの値を表します。1,2,3,1,2,3といった数値の連続のことです。 シーケンスの次の値を取得するにはstreamのobjectのnextを使用します。 streamクラスのサブクラスにFuncStreamとかRoutineがありますが、ここでは割愛。 なんらかのループ処理( streamオブジェクト.next )でstreamオブジェクトの中身を順番に取り出すことでシーケンスを作成できる、ということです。 */ /* patternクラスって? patternクラス(そのサブクラス)はコレクションを一つの固まりと見なし、 中身をごにょごにょしたり、何回繰り返すかを決めて、パターンオブジェクトを返します。 そして、asStreamメッセージによってパターンオブジェクトをストリームとして扱うことができます。 要は、コレクションの中身をいじくり倒して、nextメソッドで順番に要素を取り出すことができるということです。 また、patternクラスには、ListPatternsとFilterPatternsなどに分類でき、 ListPatternsは、引数にコレクションを渡して、コレクションの要素を並べ替えたりします。 FilterPatternsは、引数にパターンを渡して、パターンをいじくります。 */ //myListはコレクション、Pseqクラスはコレクションを順番通りに何回繰り返すか決めます ( var pat; ~myList.postln; pat = Pseq(~myList, 2); //patにmyListを2回繰り返したものをパターンとして代入します pat = pat.asStream.postln; //patをstream(routine)として扱います 6.do({ pat.next.postln;}); //6回ループ、ここでnextメソッドを使用してpatから取り出す値をずらしていきます ) //Prandクラスはコレクションの中身をランダムに取り出します。 //Pseedクラスはフィルタパターンクラスであり、引数のパターンオブジェクトにシードを与えてやります。 ( var pat; ~myList.postln; pat = Prand(~myList, 6); //myListからランダムに一つの要素を6回抜き出して、patに代入します pat = Pseed(2010, pat, 6); pat = pat.asStream.postln; //patをstream(routine)として扱います 6.do({ pat.next.postln;}); //6回ループ、ここでnextメソッドを使用してpatから取り出す値をずらしていきます ) /* では、基本は一通り押さえましたのでシーケンスを作ってみましょう */ //まずはシンセを定義 ( SynthDef(&#34;collectSynth&#34;, { arg amp, freq=440, gate=1, pan=0, outBus=0, fxBus=10, fx=0.0, vol=1.0; var signal, env, outSend, fxSend, scale, key; env = Env.adsr(); //シーケンスパートにてgate=0で解放しないと鳴りっぱなし。 scale = Scale.major; key = DegreeToKey.kr( scale.as(LocalBuf), //bufnum MouseX.kr(0, 10), //indexとしてのinput signal scale.stepsPerOctave, 1, //mul 72 //offset ).midicps; signal = SinOsc.ar(key, 0, amp) * vol; fxSend = signal * fx; outSend = signal * (1.0 - fx); Out.ar(fxBus, Pan2.ar(EnvGen.ar(env, gate, doneAction: 2) * fxSend, pan) ); Out.ar(outBus, Pan2.ar(EnvGen.ar(env, gate, doneAction: 2) * outSend, pan) ); }).store; ) //シーケンスパート ~myList = List[1,0,1,0,1,0]; ( var t, n, synth1, synth1Loop; ~effectGroup = Group.tail(s); ~synthGroup = Group.tail(s); t = TempoClock(120/60); //120bps //n = NetAddr(&#34;127.0.0.1&#34;,57124); //oscで他ソフトにメッセージ送る場合 synth1 = Task({ var pattern; pattern = Pseq(~myList, inf).asStream; loop({ synth1Loop = Synth.tail(~synthGroup, &#34;collectSynth&#34;, [\amp, pattern.next, \outBus, 0, \fxBus, 10, \vol, 0.8] ); (t.beatDur).wait; synth1Loop.set(\gate, 0); //synthのenvがadsrの時はここらで解放してやります }); }); t.sched(0, { synth1.start }); ) ~myList.insert(3, 0); //要素の挿入 ~myList[3] = 1; //要素の置換 </pre> sc3onlinux iida callingの正しい使用法 hatenablog://entry/17680117127138691071 2010-06-29T20:20:49+09:00 2019-05-17T20:20:41+09:00 iida calling v3.1なんてものがいつ出たのか知らないけれど、ちょっと面白かったのでキャプしてみました。 再生中にスクロールさせまくるだけです。ブラウザによっては無理ですかね。FFだとダメでした。読み込み中に思いっきりスクロールさせると画像がダーっと連なるやつ、の音版。 <p><a href="http://iida.jp/calling/">iida calling v3.1</a>なんてものがいつ出たのか知らないけれど、ちょっと面白かったのでキャプしてみました。<br /> <iframe width="420" height="315" src="https://www.youtube.com/embed/kMSx9m47bhc?wmode=transparent" frameborder="0" allowfullscreen></iframe></p><p>再生中にスクロールさせまくるだけです。ブラウザによっては無理ですかね。FFだとダメでした。読み込み中に思いっきりスクロールさせると画像がダーっと連なるやつ、の音版。</p> sc3onlinux Cocoa EmacsでSuperCollider 2 hatenablog://entry/17680117127138691120 2010-05-24T23:41:28+09:00 2019-05-17T20:20:41+09:00 どうやらscelではcocoaが使えないようですので、GUI関係をつかいたいならSwingOSCに頼るしかなさそうです。(もういっこGUI関係のものがあった記憶がありますが、SCUMでしたっけ?) 入れ方使い方 落とします http://www.sciss.de/swingOSC/ ここのdownloadから落としましょう。 $ svn co https://swingosc.svn.sourceforge.net/svnroot/swingosc/trunk/ SwingOSCでも良いですがコンパイルしなくてはならないので面倒ですぜ。with-extrasな方は、/Applications/… <p>どうやらscelでは<a class="keyword" href="http://d.hatena.ne.jp/keyword/cocoa">cocoa</a>が使えないようですので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a>関係をつかいたいならSwingOSCに頼るしかなさそうです。(もういっこ<a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a>関係のものがあった記憶がありますが、SCUMでしたっけ?)</p> <div class="section"> <h4>入れ方使い方</h4> <div class="section"> <h5>落とします</h5> <p><a href="http://www.sciss.de/swingOSC/">http://www.sciss.de/swingOSC/</a> ここのdownloadから落としましょう。</p> <pre class="code" data-lang="" data-unlink>$ svn co https://swingosc.svn.sourceforge.net/svnroot/swingosc/trunk/ SwingOSC</pre><p>でも良いですが<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>しなくてはならないので面倒ですぜ。with-extrasな方は、/Applications/<a class="keyword" href="http://d.hatena.ne.jp/keyword/SuperCollider">SuperCollider</a>/Optional Installs/SwingOSC/ に既に入っているかもしれません。</p> </div> <div class="section"> <h5>移します</h5> <pre class="code" data-lang="" data-unlink>$ cp -R ./SwingOSC/SuperCollider/SCClassLibrary/SwingOSC/ ~/.sclang/SCClassLibrary/SwingOSC/ $ ls ~/.sclang/SCClassLibrary</pre><p>SwingOSC.jarはsc3のフォルダに。Helpファイルはデフォが/Applications/<a class="keyword" href="http://d.hatena.ne.jp/keyword/SuperCollider">SuperCollider</a>/Helpなので、デフォでも良いですし。M-x sclang-customizeで変えてもおkです。</p> <pre class="code" data-lang="" data-unlink>$ cp ./SwingOSC/build/SwingOSC.jar /Applications/SuperCollider/ $ ls /Applications/SuperCollider/SwingOSC.jar $ cp -R SwingOSC/SuperCollider/Help/SwingOSC/ /Applications/SuperCollider/Help/SwingOSC $ ls /Applications/SuperCollider/Help/</pre> </div> <div class="section"> <h5>立ち上げます</h5> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/emacs">emacs</a>を立ち上げてM-x sclang-start。</p> <pre class="code" data-lang="" data-unlink>GUI.current; ( SwingOSC.program = &#34;/Applications/SuperCollider/SwingOSC.jar&#34;; SwingOSC.java = &#34;/usr/bin/java&#34;; g=SwingOSC.default.boot; )</pre><p>まず、一行目をC-c C-cしてみて、SwingOSCと表示されるのを確認しましょう。次に()をC-M-xとか実行。PostBufferにSwingOSC : server connected.って出たら完了です。とりあえず、サーバパネルをC-c C-p pって立ち上げてみましょう。</p> </div> </div> <div class="section"> <h4>以上</h4> <p>使い込んでいないので使えないクラスがあるかも知れませんが、Help.<a class="keyword" href="http://d.hatena.ne.jp/keyword/gui">gui</a>;が使えるので個人的には良しとします。startup.rtfを起動時に読み込んでくれればこいつに記述しておくのですが、ケチなのか読みにいってくれません。~/Library/Application Support/<a class="keyword" href="http://d.hatena.ne.jp/keyword/SuperCollider">SuperCollider</a>/startup.rtfじゃないのかよ、と。M-x sclang-customizeにもそれっぽい設定はなさそう。<a class="keyword" href="http://d.hatena.ne.jp/keyword/.emacs">.emacs</a>.d/init.elになんか書いてやればできそうですが、よくわかんないです。<br /> 実は、C-c C-nかM-TABでおーとこんぷりーとができるので<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C1%A1%BC%A5%C8%A5%B7%A1%BC%A5%C8">チートシート</a>を作り直す予定です。</p> </div> sc3onlinux ぜろから導入、cocoa emacsでSuperCollider hatenablog://entry/17680117127138691196 2010-05-23T16:41:36+09:00 2019-05-17T20:20:42+09:00 インストール macports git emacs w3m emacs-w3m macports 他のインストールを楽にするため、まずはmacportsを入れます。コンパイルは面倒なので、パッケージをDLしてインストールしてしまいましょう。 http://www.macports.org/ Installing MacPorts “dmg”disk images for Snow Leopard git macportsからインストールします。ここでは、git-coreだけで問題ないでしょう。 $ sudo port install git-core cocoa emacs $ sudo po… <div class="section"> <h4>インストール</h4> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/macports">macports</a></li> <li>git</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/emacs">emacs</a></li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/w3m">w3m</a></li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/emacs-w3m">emacs-w3m</a></li> </ul> <div class="section"> <h5><a class="keyword" href="http://d.hatena.ne.jp/keyword/macports">macports</a></h5> <p>他のインストールを楽にするため、まずは<a class="keyword" href="http://d.hatena.ne.jp/keyword/macports">macports</a>を入れます。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>は面倒なので、パッケージをDLしてインストールしてしまいましょう。</p> <pre class="code" data-lang="" data-unlink>http://www.macports.org/ Installing MacPorts “dmg”disk images for Snow Leopard</pre> </div> <div class="section"> <h5>git</h5> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/macports">macports</a>からインストールします。ここでは、git-coreだけで問題ないでしょう。</p> <pre class="code" data-lang="" data-unlink>$ sudo port install git-core</pre> </div> <div class="section"> <h5><a class="keyword" href="http://d.hatena.ne.jp/keyword/cocoa">cocoa</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/emacs">emacs</a></h5> <pre class="code" data-lang="" data-unlink>$ sudo port install emacs-app</pre> </div> <div class="section"> <h5><a class="keyword" href="http://d.hatena.ne.jp/keyword/w3m">w3m</a></h5> <pre class="code" data-lang="" data-unlink>$ sudo port install w3m</pre> </div> <div class="section"> <h5><a class="keyword" href="http://d.hatena.ne.jp/keyword/emacs-w3m">emacs-w3m</a></h5> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/macports">macports</a>からインストールすると、<a class="keyword" href="http://d.hatena.ne.jp/keyword/emacs">emacs</a>のバージョンによってはサポートしていないと怒られる場合がありますので、念のため<a class="keyword" href="http://d.hatena.ne.jp/keyword/CVS">CVS</a>からインストールします。</p> <pre class="code" data-lang="" data-unlink>$ cvs -d :pserver:anonymous@cvs.namazu.org:/storage/cvsroot login CVS password: # パスワードは設定されていません.単に Enter/Return キーを押して下さい. $ cvs -d :pserver:anonymous@cvs.namazu.org:/storage/cvsroot co emacs-w3m</pre><p>インストールします。</p> <pre class="code" data-lang="" data-unlink>$ ./configure --with-emacs=/Applications/Emacs.app/Contents/MacOS/Emacs --with-lispdir=/Applications/Emacs.app/Contents/Resource/share/emacs/site-lisp/w3m --with-icondir=/Applications/Emacs.app/Contents/Resource/etc/w3m $ make $ sudo make install $ sudo make install-icons</pre> </div> </div> <div class="section"> <h4>設定</h4> <div class="section"> <h5>シェル</h5> <p>以下<a class="keyword" href="http://d.hatena.ne.jp/keyword/bash">bash</a>の場合ですが、sc3へのパスを通してやります。最後にsclangを実行してみて、パスが通っていることを確認します。</p> <pre class="code" data-lang="" data-unlink>$ echo $SHELL /bin/bash $ vi .bash_profile if [ -f ~/.bashrc ]; then . ~/.bashrc fi $ cat .bash_profile $ vi .bashrc export PATH=$PATH:/Applications/SuperCollider $ cat .bashrc $ sclang -h</pre> </div> <div class="section"> <h5>sc3ファイルのコピー</h5> <pre class="code" data-lang="" data-unlink>$ mkdir ~/.sclang $ cp -R /Applications/SuperCollider/SCClassLibrary ~/.sclang $ cp -R /Applications/SuperCollider/plugins ~/.sclang $ cp /Applications/SuperCollider/scsynth ~/.sclang</pre><p>コピーしたら、~/.sclang/SCClassLibrary/Platform/<a class="keyword" href="http://d.hatena.ne.jp/keyword/osx">osx</a>/OSXPlatform.scファイルのstartup部分を以下に変更します。</p> <pre class="code" data-lang="" data-unlink>startup { if ( this.hasFeature( \emacs ) ) { Document.implementationClass.startup; }; this.loadStartupFiles; }</pre> </div> <div class="section"> <h5>scel</h5> <p>scelをgitでDLして、SCClassLibraryにコピーします。</p> <pre class="code" data-lang="" data-unlink>$ ls ~/.emacs.d (なければ $ mkdir ~/.emacs.d $ cd ~/.emacs.d $ git init $ git submodule add git://github.com/samaaron/scel.git vendor/supercollider $ cp -R ~/.emacs.d/vendor/supercollider/sc ~/.sclang/SCClassLibrary/Common/Emacs</pre> </div> <div class="section"> <h5><a class="keyword" href="http://d.hatena.ne.jp/keyword/emacs">emacs</a></h5> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/emacs">emacs</a>の設定ファイルを記述します。emacs22からは~/<a class="keyword" href="http://d.hatena.ne.jp/keyword/.emacs">.emacs</a>.elではなく、~/<a class="keyword" href="http://d.hatena.ne.jp/keyword/.emacs">.emacs</a>.d/以下に設定ファイルを置くことが推奨されているそうです。<br /> では、~/<a class="keyword" href="http://d.hatena.ne.jp/keyword/.emacs">.emacs</a>.d/init.elに以下を記述します。ついでにヘルプファイルを見るために必要な<a class="keyword" href="http://d.hatena.ne.jp/keyword/w3m">w3m</a>、<a class="keyword" href="http://d.hatena.ne.jp/keyword/emacs-w3m">emacs-w3m</a>の設定も記述しましょう。</p> <pre class="code" data-lang="" data-unlink>(set-language-environment &#39;Japanese) (prefer-coding-system &#39;utf-8) (setq exec-path (append exec-path &#39;(&#34;/opt/local/bin&#34;))) (require &#39;w3m-load) (add-to-list &#39;load-path &#34;~/.emacs.d/vendor/supercollider/el&#34;) (require &#39;sclang) (custom-set-variables &#39;(sclang-auto-scroll-post-buffer t) &#39;(sclang-eval-line-forward nil) &#39;(sclang-help-path (quote (&#34;/Applications/SuperCollider/Help&#34;))) &#39;(sclang-runtime-directory &#34;~/.sclang/&#34;)) (setq path &#34;/Applications/SuperCollider:/rest/of/PATH&#34;) (setenv &#34;PATH&#34; path) (push &#34;/Applications/SuperCollider&#34; exec-path)</pre> </div> </div> <div class="section"> <h4>実行</h4> <p>インストールした<a class="keyword" href="http://d.hatena.ne.jp/keyword/emacs">emacs</a>.appを実行します。次にスパコモードへ変更、</p> <pre class="code" data-lang="" data-unlink>M-x sclang-start</pre><p>で変更されます。<br /> 以下scelのショートカットコマンドです。</p> <pre class="code" data-lang="" data-unlink>サーバブート C-c C-p b サーバストップ C-c C-p q サーバパネル開く C-c C-p p リージョン実行(範囲内どこでも) C-M-x リージョン実行(範囲指定) C-c C-x 一行実行 C-c C-c ストップ C-c C-s メイン実行 C-c C-f 再コンパイル C-c C-l ヘルプ(検索) C-c C-h ヘルプ(w3m) C-M-h クラス定義開く C-c : クラスリファレンス開く C-c ;</pre> </div> <div class="section"> <h4>以上</h4> <p>慣れれば<a class="keyword" href="http://d.hatena.ne.jp/keyword/emacs">emacs</a>最強!とか周りに言い出すはずです。慣れるまで結構時間かかりますけれど。<br /> <a class="keyword" href="http://d.hatena.ne.jp/keyword/linux">linux</a>時代に作った<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C1%A1%BC%A5%C8%A5%B7%A1%BC%A5%C8">チートシート</a>がありますのでどぞ。たぶん<a class="keyword" href="http://d.hatena.ne.jp/keyword/cocoa">cocoa</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/emacs">emacs</a>でもそのまま使えるはずです。<br /> <a href="http://spreadsheets.google.com/pub?key=pcuCAL5TV5IcS_bSRIXrYEg&single=true&gid=0&output=html">http://spreadsheets.google.com/pub?key=pcuCAL5TV5IcS_bSRIXrYEg&single=true&gid=0&output=html</a></p> </div> sc3onlinux SuperColliderとopenFrameworks2 hatenablog://entry/17680117127138691295 2010-05-04T22:17:28+09:00 2019-05-17T20:20:43+09:00 sc3からoFにOSCメッセージを送る方法は前回書きました。あまり良い方法ではありませんが。では、oFからSC3にOSCメッセージを送る方法はどうかといいますと、ofxOSC使えばちょい手間ですが簡単に出来ます。ただ、さらに簡単に行えるプラグインがofxSuperColliderです。ofxSuperColliderのソース見ていただければお分かりですが、中身はofxOSCを使用しています。より細かく制御したいならofxOSC使って自分でクラス組んでねってことです。 ofxSuperColliderのサンプルですと、oFを実行した際にシンセを作成、サーバに送っているため、ちょっと参考にならない… <p>sc3からoFにOSCメッセージを送る方法は前回書きました。あまり良い方法ではありませんが。では、oFからSC3にOSCメッセージを送る方法はどうかといいますと、ofxOSC使えばちょい手間ですが簡単に出来ます。ただ、さらに簡単に行える<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%E9%A5%B0%A5%A4%A5%F3">プラグイン</a>がofxSuperColliderです。ofxSuperColliderのソース見ていただければお分かりですが、中身はofxOSCを使用しています。より細かく制御したいならofxOSC使って自分でクラス組んでねってことです。<br /> ofxSuperColliderのサンプルですと、oFを実行した際にシンセを作成、サーバに送っているため、ちょっと参考にならない場合がありますので、以下キーを押してシンセ作成、サーバに送る、音を出す。ってサンプルになってます。じゃあコードから行くっすよ。</p> <div class="section"> <h4>testApp.cpp</h4> <pre class="code" data-lang="" data-unlink>#include &#34;testApp.h&#34; //-------------------------------------------------------------- void testApp::setup(){ ofSetWindowTitle(&#34;oF2sc3Test&#34;); ofSetFrameRate(60); ofBackground(0,0,0); receiver.setup( PORT ); //OSCメッセージ受信ポート。今回は関係ないです flag = 0; //ここも今回は関係ないです //ofxsupercolliderここから //oFを実行した際にsc3側で作成したシンセをデフォルト値でサーバに送ります、本コードでは不要になります。サンプルではここでシンセをサーバに送っています。デフォルト値とは、sc3側で var amp = 0.4;とかの0.4の値のことです。 //synty1 = new ofxSCSynty(&#34;ofxsynth1&#34;); //synth1-&gt;create(); //デフォルト値ではなく初期値を設定する場合setしてからcreate() //synth2 = new ofxSCSynth(&#34;ofxsynth2&#34;); //synth2-&gt;set(&#34;vol&#34;,0.6); //synth2-&gt;create(); //サンプルは上記のようになっていますが、oF実行した際にシンセ作成してしまうと、後の処理が面倒になる可能性があります。どこかのタイミングでシンセを音を消したいときに、単に音量を0にするかシンセを解放するかなどの制御が必要です。解放した方がメモリ的に優しいですよね。ここではなく別のところでシンセ作成した方が良いと思います。 } //-------------------------------------------------------------- void testApp::update(){ oscReceive();//受け取り用なので今回は関係なし } //-------------------------------------------------------------- testApp::~testApp() { //free()によってシンセを解放します、必要ならばデストラクタで解放を忘れないようにしましょう。sc3側でdoneAction:2を指定し、かつgateに0を送ってシンセを解放している場合は不要。本コードではgateに0を送ってシンセを解放していますので、不要になります。試しにコメントを外してみると、実行アプリを閉じたときにノードがないっすよ、とかのエラーが確認できます。 //synth1-&gt;free(); //synth2-&gt;free(); } //-------------------------------------------------------------- void testApp::draw(){ string buf; buf = &#34;listening for osc messages on port&#34; + ofToString( PORT ); ofDrawBitmapString( buf, 10, 20 ); ofDrawBitmapString(&#34;flag : &#34;+ofToString(flag), 50, 60); ofDrawBitmapString(&#34;sinAmp : &#34;+ofToString(sinAmp), 50, 70); } //受け取り用なので今回は不要 void testApp::oscReceive() { // hide old messages for ( int i=0; i&lt;NUM_MSG_STRINGS; i++ ) { if ( timers[i] &lt; ofGetElapsedTimef() ) msg_strings[i] = &#34;&#34;; } // check for waiting messages while( receiver.hasWaitingMessages() ) { // get the next message ofxOscMessage receiveSC; receiver.getNextMessage( &amp;receiveSC ); if(receiveSC.getAddress() == &#34;/scSinReceive&#34;) { flag = 1; //テスト用 sinAmp = receiveSC.getArgAsFloat(0); } } } //-------------------------------------------------------------- void testApp::keyPressed (int key){ if (key == &#39;f&#39;){ ofToggleFullscreen(); } } //-------------------------------------------------------------- //ここから本サンプルのメイン。a押すとシンセを作成して、グループのケツとしてシンセをサーバに送り、gate,ampを0にして音を鳴らします。sを押すとgateを0にすることで、シンセを解放します。sc3側ではdoneAction:7としていますので、このシンセより前のシンセノードも全て解放します。 void testApp::keyReleased (int key){ if(key == &#39;a&#39;) { synth1 = new ofxSCSynth(&#34;ofxsynth1&#34;); synth1-&gt;set(&#34;gate&#34;,1); synth1-&gt;set(&#34;amp&#34;,1.0); synth1-&gt;addToTail(); } if(key ==&#39;s&#39;) { synth1-&gt;set(&#34;gate&#34;,0); //sc3側でdoneAction:2にしており、gateに0を送っているため下のfreeは必要なし //念のためdoneAction:7にして同じグループに追加したノードを解放している、もっと良い方法があるはず! //synth1-&gt;free(); } //必要ないとは思いますが念のためfree()でシンセを解放できるキーを定義。 if(key ==&#39;d&#39;) { synth1-&gt;free(); } if(key ==&#39;z&#39;) { synth2-&gt;set(&#34;gate&#34;,1); synth2-&gt;set(&#34;amp&#34;,1.0); synth2-&gt;addToTail(); } if(key ==&#39;x&#39;) { synth2-&gt;set(&#34;gate&#34;,0); //synth2-&gt;free(); } } //-------------------------------------------------------------- void testApp::mouseMoved(int x, int y ){ } //-------------------------------------------------------------- void testApp::mouseDragged(int x, int y, int button){ } //-------------------------------------------------------------- void testApp::mousePressed(int x, int y, int button){ if (button ==0) { //マウスクリックでオブジェクトsynty1のパラメータを変更。 // synth1-&gt;set(&#34;amp&#34;,1.0); } } //-------------------------------------------------------------- void testApp::mouseReleased(int x, int y, int button){ //synth1-&gt;set(&#34;amp&#34;,0.0); }</pre> </div> <div class="section"> <h4>testApp.h</h4> <p>ofxSuperCollider.hをインクルードすればおkです。</p> <pre class="code" data-lang="" data-unlink>#ifndef _TEST_APP #define _TEST_APP #include &#34;ofMain.h&#34; #include &#34;ofxOsc.h&#34; #include &#34;ofxSuperCollider.h&#34; #define HOST &#34;localhost&#34; #define PORT 57124 #define NUM_MSG_STRINGS 20 class testApp : public ofBaseApp{ public: ~testApp(); void setup(); void update(); void draw(); void keyPressed(int key); void keyReleased(int key); void mouseMoved(int x, int y ); void mouseDragged(int x, int y, int button); void mousePressed(int x, int y, int button); void mouseReleased(int x, int y, int button); void windowResized(int w, int h); void oscReceive(); ofxSCSynth *synth1; //ここの定義も忘れずに。作りたいシンセのオブジェクトを定義します。 ofxSCSynth *synth2; //同様 ofxSCBus *bus; //出力ofxSCBusを指定したい場合はこれも ofxSCBuffer *buffer; //ofxSCBufferはファイルを読み込んで使いたい場合に private: ofxOscReceiver receiver; int current_msg_string; string msg_strings[NUM_MSG_STRINGS]; float timers[NUM_MSG_STRINGS]; float sinAmp; int flag; }; #endif</pre> </div> <div class="section"> <h4>sc3側</h4> <p>普通にシンセを定義してやれば良いです。ofxSuperColliderのサンプルシンセで問題ないです。doneAction:7にしていますが、これはgateに0を送ったときの挙動を指定しています。7だとこのグループにおける指定したシンセノードを含め、それより前のノードを全て解放する、の意味になります。ofxsynth2の方は上手く解放できないはずです。</p> <pre class="code" data-lang="" data-unlink>( SynthDef(&#34;ofxsynth1&#34;, { arg amp, dur, freq = 440, gate = 1, pan = 0, outBus = 0, fxBus = 10, fx = 0.0, vol = 0.8; var env, signal, outSend, fxSend,scale,key; env = Env.adsr(); scale = Scale.ionian.postln; key = DegreeToKey.kr( scale.as(LocalBuf), SinOsc.kr(0.08*MouseX.kr(1,10000),0,12), // mouse indexes into scale scale.stepsPerOctave, 1, // mul = 1 70 // offset by 70 notes ).midicps; signal = SinOsc.ar(key, 0, amp) * vol; fxSend = signal * fx; outSend = signal * (1.0 - fx); Out.ar(fxBus, Pan2.ar(EnvGen.ar(env, gate, doneAction: 7) * fxSend, pan) ); Out.ar(outBus, Pan2.ar(EnvGen.ar(env, gate, doneAction: 7) * outSend, pan) ); }).store; SynthDef(&#34;ofxsynth2&#34;, { arg amp, dur, freq = 220, gate = 1,pan = 0, outBus = 0, fxBus = 10, fx = 0.0, vol = 0.8; var env, signal, outSend, fxSend; env = Env.adsr(); signal = SinOsc.ar(freq, 0, amp); signal = Blip.ar(signal+WhiteNoise.ar(0.00001), 2, 0.8); signal = LPF.ar(signal, 1400); fxSend = signal * fx; outSend = signal * (1.0 - fx); Out.ar(fxBus, Pan2.ar(EnvGen.ar(env, gate, doneAction: 2) * fxSend, pan) ); Out.ar(outBus, Pan2.ar(EnvGen.kr(env, gate, doneAction: 2) * outSend, pan) ); }).store; )</pre> </div> <div class="section"> <h4>関数</h4> <div class="section"> <h5>ofxSCSynthクラス</h5> <p>シンセ定義、bufferで読み込んだファイルを再生するときにも</p> <ul> <li>create() <ul> <li>シンセ作成。指定可能な引数はint position, int groupID、よくわかんないっす。</li> </ul></li> <li>set(string arg, int <a class="keyword" href="http://d.hatena.ne.jp/keyword/value">value</a>) <ul> <li>arg名のパラメータに、<a class="keyword" href="http://d.hatena.ne.jp/keyword/value">value</a>値を送ります。</li> </ul></li> </ul> </div> <div class="section"> <h5>ofxBufferクラス</h5> <ul> <li>read(string path) <ul> <li>サンプルみたいにbuffer->read(ofToDataPath("bell.aif", true));で</li> </ul></li> </ul><p>とかありますが、細かいところはソース読んで使うしかなさそうです。<br /> シンセをcreate()するときにはノードIDをずらして作成しますので、ノードIDを意識して組まないとsc3側でエラーが出ます。sc3側のノードの概念はよくわかっていないのでなんとも書けませんが。<br /> 以上。</p> </div> </div> sc3onlinux SuperColliderとopenframeworks hatenablog://entry/17680117127138691435 2010-04-04T23:14:55+09:00 2019-05-17T20:20:44+09:00 SuperColliderにメッセージ送るならofxOscじゃなくて、ofxSuperCollider使えば良いじゃん。とまあそうですが、ざっとソース見たところofxSuperColliderではSuperColliderからoscメッセージを受け取ることはできなさそうですので、基本的な手法をメモ。ほぼoFのサンプルまんまですが。 SuperCollider側 ( SynthDef("oscTestSin", { arg amp, pan = 0, outBus = 0, fxBus = 10, fx = 0.0, vol = 0.8; var env, signal, outSend, fx… <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/SuperCollider">SuperCollider</a>にメッセージ送るならofxOscじゃなくて、ofxSuperCollider使えば良いじゃん。とまあそうですが、ざっとソース見たところofxSuperColliderでは<a class="keyword" href="http://d.hatena.ne.jp/keyword/SuperCollider">SuperCollider</a>からoscメッセージを受け取ることはできなさそうですので、基本的な手法をメモ。ほぼoFのサンプルまんまですが。</p> <div class="section"> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/SuperCollider">SuperCollider</a>側</h4> <pre class="code" data-lang="" data-unlink>( SynthDef(&#34;oscTestSin&#34;, { arg amp, pan = 0, outBus = 0, fxBus = 10, fx = 0.0, vol = 0.8; var env, signal, outSend, fxSend; env = Env.perc(0.001, 0.2, 1, -3); signal = SinOsc.ar(440, 0, amp) * vol; fxSend = signal * fx; outSend = signal * (1.0 - fx); Out.ar(fxBus, Pan2.ar(EnvGen.ar(env, doneAction: 2) * fxSend, pan) ); Out.ar(outBus, Pan2.ar(EnvGen.ar(env, doneAction: 2) * outSend, pan) ); }).store; ) ( var t,n,sin,pan; ~effectGroup = Group.tail(s); ~synthGroup = Group.tail(s); t = TempoClock(210/60); n = NetAddr(&#34;127.0.0.1&#34;,57124); sin = Task({ var pat,pat2,pattern; pattern = [1.0,0.0,1.0,0.0,1.0,0.1,1.0,0.0]; pat = Pseq(pattern,inf).asStream; pat2 = Pseq(pattern,inf).asStream; //ここが問題 loop({ Synth.tail(~synthGroup, &#34;oscTestSin&#34;, [\amp, pat.next, \outBus, 0, \fxSend, 10, \vol, 1.0, \fx, 0.0] ); n.sendMsg(&#34;/scSinReceive&#34;,pat2.next); //力技でメッセージ送っています (t.beatDur).wait; }); }); t.sched(0, {sin.start}); )</pre> </div> <div class="section"> <h4>oF側(ofxOsc使います)</h4> <pre class="code" data-lang="" data-unlink>[testApp.h] #ifndef _TEST_APP #define _TEST_APP #include &#34;ofMain.h&#34; #include &#34;ofxOsc.h&#34; #define HOST &#34;localhost&#34; #define PORT 57124 #define NUM_MSG_STRINGS 20 class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); void keyPressed(int key); void keyReleased(int key); void mouseMoved(int x, int y ); void mouseDragged(int x, int y, int button); void mousePressed(int x, int y, int button); void mouseReleased(int x, int y, int button); void windowResized(int w, int h); void oscReceive(); private: ofxOscReceiver receiver; int current_msg_string; string msg_strings[NUM_MSG_STRINGS]; float timers[NUM_MSG_STRINGS]; float sinAmp; int flag; }; #endif</pre><pre class="code" data-lang="" data-unlink>[testApp.cpp] #include &#34;testApp.h&#34; //-------------------------------------------------------------- void testApp::setup(){ ofSetWindowTitle(&#34;oscTest&#34;); ofSetFrameRate(60); ofBackground(0,0,0); receiver.setup( PORT ); flag = 0; } //-------------------------------------------------------------- void testApp::update(){ oscReceive(); } //-------------------------------------------------------------- void testApp::draw(){ string buf; buf = &#34;listening for osc messages on port&#34; + ofToString( PORT ); ofDrawBitmapString( buf, 10, 20 ); ofDrawBitmapString(&#34;flag : &#34;+ofToString(flag), 50, 60); ofDrawBitmapString(&#34;sinAmp : &#34;+ofToString(sinAmp), 50, 70); } void testApp::oscReceive() { // hide old messages おまじない for ( int i=0; i&lt;NUM_MSG_STRINGS; i++ ) { if ( timers[i] &lt; ofGetElapsedTimef() ) msg_strings[i] = &#34;&#34;; } // check for waiting messages while( receiver.hasWaitingMessages() ) { ofxOscMessage receiveSC; receiver.getNextMessage( &amp;receiveSC ); if(receiveSC.getAddress() == &#34;/scSinReceive&#34;) { flag = 1; //テスト用 sinAmp = receiveSC.getArgAsFloat(0); //ここでfloat型に変換してsinAmpに代入します。 //getArgAsFloat(1)とかにしますとn.sendMsg(&#34;/scSinReceive&#34;,pat2.next,arg1);のarg1を読み込めます。 } } } //-------------------------------------------------------------- keyPressed以下略 }</pre> </div> <div class="section"> <h4>駄目だなあ</h4> <p>sc3側で上手くoscメッセージを送る手法がよく分かっていませんので、シンセに送っているメッセージと同じものをコピーしてoFにも送っています。もっと上手くoscメッセージを送る手法があると思うのですが、help見てもよくわかりませんでした。</p><p>注意点としては、update関数内でoscメッセージ読み込むようにしますと、frameRate()で指定したレートで読み込みます。当然、指定レートでoscメッセージが更新されます。タイミングによってはズレが生じますのでチューニングというか注意が必要になります。</p> </div> sc3onlinux SuperCollider 3.3.1 win版について hatenablog://entry/17680117127138691520 2010-02-28T21:46:35+09:00 2019-05-17T20:20:45+09:00 ようやく待望のSuperCollider 3.3.1 for windowsがリリースされました。 MouseX,MouseYが使えるようになったなどの変更があります。あと、helpブラウザがかなり使い易いです。詳細な変更点はこちらを参照して下さい。 インストールする際に、ちょっと迷う箇所があります。以前のバージョンである3.3winalpha6などがインストールされていると、3.3.1をインストールする際に、別のバージョンの製品が……と怒られます。で、プログラムの追加と削除から削除しようと見てみると私の環境では見当たらず……。すわ、レジストリかとか思って削除してもダメ。 以前のバージョンを削… <p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/sc3onlinux/20100228212553" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sc3onlinux/20100228/20100228212553.jpg" alt="f:id:sc3onlinux:20100228212553j:image" title="f:id:sc3onlinux:20100228212553j:image" class="hatena-fotolife" itemprop="image"></a></span><br /> ようやく待望の<a class="keyword" href="http://d.hatena.ne.jp/keyword/SuperCollider">SuperCollider</a> 3.3.1 for <a class="keyword" href="http://d.hatena.ne.jp/keyword/windows">windows</a>がリリースされました。<br /> MouseX,MouseYが使えるようになったなどの変更があります。あと、helpブラウザがかなり使い易いです。詳細な変更点は<a href="http://supercollider.svn.sf.net/viewvc/supercollider/trunk/common/build/ChangeLog?revision=9692">&#x3053;&#x3061;&#x3089;</a>を参照して下さい。<br /> インストールする際に、ちょっと迷う箇所があります。以前のバージョンである3.3winalpha6などがインストールされていると、3.3.1をインストールする際に、別のバージョンの製品が……と怒られます。で、プログラムの追加と削除から削除しようと見てみると私の環境では見当たらず……。すわ、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%C8%A5%EA">レジストリ</a>かとか思って削除してもダメ。<br /> 以前のバージョンを削除する場合は、そのバージョンの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%C8%A1%BC%A5%E9">インストーラ</a>を立ち上げてremoveで削除出来ます。<br /> 5分ほどハマりました。インストールするときにイラッとしないようにここに書いておきます。</p> sc3onlinux SuperCollider Collectionについて hatenablog://entry/17680117127138691621 2010-02-17T23:58:53+09:00 2019-05-17T20:20:46+09:00 はじめに 本文はプレビューです。うまくまとめられたら、書き直します。以下、嘘を書いているかもしれませんし、結局helpの日本語注釈付きになってしまっていますので参考にならないと思います。途中で挫折していますし。ただ、helpの日本語注釈付きなんてすばらしいものは、それはそれでめちゃめちゃ需要ありそうですけれどね。ま、helpを翻訳する気なんざさらさらないですけれど。 以下、こんな感じで /* 本テキストでは、Collectionオブジェクトをコレクションと記載します。 スパコでのコレクションとはオブジェクトの集合を指し、CollectionクラスのサブクラスにArray,Listなどなどがあり… <div class="section"> <h4>はじめに</h4> <p>本文はプレビューです。うまくまとめられたら、書き直します。以下、嘘を書いているかもしれませんし、結局helpの日本語注釈付きになってしまっていますので参考にならないと思います。途中で挫折していますし。ただ、helpの日本語注釈付きなんてすばらしいものは、それはそれでめちゃめちゃ需要ありそうですけれどね。ま、helpを翻訳する気なんざさらさらないですけれど。</p> </div> <div class="section"> <h4>以下、こんな感じで</h4> <p>/*<br /> 本テキストでは、Collectionオブジェクトをコレクションと記載します。<br /> スパコでのコレクションとはオブジェクトの集合を指し、CollectionクラスのサブクラスにArray,Listなどなどがあります。コレクションの子に配列があるといった認識になります。<br /> まず、つまづく点にArrayとListの違いがあります。Arrayは最大サイズが固定なので、はじめに定義したサイズを超えた要素は廃棄されます。Listはサイズが固定ではないため廃棄されず挿入されます。//おそらくこんな感じです、私はまだ詳しく理解出来ていません。<br /> Array,ListともにCollection,SequenceableCollectionのサブクラスですのでこれらのメソッドは使用できますが、ArrayのメソッドはListでは使えません。ただし、同じだったり似たようなメソッドが多々ありますのでごっちゃになりがちです。親子関係を明確にしておかないと死ぬかもしれません。<br /> */</p> </div> <div class="section"> <h4>Collection</h4> <p>/*<br /> 一番の親クラスはCollectionなので、メソッドは一通り押さえておきましょう<br /> */</p> <div class="section"> <h5>Class Methods:</h5> <pre class="code" data-lang="" data-unlink>*newFrom(collection) Creates a new Collection from another collection. This supports the interface for the mathod &#34;as&#34; //別のコレクションからコレクションを作成 Array.newFrom(Set[4, 2, 1]); //[ 2, 4, 1 ] , setオブジェクトからArrayオブジェクトを作成 Set.newFrom(Array[4, 2, 1]); //Set[ 2, 4, 1 ], ArrayオブジェクトからSetオブジェクトを作成 [1, 2, 3, 4, 3, 2].as(Set); // as(someClass) calls someClass.newFrom(this) *with(collection) Creates a new Collection from the args. //要素に引数を代入したコレクションを作成 Array.with(4, 2, 1); //[ 4, 2, 1 ] *fill(size, function) Creates a Collection of the given size, the elements of which are determined by evaluation the given function. The function is passed the index as an argument. //コレクションのサイズを定義し、関数の戻り値を要素に代入したコレクションを作成。関数の引数にはインデックス番号が渡されます Array.fill(4, { arg i; i * 2 }); //[ 0, 2, 4, 6 ] 、引数に渡されるインデックス番号は、0, 1, 2, 3になります</pre> </div> <div class="section"> <h5>Accessing:</h5> <pre class="code" data-lang="" data-unlink>size Answers the number of objects contained in the Collection. //コレクションのサイズを返す List[1, 2, 3, 4].size; //4 isEmpty Answer whether the receiver contains no objects. //コレクションが要素を持っていないならばtrueを返す List[].isEmpty; //true</pre> </div> <div class="section"> <h5>Adding and Removing:</h5> <pre class="code" data-lang="" data-unlink>add(anObject) Add anObject to the receiver. //anObjectをレシーバに追加。 //レシーバとはドット(.)の前に記述するオブジェクトを指します。レシーバ.メソッド()と書きます。 //これはメソッド呼び出し記法なんですかね?ドットシンタックスじゃないのかな・・・・・・ List[1, 2].add(3); //List[ 1, 2, 3 ] addAll(aCollection) Add all items in aCollection to the receiver. //aCollectionの要素をレシーバに追加 List[1, 2].addAll(List[3, 4]); //List[ 1, 2, 3, 4 ] remove(anObject) Remove anObject from the receiver. Answers the removed object. //レシーバからanObjectを削除 ( var a; a = List[1, 2, 3, 4]; a.remove(3); a; ) //List[ 1, 2, 4 ] removeAll(aCollection) Remove all items in aCollection from the receiver. //aCollectionの要素をレシーバから削除 List[1, 2, 3, 4].removeAll(List[2, 3]); //List[ 1, 4 ] Note that multiple items in the receiver will not necessarily be removed: //レシーバの要素が全て削除されるわけではない、全て削除はremoveEvery ~closet = [\hat, \hat, \hat, \coat, \coat, \shoe, \shoe]; ~closet.removeAll([\hat, \coat, \shoe, \shoe]); //[ hat, hat, coat ]  Doesn&#39;t empty the closet, just removes what we wanted to See removeEvery (below) for a related method that removes all occurrences. removeEvery(aCollection) Remove all occurrences of the items in aCollection from the receiver. //レシーバからaCollectionの要素を全て削除 List[1, 2, 3, 2, 3, 2, 3, 4].removeEvery(List[2, 3]); //List[ 1, 4 ] 2,3を全て削除 removeAllSuchThat(function) Remove all items in the receiver for which function answers true. The function is passed two arguments, the item and an integer index. Answers the objects which have been removed. //レシーバから関数の戻り値を削除 ( var a; a = List[1, 2, 3, 4]; a.removeAllSuchThat({ arg item, i; item &lt; 3 }); a; ) //List[ 3, 4 ] , 3より小さい要素を削除 putEach(keys, values) Put the values in the corresponding indices given by keys. If one of the two argument arrays is longer then it will wrap. //レシーバのkeysで指定したインデックスに valuesを追加、引数のいずれかが配列ならそれを追加 y = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; //[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] y.putEach([4, 7], [\smelly, \head]) //[ 0, 1, 2, 3, smelly, 5, 6, head, 8, 9 ] , 4個目と7個目にsmelly,headを追加 y.putEach([2, 3, 5, 6], \wotsits); //[ 0, 1, wotsits, wotsits, smelly, wotsits, wotsits, head, 8, 9 ] , 2,3,5,6個目にwotsistsを追加 atAll(keys) return a collection of all the items for the keys. //レシーバの要素からkeysインデックス番号のものを抜き出す y = [\a, \b, \c]; //[ a, b, c ] y.atAll([0, 2]) //[ a, c ]</pre> </div> </div> <div class="section"> <h4>ArrayCollection</h4> <div class="section"> <h5>Class Methods</h5> <pre class="code" data-lang="" data-unlink>*with(... args) Create a new ArrayedCollection whose slots are filled with the given arguments. //argで埋めた新しい配列を作成 Array.with(7, &#39;eight&#39;, 9).postln; //[ 7, eight, 9 ] *series(size, start, step) Fill an ArrayedCollection with an arithmetic series. //等差級数で埋めた新しい配列、startからstepづつ増やした数値をsize分の要素で配列を作成 Array.series(5, 10, 2).postln; //[ 10, 12, 14, 16, 18 ] *geom(size, start, grow) Fill an ArrayedCollection with a geometric series. //等比級数で埋めた新しい配列、startからgrow倍の数値をsize分の要素で配列を作成 Array.geom(5, 1, 3).postln; //[ 1, 3, 9, 27, 81 ] *iota(...sizes) Fills an ArrayedCollection with a counter. See J_concepts_in_SC for more examples. //iota(a, b, c, d)ならd個の要素をもった配列がc個あり、そのc個の配列がb個あり、そのb個の配列がa個ある配列を作成、要素は0からカウントアップ //[ [ [ [ d個 ] がc個 ] がb個 ] がa個 ]分かりにくいけれど、こんな感じです。 Array.iota(2, 3); //[ [ 0, 1, 2 ], [ 3, 4, 5 ] ] 3個の要素を持った配列が2個 Array.iota(2, 3, 4); //[ [ [ 0, 1, 2, 3 ], [ 4, 5, 6, 7 ], [ 8, 9, 10, 11 ] ], [ [ 12, 13, 14, 15 ], [ 16, 17, 18, 19 ], [ 20, 21, 22, 23 ] ] ] *fill2D(rows, cols, function) Creates a 2 dimensional ArrayedCollection of the given sizes. The items are determined by evaluation of the supplied function. The function is passed row and column indexes as arguments. See J_concepts_in_SC //2次元配列を作成、rows個の要素を持った配列をcols個作成し要素はfunctionで代入 Array.fill2D(2, 4, 0); //[ [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ] ] Array.fill2D(3, 4, { arg r, c; r*c+c; }); //[ [ 0, 1, 2, 3 ], [ 0, 2, 4, 6 ], [ 0, 3, 6, 9 ] ] *fill3D(planes, rows, cols, function) Creates a 3 dimensional ArrayedCollection of the given sizes. The items are determined by evaluation of the supplied function. The function is passed plane, row and column indexes as arguments. See J_concepts_in_SC //fill2Dの3次元版 Array.fill3D(2, 3, 4, { arg p, r, c; p; }); *fillND(dimensions, function) Creates a N dimensional ArrayedCollection where N is the size of the array dimensions. The items are determined by evaluation of the supplied function. The function is passed N number of indexes as arguments. //多次元版 Array.fillND([4, 4], { arg a, b; a+b; }); //2d Array.fillND([4, 4, 4], { arg a, b, c; a+b*c; }); //3d Array.fillND([1, 2, 3, 4], { arg a, b, c, d; b+d; }); //4d</pre> </div> </div> <div class="section"> <h4>とまあこのように</h4> <p>つらつらhelpを見ていますが、よくわからないメソッドがごちゃごちゃとあります。自分の使いそうなクラス、メソッドは理解して意訳する必要はありそうですね。</p> </div> sc3onlinux SuperCollider基礎文法最速マスター hatenablog://entry/17680117127138691759 2010-02-06T18:37:56+09:00 2019-05-17T20:20:47+09:00 SuperColliderの文法一覧です。他の言語をある程度知っている人がこれを読めばSuperColliderの基礎をマスターしてSuperColliderを書くことができるようになれると良いですね。簡易リファレンスとしても利用できたら良いですね。無理ですか、そうですよね。 これを読んでもスパコでシンセ、シーケンスが書けますか?いいえ、書けません。さらに細かいことを知る必要があります。また、SuperColliderはそこそこ難しい部類に入ると思います。柔軟性が高く、他人のコードを読んでもわけが分からなかったりします。 更新履歴 2010/11/27 修正、追記 2010/09/25 間違い… <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/SuperCollider">SuperCollider</a>の文法一覧です。他の言語をある程度知っている人がこれを読めば<a class="keyword" href="http://d.hatena.ne.jp/keyword/SuperCollider">SuperCollider</a>の基礎をマスターして<a class="keyword" href="http://d.hatena.ne.jp/keyword/SuperCollider">SuperCollider</a>を書くことができるようになれると良いですね。簡易リファレンスとしても利用できたら良いですね。無理ですか、そうですよね。<br /> これを読んでもスパコでシンセ、シーケンスが書けますか?いいえ、書けません。さらに細かいことを知る必要があります。また、<a class="keyword" href="http://d.hatena.ne.jp/keyword/SuperCollider">SuperCollider</a>はそこそこ難しい部類に入ると思います。柔軟性が高く、他人のコードを読んでもわけが分からなかったりします。<br /> <br /> </p> <div class="section"> <h4>更新履歴</h4> <p>2010/11/27</p> <ul> <li>修正、追記</li> </ul><p>2010/09/25</p> <ul> <li>間違い削除</li> </ul><p>2010/02/14 19:00</p> <ul> <li>文字列部分にシンボルなど追記</li> <li>制御文に、do,switch文追加</li> </ul><p>2010/02/06 23:00<br /> tn8さんに指摘していただいた</p> <ul> <li>小文字で変数宣言しない場合はグルーバル変数</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/SuperCollider">SuperCollider</a>の記述</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/mac">mac</a>における<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>の実行コマンド</li> </ul><p>を修正<br /> 2010/02/06 18:00<br /> 新規</p> </div> <div class="section"> <h4>基礎の前に</h4> <p>基礎の前に<br /> まずはその複雑さを確認しましょう。<br /> max(a, b)<br /> a.max(b)<br /> は同じです。<br /> g(f(a, b), c)<br /> g(a.f(b), c)<br /> f(a, b).g(c)<br /> a.f(b).g(c)<br /> これらも同じです。<br /> 複数の記述方法に対応しているのが、SCの特徴といえます。SCは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%D6%A5%B8%A5%A7%A5%AF%A5%C8%BB%D8%B8%FE%B8%C0%B8%EC">オブジェクト指向言語</a>です。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%D6%A5%B8%A5%A7%A5%AF%A5%C8%BB%D8%B8%FE%B8%C0%B8%EC">オブジェクト指向言語</a>は、おおまかに<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%B8%C0%B8%EC">C言語</a>形、<a class="keyword" href="http://d.hatena.ne.jp/keyword/smalltalk">smalltalk</a>形に分けられます。基本的には<a class="keyword" href="http://d.hatena.ne.jp/keyword/smalltalk">smalltalk</a>形ですが、SCはどちらにも対応しています。そのため、多彩な記述方法がありスパコはややこしいのです。以下は、helpのSyntax Shortcutsの例になります。なんと全て意味は同じなんですよ。</p> <pre class="code" data-lang="" data-unlink>// new argument syntax (1..10).collect({|n| n.squared }); // receiver syntax collect((1..10), {|n| n.squared }); // function call syntax (1..10).collect {|n| n.squared }; // receiver syntax with trailing function arg collect ((1..10)) {|n| n.squared }; // function call syntax with trailing function arg (1..10) collect: {|n| n.squared }; // binary operator syntax // partial application syntax (1..10).collect( _.squared ); // receiver syntax collect((1..10), _.squared ); // function call syntax (1..10) collect: _.squared ; // binary operator syntax</pre> </div> <div class="section"> <h4>基礎</h4> <div class="section"> <h5>print文</h5> <pre class="code" data-lang="" data-unlink> &#34;Hello world&#34;;// 単に出力ならこれで出ます。 &#34;Hello world&#34;.post;// 改行なし &#34;Hello world&#34;.postln;// 改行あり postln(&#34;Hello world&#34;);// この書き方でも出力できます。 //ex) 100;// -&gt;100 100.post;200.postln;// -&gt;100 200\n 200 &#34;super collider&#34;.speak; //音響言語らしく、文字出力ではなく音出力。すーぱーこらーいだー /* Hello world Hello world と何故か2行出力されました。仕様です。スパコでは最終実行結果が常に出力されます。 */ </pre> </div> <div class="section"> <h5>コメント</h5> <pre class="code" data-lang="" data-unlink>//でコメント一行 /* で複数行コメント */ /* コメントの中に /* コメントを入れられます */ いれられます */</pre> </div> <div class="section"> <h5>変数の宣言</h5> <pre class="code" data-lang="" data-unlink> // ローカル変数はvarで宣言します // ローカルなので、ブロック内、関数内でのみ使用可能です。ブロック、関数は()や{}囲みになります。 var myLocalVar = 1; myLocalVar.postln; // -&gt;1 myLocalVar.postln; // ERROR: 定義されていません // グローバル変数は〜で宣言します。 ~myGrobalVar = 10; ~myGrobalVar.postln; // -&gt;10 // 小文字一文字でvar宣言しないとグローバル変数として定義されます。 b=2; b.postln; //-&gt;2 </pre> </div> <div class="section"> <h5><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>の実行</h5> <pre class="code" data-lang="" data-unlink> // 1行実行(mac: enter, ctl-c, ctl-return, shift-return), (emacs:C-c C-c), (win: ctl+enter) {SinOsc.ar(440)}.play; ( // 複数行実行は実行したい部分を選択し(mac: enter, ctl-c, ctl-return, shift-return), (emacs:C-c C-c), (win: ctl-enter) //(か)の後ろをダブルクリックで()内を選択できます。(mac: shift-cmd-bでもおkです) { SinOsc.ar(440) + SinOsc.ar(880) }.play ) </pre> </div> </div> <div class="section"> <h4>数値</h4> <div class="section"> <h5>数値の表現</h5> <pre class="code" data-lang="" data-unlink> // 数値の表現 var num = 1;num; // int型として扱われる var num = 1.1;num; // float型として扱われる var num = 16rF0;num; // 16進数 var num = 2r01101011;num; // バイナリ // 四則演算 var num = 1+1;num; var num = 1-1;num; var num = 1*2;num; var num = 3/2; num; // 商と余り、累乗 var num = floor(3/2); num; // 商はfloorで切り捨てます var num = (3/2).floor; num; // 同様に商 var num = 3%2; num; // 余り var num = 3**2; num; // 累乗 // インクリメントとデクリメント もしかしてない? +=とか代入演算子もないです。 // ビット演算 var num = 1&amp;1; num; // and var num = 1|1; num; // or var num = 1&lt;&lt;1; num; // 左シフト var num = 11&gt;&gt;1; num; // 右シフト var num = 11+&gt;&gt;1; num; // ? // 関係演算 1==1; // 同等 1===1; // 同一 1!=2; // 非同等 1!==2; // 非同一 1&lt;2; // 小なり 1&lt;=2; // 小なりイコール 1&gt;2; // 大なり 1&gt;=2; // 大なりイコール true &amp;&amp; false; // 論理積 true || false; // 論理和</pre> </div> </div> <div class="section"> <h4>文字列</h4> <div class="section"> <h5>文字列の表現</h5> <pre class="code" data-lang="" data-unlink> /* シングルクォート、ダブルクォートで囲みます。 ダブルクォートの中では\t(タブ)や\n(改行)などの特殊文字を利用することができます。 ダブルクォートで囲むと文字列、シングルクォートで囲むとシンボル。シンボルは\symbolとも書けます。 $を頭に付けると文字。 文字列とは文字の配列、集合を表しています。シンボルとは単一のものになりますので後述の操作はできません。 */ $A // 文字 &#39;abc&#39; // シンボル \abc // こちらもシンボル &#34;a\tb\nc&#34; // 文字列</pre> </div> <div class="section"> <h5>文字列操作</h5> <p>//文字列は文字の配列のことですので、次項の配列操作が可能です。</p> <pre class="code" data-lang="" data-unlink> // 文字列は文字の配列のことですので、次項の配列操作が可能です。 // 結合 (&#34;aaa&#34;+&#34;bbb&#34;).postln; // スペース有り結合 aaa bbb (&#34;aaa&#34;++&#34;bbb&#34;).postln; // スペース無し結合 aaabbb // 分割 &#34;aaa/bbb/ccc&#34;.split.postln; // デフォルトセパレータは/ &#34;aaa@bbb@ccc&#34;.split($@).postln; // セパレータは任意のchar、ここでは@ // 長さ (&#34;aaa&#34;).size.postln; // -&gt;3 // 切り出し &#34;abcdef&#34;.at(2).postln; // -&gt;c // 検索 &#34;abcdef&#34;.find(&#34;c&#34;).postln; // -&gt;2 indexを返す &#34;abcdefc&#34;.findAll(&#34;c&#34;).postln; // -&gt;[2, 6] // 置換 &#34;abcdefg&#34;.replace(&#34;abc&#34;,&#34;aaa&#34;); // シンボルはこのような操作ができない &#39;abc&#39;.at(2).postln; // error // 上記基本操作だけでなく、Stringクラスのメソッドは沢山あり、一通りなんでも操作可能です </pre> </div> </div> <div class="section"> <h4>配列</h4> <p>スパコでは配列が非常に重要になってきます。配列の要素を遷移させつつ読み込むことでパターン<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A1%BC%A5%B1%A5%F3%A5%B5%A1%BC">シーケンサー</a>が作れたりします。またList,Array,Dictionaryなどのオブジェクトが配列としてありますが、ここではArrayのみにしています。</p> <div class="section"> <h5>配列変数の宣言と要素の代入と参照</h5> <pre class="code" data-lang="" data-unlink>//配列の生成 var myArray = Array.new(10); // 最大サイズを指定して生成(ただし、サイズ指定はあまり意味ない) var myArray = Array.with(1,2,3); myArray; // 要素に代入して生成 var myArray = Array.series(10, 1, 2); myArray; // 等差数列、series(size,start,step) var myArray = Array.fill2D(2, 4, 1); myArray; // 2*4の2次元配列生成、3次元、多次元もあります var myArray = [1,2,3]; // 変数に配列を代入して生成 //要素の代入、参照 // 一行づつ確認出来るようグローバル変数にしてます ~myArray = Array.new(10); // 新規配列生成 ~myArray.add(1); // index0に1を代入 ~myArray.extend(10,2); // 指定サイズまで要素を代入 ~myArray.at(1); // indexを指定して参照 ~myArray[2]; // こちらもindexを指定して参照</pre> </div> <div class="section"> <h5>配列の操作</h5> <pre class="code" data-lang="" data-unlink> // 取り出し ~myArray = Array.with(1,2,3); // 新規配列生成 ~myArray.removeAt(1); // index1を取り出す ~myArray;// -&gt;[1, 3] // 多くの言語がshiftメソッドで取り出しですが、SCのshiftは挙動が違います。 ~myArray = Array.with(1,2,3); // Array.withで要素代入済みの配列定義 ~myArray.shift(2); // -&gt;[0, 0, 1] 2要素右へシフト、移動分の要素は0に // 追加 ~myArray = [1,2,3]; // 新規配列 ~myArray.insert(1,10); // index1に10を代入 ~myArray.add(11); // 末尾に追加。ただし、新規配列が返されるためmyArrayは変化無し ~myArray; // 追加されていない ~myArray.addFirst(100); // 先頭に追加 // 置換 ~myArray = [1,2,3]; // 新規配列 ~myArray.put(1,100); // index1を100に置換 ~myArray.clipPut(10,200); // index10を200に置換。最大サイズ超過時は末尾を置換 ~myArray.wrapPut(5,300); // 最大サイズ超過時は、最初から数え直す ~myArray.foldPut(5,400); // 折り返す ~myArray.fill(2); // 全て置換 // 並べ替え ~myArray = [1,2,3]; // 新規配列 ~myArray.reverse; // 逆 ~myArray.scramble; // スクランブル // その他 ~myArray = [1,2,3]; // 新規配列 ~myArray.mirror; // 中心を軸にコピー ~myArray.stutter(2); // 要素を引数値だけ繰り返す ~myArray.rotate(1); // ずらす</pre> </div> </div> <div class="section"> <h4>制御文</h4> <p>他の言語とちょい違います。</p> <div class="section"> <h5>if文</h5> <pre class="code" data-lang="" data-unlink> /* if(条件, 真の時, 偽の時); もしくは 条件.if(真の時, 偽の時); */ if(true,1,2);  // -&gt;1 false.if(1,2); // -&gt;2</pre> </div> <div class="section"> <h5>while文</h5> <pre class="code" data-lang="" data-unlink> /* while(条件,関数); もしくは 条件.while(関数); */ ( i=0; while( {i&lt;5}, { i=i+1; i.postln; } ) )</pre> </div> <div class="section"> <h5>for文</h5> <pre class="code" data-lang="" data-unlink> /* for(開始, 最後, 関数); もしくは 開始値.for(終了値,関数); 反復値が関数の引数として渡されます。 */ for(1, 10, {arg i; i.postln; }); // 1から10まで出力(1から順に関数へ渡されています) 1.for(10, {arg i; i.postln; }); // 上と同じ結果</pre> </div> <div class="section"> <h5>forby文</h5> <pre class="code" data-lang="" data-unlink> /* forBy(開始値, 終了値, ステップ値, 関数); もしくは 開始値.forBy(終了値,ステップ値,関数); 開始値から終了値までステップ値づつ増えます。 */ forBy(1, 10, 2, {arg i; i.postln; }); //2づつ増加</pre> </div> <div class="section"> <h5>Do文</h5> <pre class="code" data-lang="" data-unlink> /* do(コレクション,関数); もしくは コレクション.do(関数); ここでのコレクションとは[ ]で括った集合のことです。 n回繰り返すための制御文として主に使われる、コレクションを反復処理するための制御文でもあります。 コレクションの頭から順に、関数の第1引数へ渡されます。コレクションではなく単に整数nにするとゼロからnまで繰り返します。 関数に引数が二つあれば、第2引数は繰り返しのカウンタ値となります。 */ do([ &#34;a&#34;,1,10,&#39;b&#39;] , {arg item; item.postln; } ); // -&gt;a 1 10 b do(5, {arg item; item.postln; }); //-&gt; 0 1 2 3 4,最後に5が出力されるが仕様 ( 5 .. 10 ).do( {arg i, counter; [i , counter].postln; }); // -&gt;[5.0] [6.1] [7,2] [8,3] [9,4] [10.5], こちらの書き方が一般的。</pre> </div> <div class="section"> <h5>Switch文</h5> <pre class="code" data-lang="" data-unlink> /* switch( 変数, 定数1, 定数1の時, 定数2, 定数2の時,・・・ ); case文なるものもあります。 */ ( var x=2.rand; // xは0か1 switch(x, 0, { &#34;x == 0&#34; }, 1, { &#34;x == 1&#34; } ); ) </pre> </div> </div> <div class="section"> <h4>関数</h4> <pre class="code" data-lang="" data-unlink> // {}で括ったものが関数となる // argは引数、varは変数 ~myFunction = { arg a; var b = 1; a + b; }; ~myFunction.value(1); // -&gt;2 valueメソッドで引数にアクセス // 引数は| | でも書けます。 ~myFunction = { |a=1| var b = 1; a+b; }; ~myFunction.value; // -&gt;2 // 引数で... bのように書くと配列と見なされます。 ~myFunction = { arg ... a; a; }; ~myFunction.value(1,2,3,4,5,6); // -&gt;[1,2,3,4,5,6]</pre> </div> <div class="section"> <h4>ファイル入出力</h4> <p>ここでは、とりあえずテキストのみ。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B5%A5%A6%A5%F3%A5%C9">サウンド</a>の読み込みを書くと操作も書くことになるので。</p> <pre class="code" data-lang="" data-unlink>//ファイル書き込み ( var f, g; f = File(&#34;test&#34;,&#34;w&#34;); f.write(&#34;Does this work?\n is this thing on ?\n&#34;); f.close; ) //ファイル書き込み ( g = File(&#34;test&#34;,&#34;r&#34;); g.readAllString.postln; g.close; )</pre> </div> <div class="section"> <h4>いじょう</h4> <p>スパコは難しいです。ヘルプファイルは充実していますが、英語がよくわからないです。<br /> とりあえず<a href="http://d.hatena.ne.jp/gifnksm/20100202/1265105961">&#x4ED6;&#x306E;&#x6700;&#x901F;&#x30DE;&#x30B9;&#x30BF;&#x30FC;</a>に従って書いてあります。かなり省いた部分がありますので加筆していくかもしれません。もちろん間違っているところなど指摘していただければ修正します。しないかもしれません。<br /> どう見ても見にくいので、sc.jpにrtfファイルを置かせていただいています。出来ればこちらをSCで開いて見てください。<a href="http://supercollider.jp/modules/bwiki/index.php?Tips">&#x30B9;&#x30D1;&#x30B3;wiki</a>の文法です。</p> </div> sc3onlinux