generated from stagas/ts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathx-oscilloscope.tsx
91 lines (78 loc) · 2.16 KB
/
x-oscilloscope.tsx
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
/** @jsxImportSource sigl */
import $ from 'sigl'
import { PlotElement } from 'x-plot'
import { Stabilizer } from './stabilizer'
export interface OscilloscopeElement extends $.Element<OscilloscopeElement> {}
@$.element()
export class OscilloscopeElement extends HTMLElement {
@$.attr() autoResize = true
@$.attr() width = 150
@$.attr() height = 50
@$.attr() background = '#123'
@$.attr() color = '#1ff'
@$.attr() divider = 1
analyser?: AnalyserNode
analyserData?: Float32Array
Plot = $.element(PlotElement)
plotData = new Float32Array([0])
stabilizer = new Stabilizer()
draw?: () => void
loop?: {
start(): void
stop(): void
}
/**
* Start displaying the spectrum.
*/
start() {
this.loop?.start()
}
/**
* Stop displaying the spectrum.
*/
stop() {
this.loop?.stop()
}
mounted($: OscilloscopeElement['$']) {
let animFrame: any
$.analyserData = $.reduce(({ analyser }) => new Float32Array(analyser.frequencyBinCount))
let piece = 0
$.draw = $.reduce(({ analyser, analyserData, divider, stabilizer }) => (function draw() {
animFrame = requestAnimationFrame(draw)
if (divider === 1 || !piece)
analyser.getFloatTimeDomainData(analyserData)
let data
if (divider > 1) {
const half = analyserData.length / divider
piece = (piece + 1) % divider
data = analyserData.slice(piece * half, piece * half + half)
} else {
data = analyserData
}
const startIndex = stabilizer.findStartingPoint(data)
$.plotData = data.slice(startIndex, startIndex + analyser.frequencyBinCount / divider * 0.5)
}))
$.loop = $.reduce(({ draw }) => ({
start() {
animFrame = requestAnimationFrame(draw)
},
stop() {
cancelAnimationFrame(animFrame)
},
}))
$.effect(({ loop }) => {
loop.start()
return () => loop.stop()
})
$.render(({ Plot, autoResize, width, height, background, color, plotData }) => (
<Plot
autoResize={autoResize}
data={plotData}
width={width}
height={height}
background={background}
color={color}
/>
))
}
}