ChucKにmusic shaderを移植
ChucKにmusic shaderを移植してみた。 まだ覚え始めなので、怪しいところもあると思います。
今回使ってるadsrの関数には、バグがあるので鵜呑みにしないでください。ここでは正常に動いているけど、違うパターンでダメな時がありました。そのうち直します。
元のmusic shaderはこれ。
#define BPM 140. #define A (15./BPM) float adsr(float t, vec4 e, float s) { return max(0.0, min(1.0, t/max(0.0001, e.x)) - min((1.0 - s) ,max(0.0, t - e.x)*(1.0 - s)/max(0.0001, e.y)) - max(0.0, t - e.z)*s/max(0.0001, e.w)); } float square(float f) { return sign(fract(f)-0.5); } float kick(float t){ return cos(315.0 * t - 10. * exp( -50. * t )+0.3)*adsr(t,vec4(0.0, 0.3, 0.0, 0.0), 0.0); +0.2*square(50.*t)* adsr(t,vec4(0.0, 0.05, 0.0, 0.0), 0.0); } float snare(float t) { return square(3063.0*t*sin(t*8000.0)) * adsr(t,vec4(0.005, 0.08, 0.0, 0.0), 0.0); } float closeHihat(float t) { return square(2763.0*t*sin(t*8500.0)) * adsr(t,vec4(0.0, 0.03, 0.0, 0.0), 0.0); } float openHihat(float t) { return square(2763.0*t*sin(t*8300.0)) * adsr(t,vec4(0.0, 0.05, 0.03, 0.03), 0.5); } float sequence(int s,float t) { float n =mod(t,A); for(int i=0;i<16;i++){ if((s>>(int(t/A)-i)%16&1)==1)break; n+=A; } return n; } vec2 mainSound( float time ) { int i = int(floor(time/(A*16.)))&3; int velocity = int[](0x3030,0x3030,0x3030,0x3030)[i]>>(int(floor(time/A))&15)&1; float vol = 0.2 *(1.0+1.5*float(velocity)); return vec2( 0.0 + 0.3 * kick(sequence( int[](0x0c05,0x0c05,0x0c05,0x0c0c)[i],time)) + 0.3 * snare(sequence( int[](0x9290,0x9290,0x4290,0x4292)[i],time)) + vol * closeHihat(sequence(int[](0x5555,0x5555,0x5555,0x5155)[i],time)) + vol * openHihat(sequence( int[](0x0000,0x0000,0x0000,0x0400)[i],time)) ); }
Chuckでサンプリング音源を使った奴。
140 => float bpm; 1::second * 15 / bpm=> dur tick; fun void kick(){ SndBuf buf => Gain g => dac; .25 => g.gain; me.dir() + "data/kick.wav" => buf.read; [0x0c05,0x0c05,0x0c05,0x0c0c]@=> int seq[]; 0 => int bar; while( true ){ for(int i; i < 16; i++) { if (seq[bar%4]>>i&1==1){0 => buf.pos;} 1::tick => now; } bar++; } } fun void snare(){ SndBuf buf => Gain g => dac; .4 => g.gain; me.dir() + "data/snare.wav" => buf.read; [0x9290,0x9290,0x4290,0x4292]@=> int seq[]; 0 => int bar; while( true ){ for(int i; i < 16; i++) { if (seq[bar%4]>>i&1==1){0 => buf.pos;} 1::tick => now; } bar++; } } fun void hihat(){ SndBuf buf => Gain g => dac; .25 => g.gain; 0 => int bar; [0x5555,0x5555,0x5555,0x5155]@=> int seq[]; me.dir() + "data/hihat.wav" => buf.read; while( true ){ for(int i; i < 16; i++) { if (seq[bar%4]>>i&1==1){0 => buf.pos;} 1::tick => now; } <<<"bar",bar>>>; bar++; } } fun void openHihat(){ SndBuf buf => Gain g => dac; .25 => g.gain; 0 => int bar; [0x0000,0x0000,0x0000,0x0400]@=> int seq[]; me.dir() + "data/hihat-open.wav" => buf.read; while( true ){ for(int i; i < 16; i++) { if (seq[bar%4]>>i&1==1){0 => buf.pos;} 1::tick => now; } bar++; } } spork ~ kick(); spork ~ snare(); spork ~ hihat(); spork ~ openHihat(); 3::minute=> now;
ChucKで音源をmusic shaderに合わせた奴。
音源のclassをつくるのに参考にしたページ
140 => float bpm; 1::second * 15 / bpm=> dur tick; fun float square(float f) { return (Math.floor(Math.sin(f))+0.5)*2.0; } fun float adsr(float t, float a, float d, float s, float r, float gt) { return Math.max(0.0, Math.min(1.0, t/Math.max(0.0001, a)) - Math.min((1.0 - gt) ,Math.max(0.0, t - a)*(1.0 - gt)/Math.max(0.0001, d)) - Math.max(0.0, t - s)*gt/Math.max(0.0001,r)); } class MyKick extends Chugen { 100 => float time; samp/second => float dt; fun float tick(float in) { Math.cos(315*time-10*Math.exp(-50*time)+0.3)*adsr(time,0,0.3,0,0,0) => float g; time+dt=>time; return g; } } class MySnare extends Chugen { 100 => float time; samp/second => float dt; fun float tick(float in) { square(3063.0*time*Math.sin(time*8000.0))*adsr(time,0.005,0.08,0,0,0) => float g; time+dt=>time; return g; } } class MyCloseHihat extends Chugen { 100 => float time; samp/second => float dt; fun float tick(float in) { square(3063.0*time*Math.sin(time*8000.0)) * adsr(time,0.005,0.08,0,0,0) => float g; time+dt=>time; return g; } } class MyOpenHihat extends Chugen { 100 => float time; samp/second => float dt; fun float tick(float in) { square(2763*time*Math.sin(time*8500)) * adsr(time,0.0,0.05,0.03,0.03,0.5) => float g; time+dt=>time; return g; } } fun void kick(){ MyKick o => Gain g => dac; 0.3 => g.gain; [0x0c05,0x0c05,0x0c05,0x0c0c]@=> int seq[]; 0 => int bar; while( true ){ for(int i; i < 16; i++) { if (seq[bar%4]>>i&1==1){0=>o.time;} 1::tick => now; } bar++; } } fun void snare(){ MySnare o => Gain g => dac; 0.2 => g.gain; [0x9290,0x9290,0x4290,0x4292]@=> int seq[]; 0 => int bar; while( true ){ for(int i; i < 16; i++) { if (seq[bar%4]>>i&1==1){0 => o.time;} 1::tick => now; } bar++; } } fun void closeHihat(){ MyCloseHihat o => Gain g => dac; 0.2 => g.gain; 0 => int bar; [0x5555,0x5555,0x5555,0x5155]@=> int seq[]; [0x3030,0x3030,0x3030,0x3030]@=> int vel[]; while( true ){ for(int i; i < 16; i++) { if (seq[bar%4]>>i&1==1){0 => o.time;} if (vel[bar%4]>>i&1==1){0.3 => g.gain;}else{0.2 => g.gain;} 1::tick => now; } bar++; } } fun void openHihat(){ MyOpenHihat o => Gain g => dac; 0.2 => g.gain; 0 => int bar; [0x0000,0x0000,0x0000,0x0400]@=> int seq[]; [0x3030,0x3030,0x3030,0x3030]@=> int vel[]; while( true ){ for(int i; i < 16; i++) { if (seq[bar%4]>>i&1==1){0 => o.time;} if (vel[bar%4]>>i&1==1){0.3 => g.gain;}else{0.2 => g.gain;} 1::tick => now; } bar++; } } spork ~ kick(); spork ~ snare(); spork ~ closeHihat(); spork ~ openHihat(); 3::minute=> now;
ここで使っているシーケンスについての説明は
ここにあります。
メモ
俺的、kick音源、暫定一位は
— gaz (@gaziya5) 2019年5月25日
sin(pow(1.0-min(1.0,t*3.5),15.)*48.0+1.3)*exp(-t*3.0)
これ。+1.3は何だろうね。昔、FL1NEくんが熱くkickについて語っていたのが、わかるレベルには到達できたと思う。