summaryrefslogtreecommitdiff
path: root/client/index.js
blob: 097c7ab1e35e8352fd95c03b411efa83915fd1df (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
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
  )
}