Ssaw08 0701

26
SSAW08 第10回 ChucK入門 2008年7月1日

Transcript of Ssaw08 0701

Page 1: Ssaw08 0701

SSAW08 第10回

ChucK入門2008年7月1日

Page 2: Ssaw08 0701

今日の内容

• ChucKを使ってみる• Max/MSP・Pd、SuperColliderとはまた別の音響合成/分析用の言語• 2004年に公表• 現在も開発が続いている、最新のコンピュータ音楽用言語の一つ

Page 3: Ssaw08 0701

ChucKとは

• Ge Wang と Perry Cookにより開発 (2004年)• リアルタイム音響合成、作曲、パフォーマンス、音響分析といった用途に特化したプログラミング言語

• Mac OSX, Windows, Linuxで使用可能• フリーソフト (GNU General Public License)

Page 4: Ssaw08 0701

ChucKの特徴

• 時間軸にそって正確にコントロールされる (Strongly Timed)• 読み易く、メンテナンスし安い言語設計• オープンソース、クロスプラットフォーム(OSX, Windows, Linux)• オブジェクト指向言語 (OOP)• 並列プログラミングモデル (concurrent proguramming model)• Chuck演算子 => • ライブコーディング• MIDIを利用可能• OpenSoundControlを利用可能• Synthesis Toolkit (STK) が利用可能• 物理モデルを利用した高度な音響合成• フルート• マリンバ• 声• …etc.

Page 5: Ssaw08 0701

ChucKとminiAudicle

• ChucKでの開発の流れ• テキストエディタを用いてプログラムを作成• コマンドラインで実行• % chuck hoo.ck

• miniAudicle• ChucKの統合開発環境• midiAudicle単体で一括した開発が可能• ChucKのプログラムの作成• 実行• ライブコーディング• パフォーマンス• GUIの開発

Page 6: Ssaw08 0701

ChucKとminiAudicle

• miniAudicle

Page 7: Ssaw08 0701

miniAudicleのインストール

• miniAudicleのWebページから、使用したいOSにあわせてアプリケーションをダウンロードする• miniAudicle (http://audicle.cs.princeton.edu/mini/)

Page 8: Ssaw08 0701

ChucK演算子 =>

=>• ChucK独自の演算子• 左から右へ値を接続する• 単純なChucK接続: x => y;• Chuckのチェーン:w => x => y => z;• ChucKのネスト:w => ( x => y ) => z;• ChucK接続の解除 (un-chuck):x =< y =< z;

Page 9: Ssaw08 0701

//Sin波の生成

//Sin波を生成するUG SinOscの出力をDACに接続SinOsc s => dac;

//周波数を440Hzに440 => s.freq;

//1秒間音を生成1::second => now;

簡単なプログラムを実行してみる 1

Page 10: Ssaw08 0701

/* 複数のSin波を順番に */

//Sin波の出力をDACにSinOsc s => dac;

//440Hzで1秒間生成440 => s.freq;1::second => now;

//880Hzで0.5秒間生成880 => s.freq;.5::second => now;

//220Hzで2秒間生成220 => s.freq;2::second => now;

簡単なプログラムを実行してみる 2

Page 11: Ssaw08 0701

/* 複数のSin波をループ */

//Sin波の出力をDACにSinOsc s => dac;

//くりかえしwhile(true){ 440 => s.freq; 1::second => now;

880 => s.freq; .5::second => now;

220 => s.freq; 2::second => now;}

簡単なプログラムを実行してみる 3

Page 12: Ssaw08 0701

/* 複数のSin波をループ */

//Sin波の出力をDACにSinOsc s => dac;

//くりかえしwhile(true){ //ランダムな周波数(30 < freq < 1000)を生成 Std.rand2f(30,1000) => s.freq; //100ミリ秒生成 100::ms => now;}

簡単なプログラムを実行してみる 4

Page 13: Ssaw08 0701

//オーディオ信号の流れ (Sin波 => リバーブ => DAC)SinOsc s => JCRev r => dac;

// 全体の音量を調整.5 => s.gain;

// リバーブのミックスを調整.2 => r.mix;

// ピッチの配列を生成[ 0, 4, 7, 11 ] @=> int note[];

// 無限ループwhile( true ){ // ノートを選択 Std.mtof(Std.rand2(1,3)*12 + 48 + note[Std.rand2(0,note.cap()-1)] ) => s.freq; // 120msで生成 120::ms => now;}

プログラム例:配列の利用

Page 14: Ssaw08 0701

SinOsc s => ADSR e => JCRev r => dac; //オーディオ信号の流れe.set( 1::ms, 60::ms, .3, 60::ms ); //エンベロープを設定.5 => s.gain; // 全体の音量を調整.2 => r.mix; // リバーブのミックスを調整[ 0, 4, 7, 11 ] @=> int note[]; // ピッチの配列を生成while( true ) // 無限ループ{ // ノートを選択 Std.mtof(Std.rand2(1,3)*12 + 48 + note[Std.rand2(0,note.cap()-1)] ) => s.freq;

e.keyOn(); //ノートオン 120::ms => now; // 120ms生成 e.keyOff(); //ノートオフ 60::ms => now; //60ms休止}

プログラム例:ADSRエンベロープ

Page 15: Ssaw08 0701

// FM合成SinOsc m => SinOsc c => dac;

while( true ){ // キャリア周波数 Std.rand2(100,1000) => float cf => c.freq; // モジュレータ周波数 Std.rand2(40,100) => m.freq; // インデックス値 Std.rand2(100,5000) => m.gain; //1000ms生成 1000::ms => now;}

プログラム例:FM変調

Page 16: Ssaw08 0701

// STK Flute (へたくそフルート)Flute flute => PoleZero f => ADSR e => JCRev r => dac;e.set( 200::ms, 100::ms, 0.8, 100::ms );.75 => r.gain;.1 => r.mix;1 => f.blockZero;

while( true ){ flute.clear( 1.0 ); Std.rand2f( 0, 1 ) => flute.jetDelay; Std.rand2f( 0, 1 ) => flute.jetReflection; Std.rand2f( 0, 1 ) => flute.endReflection; Std.rand2f( 0, 1) => flute.noiseGain; Std.rand2f( 0, 12 ) => flute.vibratoFreq; Std.rand2f( 0, 1 ) => flute.vibratoGain; Std.rand2f( 0, 1 ) => flute.pressure; Std.mtof( Std.rand2(60,90) ) => flute.freq; e.keyOn(); Std.rand2f( .6, .9 ) => flute.noteOn; Std.rand2(200, 2000)::ms => now;}

プログラム例:STK - (へたくそ)フルート

Page 17: Ssaw08 0701

Chuck + OpenSoundControl

• ChuckでもOpenSoundControlの送受信機能を利用可能• OSCを利用できる他のアプリケーションと相互に通信可能• Chuck ←→ Processing (+ OscP5)• Chuck ←→ Flash (+ flosc)• Chuck ←→ Max/MSP, Jitter• Chuck ←→ SuperCollider • …etc.

Page 18: Ssaw08 0701

Chuck と Prosessingの連携

• OSCを介して、ChucKとProcessingを連携してみる• ChucKからProcessingへOSCを送信して画像生成• ProcessingからChucKにOSCを送信して音響との同期

ChucK

ChucK Processing

OSC

Page 19: Ssaw08 0701

OSC 1:ChucK → Processing

• ChuckからOSCメッセージを送信して、Processingで図形を描画する• OSCメッセージの構成• /draw (float)

ChucKChucK Processing

OSC

Page 20: Ssaw08 0701

//ChucK側SinOsc s => dac; //Sin波をDACに接続0.5 => s.gain; //音量を設定//送信先のipとportを設定"localhost" => string hostname; 12000 => int port;OscSend xmit; //オブジェクトを初期化xmit.setHost( hostname, port ); //ホストを設定while( true ){ //OSCメッセージのスタート - メッセージ名:draw, データ型:float xmit.startMsg( "/draw", "f" ); Std.rand2f( 50, 1000 ) => float freq; //ランダムな周波数を設定 freq => s.freq; //サイン波の周波数に freq * 0.1 => xmit.addFloat; //OSCの値を設定 200::ms => now; //200ms生成}

OSC 1:ChucK → Processing

Page 21: Ssaw08 0701

//Processing側import oscP5.*;import netP5.*;OscP5 oscP5;void setup() { size(400,400); colorMode(HSB, 360, 100, 100, 100); frameRate(30); noStroke(); smooth(); background(0,0,0,100); frameRate(30); oscP5 = new OscP5(this, 12000);}void draw(){}void oscEvent(OscMessage msg){ println(msg); if(msg.checkAddrPattern("/draw") == true){ float value = msg.get(0).floatValue(); fill(random(360), random(50,100), random(50,100), 50); ellipse(random(width), random(height), value, value); }}

OSC 1:ChucK → Processing

Page 22: Ssaw08 0701

OSC 2:Processing → ChucK

• Processingをユーザインターフェイスとして使用• マウスクリックでOSCを送信• タイミングを同期させてChucKで音響を生成

ChucKChucKProcessing

OSC

Page 23: Ssaw08 0701

//Chuck側SinOsc s => ADSR e => JCRev r => dac;e.set( 1::ms, 100::ms, 0.3, 1000::ms);.2 => r.mix;

OscRecv recv;12000 => recv.port;

recv.listen();recv.event( "/chuck, f" ) @=> OscEvent oe;

while ( true ){ oe => now; while ( oe.nextMsg() != 0 ) { 0.5 => s.gain; oe.getFloat() => s.freq; e.keyOn(); }}

OSC 2:Processing → ChucK

Page 24: Ssaw08 0701

//Processing側import oscP5.*;import netP5.*;OscP5 oscP5;NetAddress myRemoteLocation;Ring[] rings;int numRings = 50;int currentRing = 0;int synthId = 1000;void setup() { size(800, 800); colorMode(HSB, 360, 100, 100, 100); frameRate(30); oscP5 = new OscP5(this,12000); myRemoteLocation = new NetAddress("127.0.0.1",12000); colorMode(HSB, 360, 100, 100, 100); smooth(); rings = new Ring[numRings]; for(int i = 0; i < numRings; i++){ rings[i] = new Ring(); }}void draw(){ background(0); for(int i = 0; i < numRings; i++){ rings[i].grow(); rings[i].display(); }}

OSC 2:Processing → ChucK

Page 25: Ssaw08 0701

void mousePressed(){ OscMessage myMessage = new OscMessage("/chuck"); myMessage.add(float(height - mouseY)); oscP5.send(myMessage, myRemoteLocation); println(myMessage); synthId++; rings[currentRing].start(mouseX, mouseY); currentRing++; if(currentRing >= numRings){ currentRing = 0; }}

OSC 2:Processing → ChucK

Page 26: Ssaw08 0701

class Ring { float x, y; float diameter; boolean on = false; color col; void start(float _x, float _y){ x = _x; y = _y; on = true; diameter = 1; col = color(random(360), 50, 100, 50); } void grow() { if(on) { diameter++; if(diameter > 1000){ on = false; } } } void display(){ if(on){ noFill(); stroke(col); strokeWeight(4); ellipse(x, y, diameter, diameter); } }}

OSC 2:Processing → ChucK