-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathdecoder.html
129 lines (118 loc) · 2.59 KB
/
decoder.html
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
<!DOCTYPE html><html><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>DTMF decoder</title>
<script type="module">
import { DTMF } from "./DTMF.js";
import { FFT } from "./FFT.js";
window.onload = () => {
document.body.onclick = init;
};
const init = async () => {
document.body.onclick = null;
notice.style.display = "none";
const fftsize = 13;
const fft = new FFT();
await fft.init(fftsize);
const g = canvas.getContext('2d')
let buf = fft.getFreqs()
let bkcode = null;
let bkf = null;
const draw = function() {
canvas.width = canvas.clientWidth
canvas.height = canvas.clientHeight
const cw = canvas.width
const ch = canvas.height
const bw = cw / buf.length// * 10
buf = fft.getFreqs()
g.fillStyle = 'rgb(0, 0, 0)'
g.fillRect(0, 0, cw, ch)
let x = 0
for (let i = 0; i < buf.length; i++) {
const n = buf[i]
g.fillStyle = 'hsl(' + n + ',100%,50%)'
g.fillRect(x, ch - n, bw, n)
x += bw
}
const formant = fft.getFormant(buf)
if (formant.length > 1) {
const freq = formant[0][0];
const freq2 = formant[1][0];
const code = DTMF.decode(freq, freq2);
if (bkcode == null && code) {
bkcode = code;
ta.value += code;
}
if (!code) {
bkcode = code;
}
bkf = Math.floor(freq + .5) + "Hz " + Math.floor(freq2 + .5) + "Hz " + code;
} else {
bkf = null;
bkcode = null;
}
//console.log(scale)
g.textAlign = "center"
g.fillStyle = "#fff"
g.font = "20vw sans-serif"
g.textBaseline = "bottom"
// g.fillText(bks, cw / 2, ch / 2)
g.font = "5vw sans-serif"
g.textBaseline = "top"
if (bkf) {
g.fillText(bkf, cw / 2, ch / 2)
}
requestAnimationFrame(draw)
}
draw()
};
btnclear.onclick = () => ta.value = "";
</script>
<style>
body {
margin: 0;
x-background-color: black;
text-align: center;
font-family: sans-serif;
}
#canvas {
x-position: absolute;
width: 100vw;
height: 50vh;
background-color: black;
}
textarea {
width: 90vw;
height: 20vh;
}
button {
width: 50vw;
margin: 1vw;
}
h1 {
}
#notice {
position: absolute;
width: 100vw;
text-align: center;
padding: 30vh 0;
color: white;
}
.src {
margin: 1vh;
}
a {
color: gray !important;
}
</style>
</head>
<body>
<h1>DTMF decoder</h1>
<div id="notice">click to start</div>
<canvas id="canvas" width="640" height="300"></canvas>
<textarea id="ta"></textarea>
<button id="btnclear">clear</button>
<div class=src>
App: CC BY <a href=https://fukuno.jig.jp/3056>taisukef</a><br>
</div>
</body>
</html>