import Tone from 'tone' import Sampler from './lib/sampler' import draw from './draw' import keys from './lib/keys' import color from './lib/color' import mouse from './lib/mouse' import { Hall } from './lib/hall' import { browser, requestAudioContext, randint, randrange, choice, clamp, lerp, dist, shuffle, isMobile, } from './lib/util' const root = 440 const s = 50 const w = window.innerWidth const h = window.innerHeight const ws = w/s, hs = h/s const HALLWAY_LENGTH = 147 const SPEAKER_COUNT = 16 let notes = [299, 336, 374, 399, 449, 498, 561, 598].map(i => i/2) notes = notes.concat(notes.map(i => i/2)) notes = notes.concat(notes.map(i => i*2)) notes = shuffle(notes) let samplers = {} let sampler requestAudioContext( () => { samplers.smash = new Sampler('samples/smash/g{}.mp3', 12) samplers.glass = new Sampler('samples/glass/0{}Particle.mp3', 20) samplers.kalimba = new Sampler('samples/kalimba/380731__cabled-mess__sansula-08-c-raw.wav', 10) samplers.choice = (m,n) => { const r = Math.random() if (r < m) return samplers.smash if (r < m+n) return samplers.kalimba return samplers.glass } Tone.Buffer.on('load', function(){ console.log('all buffers are loaded.') redraw() }) }) const hall = new Hall ({ length: HALLWAY_LENGTH, speakers: SPEAKER_COUNT, }) let last_index = 0, last_dist = 0 keys.listen(index => { trigger(Math.random(), ((index+7) % SPEAKER_COUNT) / SPEAKER_COUNT, 0, samplers.smash) }) function redraw(){ draw.clear() draw.line(50/147 * window.innerHeight) draw.line(100/147 * window.innerHeight) hall.speakers.forEach(speaker => { draw.ctx.save() draw.ctx.globalAlpha = 1 - speaker.z / HALLWAY_LENGTH draw.dot( window.innerWidth / 2 - speaker.pan * window.innerHeight, speaker.z / HALLWAY_LENGTH * window.innerHeight, 10 ) draw.dot( window.innerWidth / 2 + speaker.pan * window.innerHeight, speaker.z / HALLWAY_LENGTH * window.innerHeight, 10 ) draw.ctx.restore() }) } mouse.register({ down: (x, y) => { px = x py = y x /= window.innerWidth y /= window.innerHeight redraw() trigger(x, y) }, move: (x, y, dx, dy) => { last_dist = dist(x,y,px,py) if (last_dist < 5) { return } px = x py = y x /= window.innerWidth y /= window.innerHeight play(x, y) }, up: (x, y) => { }, }) let timeout, px = 0, py = 0 function play(x, y){ const count = 3 const dt = 0.25 trigger(x, y, 0) } function trigger(x, y, t, sampler){ t = t || 0 t += Tone.now() sampler = sampler || last_dist > 40 ? samplers.choice(0.2, 0.2) : samplers.choice((1-y) * 0.2, y*0.02) const freq = notes[Math.floor(x * notes.length)] const speaker = hall.play(sampler, y, freq, x, t) draw.triangle( lerp(x, 0, 1) * window.innerWidth, lerp(y, 0, 1) * window.innerHeight - 20, 40 ) }