-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathtabletone.coffee
81 lines (73 loc) · 2.19 KB
/
tabletone.coffee
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
ctx = new (window.AudioContext || window.webkitAudioContext)
audios = []
buffercache = {}
maybeFetch = (src) ->
if buffercache[src]
Promise.resolve(buffercache[src])
else
fetch(src)
.then (response) -> response.arrayBuffer()
.then (audioData) -> new Promise (accept) -> ctx.decodeAudioData audioData, accept
.then (buffer) -> buffercache[src] = buffer; buffer
addAudio = (src) ->
maybeFetch src
.then (buffer) ->
node = ctx.createBufferSource()
node.buffer = buffer
node.loop = true
node.connect ctx.destination
audios.push node
node.start 0, ctx.currentTime % buffer.duration, 2**16 # crbug.com/457099 - offset doesn't work properly
node
removeAudio = (audio) ->
idx = audios.indexOf(audio)
audio.disconnect()
audio.stop(0)
audios.splice(idx, 1) if idx > -1
audio
drawAnalyser = (analyser, pulse) ->
analyser.fftSize = 512
ary = new Float32Array(analyser.fftSize)
min = null
max = null
draw = -> requestAnimationFrame ->
analyser.getFloatTimeDomainData(ary)
avg = 0
avg += Math.abs(val) for val in ary
avg /= ary.length
min = avg if !min || avg < min
max = avg if !max || avg > max
val = Math.round(Math.min((avg-min)/(max-min), 1)*1000)/1000
# console.log "avg", avg, "min", min, "max", max, "max-min", (max-min), "val", val
pulse.style.opacity = 1-val
draw() unless analyser.finished
draw()
addPulseAnalyser = (el) ->
analyser = ctx.createAnalyser()
el.audio.connect(analyser)
el.analyser = analyser
el.innerHTML = ""
pulse = document.createElement 'tt-pulse'
el.appendChild pulse
drawAnalyser analyser, pulse
clickHandler = (e) ->
if @playing
removeAudio @audio
@innerHTML = ""
@analyser?.finished = true
@playing = false
@classList.remove 'playing'
else
addAudio(@src).then (node) =>
@classList.add 'playing'
@audio = node
addPulseAnalyser this if @pulse
@playing = true
do ->
for el in document.querySelectorAll('tt-cell')
continue if el.tabletone
el.tabletone = true
el.src = el.getAttribute('src')
el.pulse = el.getAttribute('pulse')?
el.playing = false
el.addEventListener 'click', clickHandler