yoppa.org


(番外編) 音を見る、画像を聴く

今回は「番外編」として、これまで扱ってきた機械学習とは全く別の内容で実習を行います。今回のテーマは「音を見る、画像を聴く」です。

音楽も画像も映像も3Dオブジェクトも、コンピューターの中では最終的には数値の羅列として保存されています。極論してしまえば、全て同じ「データ」として認識されています。

今回は、フォトレタッチとサウンド編集のアプリケーションをわざと間違った方法で使用します。本来はサウンド編集のために使われるAudacityというアプリケーションで写真を開き、エフェクトや編集を行います。その結果を今度はフォトレタッチのアプリケーションで開きます。どのような結果になるのか、実際に作業をしながら体験していきます。

スライド資料


サウンドプログラミング プログラミングで音響合成 – SuperCollider入門

これまで扱ってきた2つの音楽のためのライブコーディング環境、Sonic PiとTidalCyclesは、共にSuperColliderという音響合成言語の音響合成のためのサーバーを使用してきました。つまり、最終的な音はSuperColliderを通して生成されていたのです。

ここまでの講義では、SuperCollierによる音響合成の詳細は触れずに進めてきましたが、今回は番外編としてSuperCollierの初歩の触りの部分を解説します。まっさらな状態からプログラミングで音響合成する大変さを実感できればと思います。

スライド資料


最終課題に向けて! – Patatapを作る

Image result for patatap

この講義「デザインとプログラミング」では、変数と定数、反復、乱数、論理式と条件文、アニメーションとベクトル、配列の操作、関数、そしてオブジェクト指向プログラミングと様々なトピックスを扱ってきました。最終課題はこれらの内容を総動員して、Patatap (https://patatap.com/) のようなインタラクティブなオーディオビジュアル作品をp5.jsで制作します。

Patatapはとてもシンプルなインタラクションで構成された作品です。キーボードを操作すると、それぞれのキーにシンプルなアニメーションが割り振られていて、同時にサンプリングされたサウンドが鳴るようになっています。仕組みはとても単純なのですが、キーボードをリズムにあわせてタイピングすることで音と映像が同期して、まるでVJのパフォーマンスをしているような気分を味わえます。キーボードの組み合わせは無限にあるので、いつまでも飽きることがありません。

今回は、最終課題に向け、p5.jsをつかってPatatapを制作するための方法について解説していきます。

スライド資料

サンプルコード

最終課題制作テンプレート


最終課題のヒント2 – Teachable Machine + ml5.js + p5.jsの簡単なサンプル

前回に引き続き、最終課題のTeachableMachine + ml5.js + p5.jsを使用したコンテンツの制作のヒントをサンプルを紹介しながら解説していきます。

最終課題

Teachable Machineml5.js + p5.jsを使用して機械学習を活用したインタラクティブなコンテンツを制作して発表してください。

内容は、ゲーム、インタラクティブ・アート作品、GUIのデモ (キオスク端末など) など 、Teachable Machineを活用していれば何でもOKです。

1月15日の講義内で発表を行います。

サンプルファイル


TidalCycles応用 – オリジナルの楽器を作成する

ここまでは、TidalCyclesを使用して主にリズムやメロディーなど音のパターンや構造を記述することに注力してきました。使用する音色 (楽器) はSuperDirtであらかじめ用意されたサンプルとシンセを呼び出して使用してきました。

今回はTidalCycleの応用として、自分のオリジナルの音色でTidalCylesから演奏する方法について解説します。

サンプルファイルの追加はとても簡単です。SuperDirtで指定されたフォルダ (Dirt-Samples) 以下に新しくフォルダを作成してそこにサウンドファイルを追加するだけでオリジナルのサンプルを演奏することが可能となります。

オリジナルのSynthの追加は少し複雑です。SuperColliderの”SynthDef”で新規の楽器を定義して、それをTidalCyclesから呼び出します。この方法を用いるとオリジナルのSuperColliderの楽器を演奏することが可能となります。

独自のサンプルやSynthを演奏することで、よりオリジナリティーのあるパフォーマンスが可能となります!

スライド資料

SuperDirt用のSynthDefサンプル

(
SynthDef(\superp5str, {|out, speed=1, decay=0, sustain=0.1, pan, accelerate, freq,
	gate=1, pitch1 = 2, voice = 0.5, cutoff= 20000, rq=0.5|
	var sound;
	var env = EnvGen.ar(Env.pairs([[0,0],[0.07,1],[0.2,1-decay],[0.95,1-decay],[1,0]], -1), timeScale:sustain, doneAction:2);
	var lfo, pulse, filter;
	freq = freq / 2.0;
	lfo = LFTri.kr(pitch1*[1,1.01],Rand(0,2.0)!2);
	pulse = Pulse.ar(freq*[1,1.01],lfo*voice+0.5);
	filter = RLPF.ar(pulse,cutoff,rq);
	sound = Mix(filter) * 0.5;
	OffsetOut.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env));
}).add
);

(
SynthDef(\superlaser, {|out, speed=1, decay=0, sustain=0.1, pan, accelerate, freq,
	voice = 0.03, pitch1 = 4, gate=1|
	var sound;
	var env = EnvGen.ar(Env.pairs([[0,0],[0.07,1],[0.2,1-decay],[0.95,1-decay],[1,0]], -1), timeScale:sustain, doneAction:2);
	var osc1, freqenv, ampenv;
	freqenv = EnvGen.ar(Env([pitch1,0.1,1,1],[voice,0.01,1.0]));
	osc1 = LFTri.ar(freq*freqenv);
	sound = osc1*0.5;
	OffsetOut.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env));
}).add
);

(
SynthDef(\superost, {|out, speed=1, decay=0, sustain=0.1, pan, accelerate, freq,
	gate = 1, lforate = 3, lfowidth= 0.1|
	var sound;
	var env = EnvGen.ar(Env.adsr(0.01,0.05,0.5,0.1), gate, doneAction:2, timeScale:sustain);
	var lfo, pulse, filter;
	freq = freq / 2.0;
	lfo = LFTri.kr(lforate,Rand(0,2.0)!3);
	pulse = Pulse.ar(freq*[1,1.01,0.5],lfo*lfowidth+0.5);
	sound = Mix(pulse);
	OffsetOut.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env));
}).add
);

(
SynthDef(\superbass, {|out, speed=1, decay=0, sustain=0.1, pan, accelerate, freq,
	gate=1, cutoff= 800, rq=0.2|
	var sound;
	var env = EnvGen.ar(Env.adsr(0.01,0.0,0.9,0.05),gate,doneAction:2, timeScale:sustain);
	var osc, filter, filterenv;
	freq = freq / 4.0;
	osc = Saw.ar(freq);
	filterenv = EnvGen.ar(Env.adsr(0.0,0.5,0.2,0.2),gate,doneAction:2);
	filter =  RLPF.ar(osc,cutoff*filterenv+100,rq);
	sound = Mix(filter);
	OffsetOut.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env));
}).add
);

(
SynthDef(\supermoog2, {|out, speed=1, decay=0, sustain=0.1, pan, accelerate, freq,
	gate=1, attackTime= 0.2, fenvamount=1.0, cutoff= 10000, voice=2.0|
	var sound;
	var env = EnvGen.ar(Env.pairs([[0,0],[0.07,1],[0.2,1-decay],[0.95,1-decay],[1,0]], -1), timeScale:sustain, doneAction:2);
	var osc, filter, filterenv;
	freq = freq / 4.0;
	freq = [freq, freq * 1.001];
	osc = Mix(Pulse.ar(freq.lag(0.05)*[1.0,1.001,2.0],Rand(0.45,0.5)!3,0.33));
	filterenv = EnvGen.ar(Env.adsr(attackTime,0.0,1.0,0.2),gate,doneAction:2);
	filter =  MoogFF.ar(osc,cutoff*(1.0+(fenvamount*filterenv)), 2.0);
	sound = (filter * voice).distort;
	OffsetOut.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env));
}).add
);

(
SynthDef(\superwho, {|out, speed=1, decay=0, sustain=0.1, pan, accelerate, freq,
	amp = 0.5, gate=1, cutoff=8000, rq=0.8|
	var sound, fx;
	var env = EnvGen.ar(Env.pairs([[0,0],[0.07,1],[0.2,1-decay],[0.95,1-decay],[1,0]], -1), timeScale:sustain, doneAction:2);
	var osc, filter;
	var basefreq =  (((freq/2.0).cpsmidi)+[0,0.1]).midicps;
  	osc = Mix.fill(10,{|i| SinOsc.ar(basefreq*(i+1),0.0,(0.25+(0.75*LFNoise0.kr(10.1+i,0.5,0.5)))/(1.0+(0.5*i)))})*0.2;
	filter =  BLowPass.ar(osc,2000+(amp*cutoff),rq);
	sound = Mix(filter);
	fx = BLowPass.ar(BLowPass.ar(sound,SinOsc.ar(0.25,0,5000,5500),0.4),(200+(5000*SinOsc.ar(4.01,0.5,0.5,0.5))),0.6);
	sound = (sound * 0.7) + (fx * 0.3);
	OffsetOut.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env));
}).add
);

(
SynthDef(\superrhodes, {|out, speed=1, decay=0, sustain=0.1, pan, accelerate, freq,
	gate=1, lforate = 4.85, lfowidth= 0.5, cutoff= 2000, rq=0.5|
	var sound;
	var pulse, filter, env;
	pulse = Pulse.ar(freq*[1,33.5.midiratio],[0.2,0.1],[0.7,0.3]);
	env = EnvGen.ar(Env.adsr(0.0,1.0,0.8,3.0),gate,doneAction:2, timeScale:sustain);
	filter = BLowPass4.ar(pulse,(cutoff*(env.squared))+200+freq,rq);
	sound = Mix(filter);
	OffsetOut.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env));
}).add
);