summaryrefslogtreecommitdiff
path: root/client/index.js
blob: 6e348cddd1245d4cec16bb7f6dd6709d3d9d1c3e (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
import Tone from 'tone'
import keys from './lib/keys'
import color from './lib/color'
import { browser, requestAudioContext, clamp, firstTouch } from './lib/util'

const compressor = new Tone.Compressor(-30, 3).toMaster()

const GRAIN_TIME = 1/2
const SAMPLE_RATE = 44100
const GRAIN_SIZE = GRAIN_TIME * SAMPLE_RATE

requestAudioContext( () => {
  const clock = new Tone.Clock(tick, 1/GRAIN_TIME)
  clock.start()
  console.log('ready')
})

let offsets = []

let player = new Tone.MultiPlayer({
  applause: 'applause.mp3',
}, () => {
  let data = player.buffers.get('applause').get().getChannelData(0)
  let intensities = []
  for (let i = 0, len = Math.floor(data.length / GRAIN_SIZE); i < len; i++) {
    let z = 0
    for (let j = i * GRAIN_SIZE, max = (i+1) * GRAIN_SIZE; j < max; j++) {
      z += Math.abs(data[j])
    }
    intensities[i] = [z / GRAIN_SIZE, i]
  }
  offsets = intensities.sort( (a,b) => a[0] < b[0] ? -1 : a[0] == b[0] ? 0 : 1 )
    .map( (a,i) => {
      return a[1]
    })
})

player.fadeIn = 0.25
player.fadeOut = 0.25
player.connect(compressor)

let intensity = 0, inertialIntensity = 0, inertia = 5

function tick (time) {
  if (! offsets.length) return
  // let offsetIndex = clamp( Math.floor(mouse.y * offsets.length + Math.cos(time/20)), 0, offsets.length-1 )
  inertialIntensity = Math.max(intensity, (intensity + inertialIntensity*(inertia-1))/inertia)
  console.log(inertialIntensity)
  let offsetIntensity = 0.98 * inertialIntensity
  let offsetIndex = Math.floor(offsetIntensity * offsets.length + Math.cos(time))
  let offset = Math.max((offsets[offsetIndex] || 0) * GRAIN_TIME + ( 0.25 * Math.sin(time*17/7) ), 0)
  // console.log(offset, offsets[offsetIndex] * GRAIN_TIME, ( 0.25 * Math.cos(time*13/7)))
  player.start('applause', time, offset, GRAIN_TIME * 4, 0, inertialIntensity)
}

let mouse = { x: 0, y: 0 }
let drawing = false
let canvas = document.createElement('canvas')
canvas.width = window.innerWidth
canvas.height = window.innerHeight
let ctx = canvas.getContext('2d')
document.body.appendChild(canvas)

function down (e) {
  drawing = true
  mouse.x = e.pageX / window.innerWidth
  mouse.y = e.pageY / window.innerHeight
}
function move (e){
  const x = e.pageX / window.innerWidth
  const y = e.pageY / window.innerHeight
  const dx = (mouse.x - x)
  const dy = (mouse.y - y)
  const v = Math.sqrt(dx*dx+dy*dy)
  if (drawing) {
    intensity = Math.min(0.999, intensity + v*0.1)
    inertialIntensity = Math.min(0.999, intensity)
    if (intensity == 0.999) intensity -= (Math.random() * 0.45)
    if (inertialIntensity == 0.999) inertialIntensity -= (Math.random() * 0.35)
    const gray = Math.floor( clamp(1-(10*v),0,1)*255 )
    ctx.fillStyle = 'rgb(' + [gray,gray,gray] + ')'
    ctx.beginPath()
    ctx.arc( x*window.innerWidth, y*window.innerHeight, v*500, 0, Math.PI*2 )
    ctx.fill()
  }
  mouse.x = x
  mouse.y = y
}
function up (e) {
  drawing = false
  intensity = 0
}
setInterval( () => {
  inertialIntensity += 0.001
}, 5000)

if (browser.isMobile) {
  document.body.addEventListener('touchstart', firstTouch(down))
  document.body.addEventListener('touchmove', firstTouch(move))
  window.addEventListener('touchend', firstTouch(up))
}
else {
  document.body.addEventListener('mousedown', down)
  document.body.addEventListener('mousemove', move)
  window.addEventListener('mouseup', up)
}

function animate(){
  requestAnimationFrame(animate)
  ctx.save()
  ctx.fillStyle='rgba(255,255,255,' + (1-(intensity || 0.01)) + ')'
  ctx.globalAlpha = 0.001
  ctx.fillRect(0,0,window.innerWidth,window.innerHeight)
  ctx.restore()
}
animate()