├── 1-1_shift.glsl ├── 2-1_helloworld.glsl ├── 3-1_primitives.glsl ├── 3-2_vibrato.glsl ├── 3-3_fm.glsl ├── 3-4_kick.glsl ├── 3-5_hihat.glsl ├── 4-1_chord.glsl ├── 4-2_rhythm.glsl ├── 4-3_sidechain.glsl ├── 4-4_arp.glsl ├── 5-1_finish.glsl ├── LICENSE ├── README.md └── slides.pdf /1-1_shift.glsl: -------------------------------------------------------------------------------- 1 | #define PI 3.141592654 2 | #define TAU 6.283185307 3 | #define BPM 175.0 4 | 5 | #define V vec3(0.,1.,-1.) 6 | #define saturate(i) clamp(i,0.,1.) 7 | #define saturateA(i) clamp(i,-1.,1.) 8 | #define lofi(i,j) floor((i)/j)*j 9 | #define b2t(i) ((i)/BPM*60.0) 10 | #define noten(i) 440.0*pow(2.0,(float(i)+trans)/12.0) 11 | 12 | // ------ 13 | 14 | // general functions 15 | 16 | vec4 random2D( vec2 _v ) { 17 | return fract( sin( texture( iChannel0, _v ) * 25711.34 ) * 175.23 ); 18 | } 19 | 20 | vec4 random( float _v ) { 21 | return random2D( _v * V.yy ); 22 | } 23 | 24 | // ------ 25 | 26 | // Instruments 27 | 28 | // stronger kick 29 | vec2 kick( float _phase ) { 30 | if ( _phase < 0.0 ) { return V.xx; } 31 | return V.yy * sin( _phase * 300.0 - exp( -_phase * 70.0 ) * 80.0 ) * exp( -_phase * 4.0 ); 32 | } 33 | 34 | // weaker kick 35 | vec2 kick2( float _phase ) { 36 | if ( _phase < 0.0 ) { return V.xx; } 37 | return V.yy * sin( _phase * 300.0 - exp( -_phase * 100.0 ) * 30.0 ) * exp( -_phase * 5.0 ); 38 | } 39 | 40 | // stronger kick 41 | vec2 snare( float _phase ) { 42 | if ( _phase < 0.0 ) { return V.xx; } 43 | return saturateA( ( 44 | random( _phase / 0.034 ).xy + 45 | sin( _phase * 2500.0 * vec2( 1.005, 0.995 ) - exp( -_phase * 400.0 ) * 30.0 ) 46 | ) * 2.0 * exp( -_phase * 23.0 ) ); 47 | } 48 | 49 | // weaker kick 50 | vec2 snare2( float _phase ) { 51 | if ( _phase < 0.0 ) { return V.xx; } 52 | return ( 53 | random( lofi( _phase, 6E-5 ) / 2.06 ).xy * 0.5 + 54 | sin( _phase * 2000.0 * vec2( 1.005, 0.995 ) - exp( -_phase * 800.0 ) * 20.0 ) 55 | ) * exp( -_phase * 31.0 ); 56 | } 57 | 58 | // cowbell 59 | vec2 cowbell( float _phase ) { 60 | if ( _phase < 0.0 ) { return V.xx; } 61 | vec2 cow = ( 62 | sin( _phase * 800.0 * TAU * vec2( 1.005, 0.995 ) - exp( -_phase * 800.0 ) * 20.0 ) + 63 | sin( _phase * 540.0 * TAU * vec2( 0.995, 1.005 ) - exp( -_phase * 800.0 ) * 20.0 ) 64 | ); 65 | return sign( cow ) * pow( abs( cow ) * exp( -_phase * 20.0 ), 0.8 * V.yy ); 66 | } 67 | 68 | // tom 69 | vec2 tam( float _freq, float _phase ) { 70 | if ( _phase < 0.0 ) { return V.xx; } 71 | vec2 s = V.yy * 2.0 * sin( _phase * _freq * TAU + random( _phase * 1.45 ).xy * 0.1 - exp( -_phase * 1000.0 ) * 9.0 ); 72 | float a = exp( -_phase * 20.0 ) / 2.5; 73 | return s * a; 74 | } 75 | 76 | // hihat 77 | vec2 hihat( float _seed, float _dec ) { 78 | return random( _seed ).xy * exp( -_dec ); 79 | } 80 | 81 | // main bass 82 | float powNoise( float _freq, float _phase ) { 83 | if ( _phase < 0.0 ) { return 0.0; } 84 | float p = mod( _phase * _freq, 1.0 ) + random( _phase * 1.45 ).x * 0.01; 85 | return ( ( p < 0.4 ? -0.1 : 0.1 ) + sin( p * TAU ) * 0.7 ); 86 | } 87 | 88 | // simple saw 89 | float sharpSaw( float _phase ) { 90 | return mod( _phase, 1.0 ) * 2.0 - 1.0; 91 | } 92 | 93 | // pwm 94 | float pwm( float _phase, float _pulse ) { 95 | return fract( _phase ) < _pulse ? -1.0 : 1.0; 96 | } 97 | 98 | // filtered saw, simulated by additive synthesis 99 | float saw( float _freq, float _phase, float _filt, float _q ) { 100 | if ( _phase < 0.0 ) { return 0.0; } 101 | float sum = 0.0; 102 | for ( int i = 1; i <= 32; i ++ ) { 103 | float cut = smoothstep( _filt * 1.2, _filt * 0.8, float( i ) * _freq ); 104 | cut += smoothstep( _filt * 0.3, 0.0, abs( _filt - float( i ) * _freq ) ) * _q; 105 | sum += sin( float( i ) * _freq * _phase * TAU ) / float( i ) * cut; 106 | } 107 | return sum; 108 | } 109 | 110 | // fm synthesis 111 | vec2 fms( float _freq, float _phase, float _mod ) { 112 | if ( _phase < 0.0 ) { return V.xx; } 113 | float p = _phase * _freq * TAU; 114 | return vec2( 115 | sin( p * 0.999 + sin( p * _mod * 1.002 ) * exp( -_phase * 7.0 ) ), 116 | sin( p * 1.001 + sin( p * _mod * 0.998 ) * exp( -_phase * 7.0 ) ) 117 | ) * exp( -_phase * 7.0 ); 118 | } 119 | 120 | // DX7 tubular bell 121 | vec2 bell( float _freq, float _phase ) { 122 | if ( _phase < 0.0 ) { return V.xx; } 123 | vec2 p = _freq * vec2( 1.001, 0.999 ) * _phase * TAU; 124 | float d = exp( -_phase * 1.0 ); 125 | float d2 = exp( -_phase * 20.0 ); 126 | return ( 127 | sin( p * 1.0001 + sin( p * 3.5004 ) * d ) + 128 | sin( p * 0.9998 + sin( p * 3.4997 ) * d ) + 129 | sin( _phase * 2033.2 + sin( p * 1.9994 ) * exp( -_phase * 10.0 ) ) * exp( -_phase * 10.0 ) 130 | ) * 0.3 * d; 131 | } 132 | 133 | // wtf is this 134 | vec2 choir( float _freq, float _phase, float _time ) { 135 | if ( _phase < 0.0 ) { return V.xx; } 136 | vec2 sum = V.xx; 137 | for ( int i = 0; i < 6; i ++ ) { 138 | vec4 rand = random( float( i ) / 0.3 ); 139 | vec2 p = ( _time - _phase ) + _phase * _freq * PI * ( 0.98 + 0.04 * rand.xy ) + float( i ); 140 | p += sin( p / _freq * 3.0 + rand.zw ); 141 | sum += sin( 2.0 * p + sin( p ) * 1.0 + sin( 7.0 * p ) * 0.02 ); 142 | } 143 | return sum / 8.0; 144 | } 145 | 146 | // digital piano 147 | vec2 cccp( float _freq, float _phase ) { 148 | if ( _phase < 0.0 ) { return V.xx; } 149 | vec2 p = _freq * vec2( 0.999, 1.001 ) * _phase * TAU; 150 | float dl = exp( -_phase * 1.0 ); 151 | float ds = exp( -_phase * 10.0 ); 152 | return ( 153 | sin( p * 1.0003 + sin( p * 11.0035 ) * 1.5 * ds + sin( p * 1.0003 ) * 1.0 * dl ) + 154 | sin( p * 0.9997 + sin( p * 0.9997 + sin( p * 4.9984 ) * 2.0 * dl ) * 0.5 * ds ) 155 | ) * 0.5 * ds; 156 | } 157 | 158 | // fm bass 159 | vec2 bass( float _freq, float _phase ) { 160 | if ( _phase < 0.0 ) { return V.xx; } 161 | vec2 p = _freq * vec2( 0.999, 1.001 ) * _phase * TAU; 162 | float dl = exp( -_phase * 1.0 ); 163 | float ds = exp( -_phase * 14.0 ); 164 | return sin( 165 | p + 166 | sin( p ) * 1.5 * dl + 167 | sin( p + sin( p * 10.0 ) * 2.5 * ds ) * 3.0 * ds + 168 | sin( p + sin( p * 18.0 ) * 1.5 * ds ) * 0.5 * dl 169 | ) * 0.5 * dl; 170 | } 171 | 172 | // ------ 173 | 174 | vec2 mainSound( float time ) { 175 | float t = time; 176 | float beat = t * BPM / 60.0 - 8.0; 177 | vec2 ret = V.xx; 178 | float tenkai = floor( beat / 4.0 ); 179 | float sidechain = 0.0; 180 | 181 | float trans = 3.0; 182 | 183 | float beati = floor( beat ); 184 | float beatf = fract( beat ); 185 | float beat32 = mod( beat, 32.0 ); 186 | 187 | float kickTime; 188 | float snareTime; 189 | 190 | // ------ 191 | 192 | // pi po po po 193 | if ( beat < 0.0 ) { 194 | ret += 0.5 * sin( TAU * t * ( mod( beat, 4.0 ) < 1.0 ? 2000.0 : 1000.0 ) ) * ( beatf < 0.1 ? 1.0 : 0.0 ); 195 | } 196 | 197 | // ------ 198 | 199 | // weaker kick'n'snare part 200 | if ( ( 0.0 < beat && beat < 64.0 ) || ( 192.0 < beat && beat < 256.0 ) ) { 201 | kickTime = b2t( mod( mod( beat, 4.0 ), 2.5 ) ); 202 | snareTime = b2t( mod( beat - 1.0, 2.0 ) ); 203 | float beat64 = mod( beat, 64.0 ); 204 | 205 | ret += 0.7 * kick2( kickTime ); 206 | ret += 0.5 * snare2( snareTime ); 207 | sidechain = smoothstep( 0.0, 0.2, min( kickTime, snareTime ) ); 208 | 209 | ret += 0.2 * sidechain * hihat( t, b2t( mod( beat, 0.5 ) ) * 100.0 ); 210 | if ( 32.0 < beat ) { 211 | ret += 0.2 * hihat( t * 0.1, b2t( mod( beat, 0.25 ) ) * 1000.0 ); 212 | } 213 | 214 | float build = max( 0.0, beat64 - 48.0 ); 215 | float ksk = pow( build * 0.3, 2.0 ); 216 | float vib = sin( t * ( 20.0 + ksk ) ) * ( 0.1 + ksk * 0.1 ); 217 | ret += sidechain * sharpSaw( noten( -24 ) * t + vib ) * 0.04; 218 | ret += sidechain * sharpSaw( noten( -17 ) * t + vib ) * 0.04; 219 | ret += sidechain * sharpSaw( noten( -14 ) * t + vib ) * 0.04; 220 | ret += sidechain * sharpSaw( noten( -7 ) * t + vib ) * 0.04; 221 | ret += sidechain * sharpSaw( noten( 2 ) * t + vib ) * 0.04; 222 | 223 | ret += sidechain * 0.2 * build / 16.0 * random( lofi( t * 6.24, 0.0008 * lofi( build / 16.0, 0.02 ) ) ).xy; 224 | 225 | if ( 62.5 < beat64 ) { 226 | ret = 0.7 * kick( b2t( beat64 - 62.5 ) ); 227 | ret += 0.5 * snare( b2t( beat64 - 63.0 ) ); 228 | if ( 255.0 < beat ) { 229 | ret = 0.5 * snare( b2t( beat - 255.0 - lofi( beat - 255.0, 0.08 ) * 0.8 ) ); 230 | } 231 | } 232 | } 233 | 234 | // ------ 235 | 236 | // first half 237 | if ( 64.0 < beat && beat < 192.0 ) { 238 | if ( 124.5 < beat && beat < 128.0 ) { 239 | ret += 0.7 * kick2( b2t( 240 | mod( mod( beatf - 0.75, 1.0 ), 0.75 ) 241 | ) ); 242 | ret += 0.5 * snare2( b2t( 243 | mod( mod( beatf - 0.25, 1.0 ), 0.75 ) 244 | ) ); 245 | if ( 127.0 < beat ) { 246 | ret = 0.5 * snare( b2t( beat - 127.0 - lofi( beat - 127.0, 0.12 ) * 0.6 ) ); 247 | } 248 | sidechain = 0.0; 249 | } else { 250 | kickTime = mod( beat, 4.0 ) < 2.5 ? b2t( mod( mod( beat, 4.0 ), 1.75 ) ) : b2t( mod( beat - 2.5, 4.0 ) ); 251 | snareTime = b2t( mod( beat - 1.0, 2.0 ) ); 252 | 253 | ret += 0.7 * kick( kickTime ); 254 | ret += 0.5 * snare( snareTime ); 255 | sidechain = smoothstep( 0.0, 0.2, min( kickTime, snareTime ) ); 256 | } 257 | 258 | ret += 0.4 * tam( 300.0, b2t( mod( beat - 0.75, 2.0 ) ) ); 259 | 260 | if ( 96.0 < beat ) { 261 | ret += 0.3 * sidechain * hihat( t, b2t( mod( beat, 0.25 ) ) * 100.0 ); 262 | } 263 | 264 | if ( mod( beat, 2.0 ) < 1.0 ) { 265 | ret += sidechain * powNoise( noten( 0 ) / 8.0, t ) * 1.0; 266 | } 267 | } 268 | 269 | // second half 270 | if ( 256.0 < beat && beat < 448.0 ) { 271 | trans = beat < 320.0 ? 2.0 : beat < 384.0 ? 0.0 : -3.0; 272 | kickTime = mod( beat, 4.0 ) < 2.5 ? b2t( mod( mod( beat, 4.0 ), 1.75 ) ) : b2t( mod( beat - 2.5, 4.0 ) ); 273 | snareTime = b2t( mod( beat - 1.0, 2.0 ) ); 274 | 275 | if ( ( 316.0 < beat && beat < 320.0 ) || 444.0 < beat ) { 276 | sidechain = smoothstep( 0.0, 0.2, b2t( beatf ) ); 277 | } else { 278 | ret += 0.7 * kick( kickTime ); 279 | ret += 0.5 * snare( snareTime ); 280 | sidechain = smoothstep( 0.0, 0.2, min( kickTime, snareTime ) ); 281 | 282 | if ( beat < 384.0 ) { 283 | ret += 0.4 * tam( 300.0, b2t( mod( beat - 0.75, 2.0 ) ) ); 284 | ret += 0.3 * sidechain * hihat( t, b2t( mod( beat, 0.25 ) ) * 100.0 ); 285 | } 286 | 287 | float vib = sin( t * 20.0 ) * 0.1; 288 | ret += sidechain * sharpSaw( noten( -24 ) * t + vib ) * 0.04; 289 | ret += sidechain * sharpSaw( noten( -17 ) * t + vib ) * 0.04; 290 | ret += sidechain * sharpSaw( noten( -14 ) * t + vib ) * 0.04; 291 | ret += sidechain * sharpSaw( noten( -7 ) * t + vib ) * 0.04; 292 | ret += sidechain * sharpSaw( noten( 2 ) * t + vib ) * 0.04; 293 | } 294 | 295 | if ( mod( beat, 2.0 ) < 1.0 ) { 296 | ret += sidechain * powNoise( noten( 0 ) / 8.0, t ) * 1.0; 297 | } 298 | } 299 | 300 | // ------ 301 | 302 | // soooo manyyy instrumentsss 303 | if ( ( 256.0 < beat && beat < 448.0 ) ) { 304 | if ( 1.25 < beat32 && beat32 < 2.0 ) { 305 | ret += saturateA( saw( 306 | noten( beatf < 0.5 ? 10 : beatf < 0.75 ? 12 : 0 ) / 4.0, 307 | b2t( mod( beat, 0.25 ) ), 308 | 300.0 + 1200.0 * exp( -b2t( mod( beat, 0.25 ) ) * 20.0 ), 309 | 7.0 310 | ) * 1.0 ) * 0.15; 311 | } 312 | 313 | if ( 3.0 < beat32 && beat32 < 4.0 ) { 314 | ret += bell( noten( -2 ), b2t( beatf - 0.75 ) ) * 0.2; 315 | } 316 | 317 | if ( 5.0 < beat32 && beat32 < 6.0 ) { 318 | ret += sidechain * sharpSaw( noten( 0 ) / 4.0 * t ) * 0.2; 319 | } 320 | 321 | if ( 7.0 < beat32 && beat32 < 8.0 ) { 322 | ret += sidechain * sharpSaw( noten( 0 ) * t + sin( t * 50.0 ) * 0.4 ) * 0.15; 323 | } 324 | 325 | if ( 9.0 < beat32 && beat32 < 10.0 ) { 326 | ret += 0.5 * tam( 200.0, b2t( beatf - 0.5 ) ); 327 | } 328 | 329 | if ( 11.0 < beat32 && beat32 < 12.0 ) { 330 | if ( 0.5 < beatf ) { 331 | ret += saw( 332 | noten( beatf < 0.75 ? 10 : 0 ) / 4.0, 333 | b2t( mod( beatf, 0.25 ) ), 334 | 300.0 + 4500.0 * exp( -b2t( mod( beatf, 0.25 ) ) * 20.0 ), 335 | 3.0 336 | ) * 0.08; 337 | } 338 | } 339 | 340 | if ( 13.25 < beat32 && beat32 < 13.75 ) { 341 | float p = mod( noten( beatf < 0.5 ? -2 : 0 ) / 8.0 * b2t( beatf ), 1.0 ); 342 | ret += 0.4 * exp( -1.0 * b2t( mod( beat, 0.25 ) ) ) * lofi( p < 0.5 ? p * 4.0 - 1.0 : 3.0 - p * 4.0, 0.1 ); 343 | } 344 | 345 | if ( 15.0 < beat32 && beat32 < 16.0 ) { 346 | ret += fms( noten( 0 ) / 2.0, b2t( beatf - 0.5 ), 2.0 ) * 0.1; 347 | ret += fms( noten( 5 ) / 2.0, b2t( beatf - 0.5 ), 7.0 ) * 0.1; 348 | ret += fms( noten( 7 ) / 2.0, b2t( beatf - 0.5 ), 1.0 ) * 0.1; 349 | ret += fms( noten( 10 ) / 2.0, b2t( beatf - 0.5 ), 12.0 ) * 0.1; 350 | } 351 | 352 | if ( 17.0 < beat32 && beat32 < 18.0 ) { 353 | ret += 0.1 * sidechain * saw( 354 | noten( 0 ) / 8.0, 355 | lofi( b2t( beatf ), 2E-4 ), 356 | 300.0 + 3500.0 * exp( -b2t( beatf ) * 10.0 ), 357 | 7.0 358 | ); 359 | } 360 | 361 | if ( 19.0 < beat32 && beat32 < 20.0 ) { 362 | ret += 0.2 * sidechain * pwm( t * noten( -38 ), 0.5 ); 363 | } 364 | 365 | if ( 21.0 < beat32 && beat32 < 22.0 ) { 366 | ret += cccp( noten( 2 ), b2t( beatf - 0.25 ) ) * 0.1; 367 | ret += cccp( noten( 3 ), b2t( beatf - 0.5 ) ) * 0.1; 368 | ret += cccp( noten( 10 ), b2t( beatf - 0.75 ) ) * 0.1; 369 | } 370 | 371 | if ( 23.0 < beat32 && beat32 < 24.0 ) { 372 | ret += cowbell( b2t( beatf - 0.5 ) ) * 0.2; 373 | } 374 | 375 | if ( 25.25 < beat32 && beat32 < 25.75 ) { 376 | ret += 0.15 * bass( noten( beatf < 0.5 ? -26 : -24 ), b2t( mod( beatf, 0.25 ) ) ); 377 | } 378 | 379 | if ( 27.00 < beat32 && beat32 < 28.00 ) { 380 | ret += 0.15 * bass( noten( -26 ), b2t( lofi( beatf, 0.001 ) - 0.5 ) * 0.5 ); 381 | } 382 | 383 | if ( 29.0 < beat32 && beat32 < 30.0 ) { 384 | ret += 0.1 * sidechain * pwm( t * noten( -7 ), beatf * 0.5 ); 385 | } 386 | 387 | if ( 31.0 < beat32 && beat32 < 32.0 ) { 388 | int n = int( mod( floor( beatf * 12.0 ), 6.0 ) ); 389 | ret += 0.1 * sidechain * pwm( t * noten( n == 0 ? 0 : n == 1 ? 5 : n == 2 ? 7 : n == 3 ? 12 : n == 4 ? 17 : 19 ), 0.25 ); 390 | } 391 | } 392 | 393 | // ------ 394 | 395 | // arp for first half 396 | if ( 128.0 < beat && beat < 254.5 ) { 397 | for ( int i = 0; i < 3; i ++ ) { 398 | float dice = random( floor( ( beat - float( i ) * 0.75 ) / 0.25 ) / 4.72 ).x; 399 | int dicen = int( dice * 5.0 ); 400 | float note = dicen == 0 ? 0.0 : dicen == 1 ? 7.0 : dicen == 2 ? 10.0 : dicen == 3 ? 17.0 : 26.0; 401 | float diceo = mod( floor( dice * 15.0 ), 3.0 ); 402 | note += diceo * 12.0; 403 | ret += 0.07 / float( i * 4 + 1 ) * cccp( noten( note ) / 2.0, b2t( mod( beatf, 0.25 ) ) ); 404 | } 405 | } 406 | 407 | // arp for second half 408 | if ( 320.0 < beat && beat < 444.0 ) { 409 | for ( int i = 0; i < 3; i ++ ) { 410 | float dice = random( floor( ( beat - float( i ) ) / 0.25 ) / 4.72 ).x; 411 | int dicen = int( dice * 5.0 ); 412 | float note = dicen == 0 ? 0.0 : dicen == 1 ? 7.0 : dicen == 2 ? 10.0 : dicen == 3 ? 17.0 : 26.0; 413 | float diceo = mod( floor( dice * 15.0 ), 3.0 ); 414 | note += diceo * 12.0; 415 | float ph = b2t( mod( beatf, 0.25 ) ); 416 | ret += 0.03 * saw( noten( note ) / 2.0, ph, 200.0 + 6500.0 * exp( -ph * 20.0 ) / float( i * 5 + 1 ), 0.0 ); 417 | } 418 | } 419 | 420 | // ------ 421 | 422 | return saturateA( ret ); 423 | } -------------------------------------------------------------------------------- /2-1_helloworld.glsl: -------------------------------------------------------------------------------- 1 | vec2 mainSound( float time ) { 2 | return vec2( sin( 6.2831 * 440.0 * time ) * exp( -3.0 * time ) ); 3 | } -------------------------------------------------------------------------------- /3-1_primitives.glsl: -------------------------------------------------------------------------------- 1 | #define PI 3.141592654 2 | #define TAU 6.283185307 3 | 4 | // ------ 5 | 6 | float saw( float phase ) { 7 | return 2.0 * fract( phase ) - 1.0; 8 | } 9 | 10 | float square( float phase ) { 11 | return fract( phase ) < 0.5 ? -1.0 : 1.0; 12 | } 13 | 14 | float triangle( float phase ) { 15 | return 1.0 - 4.0 * abs( fract( phase ) - 0.5 ); 16 | } 17 | 18 | float sine( float phase ) { 19 | return sin( TAU * phase ); 20 | } 21 | 22 | // ------ 23 | 24 | vec2 mainSound( float time ) { 25 | return vec2( saw( 440.0 * time ) ); 26 | } -------------------------------------------------------------------------------- /3-2_vibrato.glsl: -------------------------------------------------------------------------------- 1 | #define PI 3.141592654 2 | #define TAU 6.283185307 3 | 4 | // ------ 5 | 6 | float saw( float phase ) { 7 | return 2.0 * fract( phase ) - 1.0; 8 | } 9 | 10 | float sine( float phase ) { 11 | return sin( TAU * phase ); 12 | } 13 | 14 | // ------ 15 | 16 | vec2 mainSound( float time ) { 17 | float vib = 0.2 * sine( time * 5.0 ); 18 | return vec2( saw( 440.0 * time + vib ) ); 19 | } -------------------------------------------------------------------------------- /3-3_fm.glsl: -------------------------------------------------------------------------------- 1 | #define PI 3.141592654 2 | #define TAU 6.283185307 3 | 4 | // ------ 5 | 6 | float sine( float phase ) { 7 | return sin( TAU * phase ); 8 | } 9 | 10 | // ------ 11 | 12 | vec2 mainSound( float time ) { 13 | float freq = 440.0; 14 | float fmamp = 0.1 * exp( -3.0 * time ); 15 | float fm = fmamp * sine( time * freq * 7.0 ); 16 | 17 | float amp = exp( -1.0 * time ); 18 | return vec2( amp * sine( freq * time + fm ) ); 19 | } -------------------------------------------------------------------------------- /3-4_kick.glsl: -------------------------------------------------------------------------------- 1 | #define PI 3.141592654 2 | #define TAU 6.283185307 3 | 4 | // ------ 5 | 6 | float sine( float phase ) { 7 | return sin( TAU * phase ); 8 | } 9 | 10 | // ------ 11 | 12 | float kick( float time ) { 13 | float amp = exp( -5.0 * time ); 14 | float phase = 50.0 * time 15 | - 10.0 * exp( -70.0 * time ); 16 | return amp * sine( phase ); 17 | } 18 | 19 | // ------ 20 | 21 | vec2 mainSound( float time ) { 22 | return vec2( kick( time ) ); 23 | } -------------------------------------------------------------------------------- /3-5_hihat.glsl: -------------------------------------------------------------------------------- 1 | #define PI 3.141592654 2 | #define TAU 6.283185307 3 | 4 | // ------ 5 | 6 | vec4 noise( float phase ) { 7 | vec2 uv = phase / vec2( 0.512, 0.487 ); 8 | return 2.0 * texture( iChannel0, uv ) - 1.0; 9 | } 10 | 11 | // ------ 12 | 13 | vec2 hihat( float time ) { 14 | float amp = exp( -50.0 * time ); 15 | return amp * noise( time * 100.0 ).xy; 16 | } 17 | 18 | // ------ 19 | 20 | vec2 mainSound( float time ) { 21 | return vec2( hihat( time ) ); 22 | } -------------------------------------------------------------------------------- /4-1_chord.glsl: -------------------------------------------------------------------------------- 1 | #define PI 3.141592654 2 | #define TAU 6.283185307 3 | 4 | // ------ 5 | 6 | float noteToFreq( float n ) { 7 | return 440.0 * pow( 2.0, ( n - 69.0 ) / 12.0 ); 8 | } 9 | 10 | float chord( float n ) { 11 | return ( 12 | n < 1.0 ? 55.0 : 13 | n < 2.0 ? 58.0 : 14 | n < 3.0 ? 62.0 : 15 | 65.0 16 | ); 17 | } 18 | 19 | // ------ 20 | 21 | float saw( float phase ) { 22 | return 2.0 * fract( phase ) - 1.0; 23 | } 24 | 25 | // ------ 26 | 27 | vec2 mainSound( float time ) { 28 | return vec2( 29 | saw( time * noteToFreq( chord( 0.0 ) ) ) 30 | + saw( time * noteToFreq( chord( 1.0 ) ) ) 31 | + saw( time * noteToFreq( chord( 2.0 ) ) ) 32 | + saw( time * noteToFreq( chord( 3.0 ) ) ) 33 | ) / 4.0; 34 | } -------------------------------------------------------------------------------- /4-2_rhythm.glsl: -------------------------------------------------------------------------------- 1 | #define BPM 140.0 2 | 3 | #define PI 3.141592654 4 | #define TAU 6.283185307 5 | 6 | // ------ 7 | 8 | float timeToBeat( float t ) { return t / 60.0 * BPM; } 9 | float beatToTime( float b ) { return b / BPM * 60.0; } 10 | 11 | // ------ 12 | 13 | float sine( float phase ) { 14 | return sin( TAU * phase ); 15 | } 16 | 17 | vec4 noise( float phase ) { 18 | vec2 uv = phase / vec2( 0.512, 0.487 ); 19 | return 2.0 * texture( iChannel0, uv ) - 1.0; 20 | } 21 | 22 | // ------ 23 | 24 | float kick( float time ) { 25 | float amp = exp( -5.0 * time ); 26 | float phase = 50.0 * time 27 | - 10.0 * exp( -70.0 * time ); 28 | return amp * sine( phase ); 29 | } 30 | 31 | vec2 hihat( float time ) { 32 | float amp = exp( -50.0 * time ); 33 | return amp * noise( time * 100.0 ).xy; 34 | } 35 | 36 | // ------ 37 | 38 | vec2 mainSound( float time ) { 39 | float beat = timeToBeat( time ); 40 | 41 | float kickTime = beatToTime( mod( beat, 1.0 ) ); 42 | float hihatTime = beatToTime( mod( beat + 0.5, 1.0 ) ); 43 | 44 | return vec2( kick( kickTime ) + hihat( hihatTime ) ); 45 | } -------------------------------------------------------------------------------- /4-3_sidechain.glsl: -------------------------------------------------------------------------------- 1 | #define BPM 140.0 2 | 3 | #define PI 3.141592654 4 | #define TAU 6.283185307 5 | 6 | // ------ 7 | 8 | float timeToBeat( float t ) { return t / 60.0 * BPM; } 9 | float beatToTime( float b ) { return b / BPM * 60.0; } 10 | 11 | float noteToFreq( float n ) { 12 | return 440.0 * pow( 2.0, ( n - 69.0 ) / 12.0 ); 13 | } 14 | 15 | float chord( float n ) { 16 | return ( 17 | n < 1.0 ? 55.0 : 18 | n < 2.0 ? 58.0 : 19 | n < 3.0 ? 62.0 : 20 | 65.0 21 | ); 22 | } 23 | 24 | // ------ 25 | 26 | float sine( float phase ) { 27 | return sin( TAU * phase ); 28 | } 29 | 30 | float saw( float phase ) { 31 | return 2.0 * fract( phase ) - 1.0; 32 | } 33 | 34 | // ------ 35 | 36 | float kick( float time ) { 37 | float amp = exp( -5.0 * time ); 38 | float phase = 50.0 * time 39 | - 10.0 * exp( -70.0 * time ); 40 | return amp * sine( phase ); 41 | } 42 | 43 | // ------ 44 | 45 | vec2 mainSound( float time ) { 46 | float beat = timeToBeat( time ); 47 | float kickTime = beatToTime( mod( beat, 1.0 ) ); 48 | float sidechain = smoothstep( 0.0, 0.4, kickTime ); 49 | 50 | vec2 ret = vec2( kick( kickTime ) ); 51 | ret += sidechain * ( 52 | saw( time * noteToFreq( chord( 0.0 ) ) ) 53 | + saw( time * noteToFreq( chord( 1.0 ) ) ) 54 | + saw( time * noteToFreq( chord( 2.0 ) ) ) 55 | + saw( time * noteToFreq( chord( 3.0 ) ) ) 56 | ) / 4.0; 57 | return ret; 58 | } -------------------------------------------------------------------------------- /4-4_arp.glsl: -------------------------------------------------------------------------------- 1 | #define BPM 140.0 2 | 3 | #define PI 3.141592654 4 | #define TAU 6.283185307 5 | 6 | // ------ 7 | 8 | float timeToBeat( float t ) { return t / 60.0 * BPM; } 9 | float beatToTime( float b ) { return b / BPM * 60.0; } 10 | 11 | float noteToFreq( float n ) { 12 | return 440.0 * pow( 2.0, ( n - 69.0 ) / 12.0 ); 13 | } 14 | 15 | float chord( float n ) { 16 | return ( 17 | n < 1.0 ? 55.0 : 18 | n < 2.0 ? 58.0 : 19 | n < 3.0 ? 62.0 : 20 | 65.0 21 | ); 22 | } 23 | 24 | vec4 noise( float phase ) { 25 | vec2 uv = phase / vec2( 0.512, 0.487 ); 26 | return 2.0 * texture( iChannel0, uv ) - 1.0; 27 | } 28 | 29 | // ------ 30 | 31 | float sine( float phase ) { 32 | return sin( TAU * phase ); 33 | } 34 | 35 | // ------ 36 | 37 | vec2 arp( float note, float time ) { 38 | float freq = noteToFreq( note ); 39 | float fmamp = 0.1 * exp( -50.0 * time ); 40 | float fm = fmamp * sine( time * freq * 7.0 ); 41 | float amp = exp( -20.0 * time ); 42 | return amp * vec2( 43 | sine( freq * 0.99 * time + fm ), 44 | sine( freq * 1.01 * time + fm ) 45 | ); 46 | } 47 | 48 | // ------ 49 | 50 | vec2 mainSound( float time ) { 51 | float beat = timeToBeat( time ); 52 | 53 | float arpTime = beatToTime( mod( beat, 0.25 ) ); 54 | float arpSeed = floor( beat / 0.25 ); 55 | vec4 arpDice = fract( noise( arpSeed ) * 100.0 ); 56 | 57 | float arpNote = chord( floor( 4.0 * arpDice.x ) ); 58 | arpNote += 12.0 * floor( 3.0 * arpDice.y ); 59 | 60 | return vec2( arp( arpNote, arpTime ) ); 61 | } -------------------------------------------------------------------------------- /5-1_finish.glsl: -------------------------------------------------------------------------------- 1 | #define BPM 140.0 2 | 3 | #define PI 3.141592654 4 | #define TAU 6.283185307 5 | 6 | // ------ 7 | // general functions 8 | 9 | float timeToBeat( float t ) { return t / 60.0 * BPM; } 10 | float beatToTime( float b ) { return b / BPM * 60.0; } 11 | 12 | float noteToFreq( float n ) { 13 | return 440.0 * pow( 2.0, ( n - 69.0 ) / 12.0 ); 14 | } 15 | 16 | float chord( float n ) { 17 | return ( 18 | n < 1.0 ? 55.0 : 19 | n < 2.0 ? 58.0 : 20 | n < 3.0 ? 62.0 : 21 | 65.0 22 | ); 23 | } 24 | 25 | vec4 noise( float phase ) { 26 | vec2 uv = phase / vec2( 0.512, 0.487 ); 27 | return 2.0 * texture( iChannel0, uv ) - 1.0; 28 | } 29 | 30 | // ------ 31 | // primitive oscillators 32 | 33 | float sine( float phase ) { 34 | return sin( TAU * phase ); 35 | } 36 | 37 | float saw( float phase ) { 38 | return 2.0 * fract( phase ) - 1.0; 39 | } 40 | 41 | float square( float phase ) { 42 | return fract( phase ) < 0.5 ? -1.0 : 1.0; 43 | } 44 | 45 | // ------ 46 | // drums 47 | 48 | float kick( float time ) { 49 | float amp = exp( -5.0 * time ); 50 | float phase = 50.0 * time 51 | - 10.0 * exp( -70.0 * time ); 52 | return amp * sine( phase ); 53 | } 54 | 55 | vec2 hihat( float time ) { 56 | float amp = exp( -50.0 * time ); 57 | return amp * noise( time * 100.0 ).xy; 58 | } 59 | 60 | // ------ 61 | // synths 62 | 63 | vec2 bass( float note, float time ) { 64 | float freq = noteToFreq( note ); 65 | return vec2( square( freq * time ) + sine( freq * time ) ) / 2.0; 66 | } 67 | 68 | vec2 pad( float note, float time ) { 69 | float freq = noteToFreq( note ); 70 | float vib = 0.2 * sine( 3.0 * time ); 71 | return vec2( 72 | saw( freq * 0.99 * time + vib ), 73 | saw( freq * 1.01 * time + vib ) 74 | ); 75 | } 76 | 77 | vec2 arp( float note, float time ) { 78 | float freq = noteToFreq( note ); 79 | float fmamp = 0.1 * exp( -50.0 * time ); 80 | float fm = fmamp * sine( time * freq * 7.0 ); 81 | float amp = exp( -20.0 * time ); 82 | return amp * vec2( 83 | sine( freq * 0.99 * time + fm ), 84 | sine( freq * 1.01 * time + fm ) 85 | ); 86 | } 87 | 88 | // ------ 89 | // main 90 | 91 | vec2 mainSound( float time ) { 92 | float beat = timeToBeat( time ); 93 | vec2 ret = vec2( 0.0 ); 94 | 95 | // --- 96 | // kick 97 | 98 | float kickTime = beatToTime( mod( beat, 1.0 ) ); 99 | ret += 0.8 * kick( kickTime ); 100 | 101 | float sidechain = smoothstep( 0.0, 0.4, kickTime ); 102 | 103 | // --- 104 | // hihat 105 | 106 | float hihatTime = beatToTime( mod( beat + 0.5, 1.0 ) ); 107 | ret += 0.5 * hihat( hihatTime ); 108 | 109 | // --- 110 | // bass 111 | 112 | float bassNote = chord( 0.0 ) - 24.0; 113 | ret += sidechain * 0.6 * bass( bassNote, time ); 114 | 115 | // --- 116 | // chord 117 | 118 | ret += sidechain * 0.6 * vec2( 119 | pad( chord( 0.0 ), time ) 120 | + pad( chord( 1.0 ), time ) 121 | + pad( chord( 2.0 ), time ) 122 | + pad( chord( 3.0 ), time ) 123 | ) / 4.0; 124 | 125 | // --- 126 | // arp 127 | 128 | float arpTime = beatToTime( mod( beat, 0.25 ) ); 129 | float arpSeed = floor( beat / 0.25 ); 130 | vec4 arpDice = fract( noise( arpSeed ) * 100.0 ); 131 | 132 | float arpNote = chord( floor( 4.0 * arpDice.x ) ); 133 | arpNote += 12.0 * floor( 3.0 * arpDice.y ); 134 | 135 | ret += sidechain * 0.5 * vec2( arp( arpNote, arpTime ) ); 136 | 137 | // --- 138 | 139 | return clamp( ret, -1.0, 1.0 ); 140 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 FMS_Cat 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GLSLで音楽を作ります 2 | 3 | FMS_Cat 4 | 5 | メガデモ勉強会2018, 2018年3月10日 6 | 7 | 全てのGLSLファイルは [Shadertoy](https://www.shadertoy.com/new) でAudioとして実行できます(2018年3月10日現在)。 -------------------------------------------------------------------------------- /slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fms-cat/20180310-glsl-music/6bbcebd614147f25e3211f518e1084b8a7898cd9/slides.pdf --------------------------------------------------------------------------------