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
131
132
133
134
|
const scratch = document.createElement('canvas')
const scratchCtx = scratch.getContext('2d-lodpi')
export function spectrum(spec, x0, y0, ww, hh){
const data = spec.data
const fft_size = spec.fft_size
const half_fft_size = spec.fft_size / 2
const spec_len = data.length
scratch.width = data.length
scratch.height = half_fft_size
var imageData = ctx.createImageData(scratch.width, scratch.height)
var pixels = imageData.data
let i, j, u, v, _r, _i, col, hsl
for (i = 0; i < spec_len; i++) {
col = data[i]
for (j = 0; j < half_fft_size; j++) {
u = ((half_fft_size - j) * spec_len + i) * 4
v = j * 2
_r = col[v]
_i = mod(col[v+1], Math.PI*2) / (Math.PI*2)
hsl = color.hsl2rgb((_i + 1) / 2, 1.0, 1 - Math.abs(_r / 10))
// red - real part
// pixels[u] = _r * 127 + 127
// // green - imag part
// pixels[u+1] = _i * 127 + 127
// // blue - magnitude
// pixels[u+2] = Math.sqrt(Math.pow(_r, 2) + Math.pow(_i, 2)) * 128 + 127
// pixels[u+3] = 255
pixels[u] = hsl[0]
pixels[u+1] = hsl[1]
pixels[u+2] = hsl[2]
pixels[u+3] = 255
}
}
scratchCtx.putImageData(imageData, 0, 0)
var pcm_length = spec.fft_overlap * spec_len
x0 = x0 * devicePixelRatio || 0
y0 = y0 * devicePixelRatio || Math.floor(h/4)
ww = ww * devicePixelRatio || w
hh = hh * devicePixelRatio || h/4
const width = Math.round(pcm_length / spec.sr * pixels_per_second)
const height = Math.floor(hh)
ctx.save()
clear(1, x0, y0, w, height)
ctx.drawImage(scratch, x0, y0, width, height)
ctx.restore()
}
export function raw_spectrum(spec, x0, y0, ww, hh, def_min_r, def_min_i){
const data = spec.data
const fft_size = spec.fft_size
const half_fft_size = spec.fft_size / 2
const spec_len = data.length
const _scratch = document.createElement('canvas')
const _scratchCtx = _scratch.getContext('2d-lodpi')
_scratch.width = data.length
_scratch.height = half_fft_size
// console.log("spectrum w/h:", _scratch.width, _scratch.height)
var imageData = _scratchCtx.createImageData(_scratch.width, _scratch.height)
var pixels = imageData.data
let i, j, u, v, _r, _i, col, hsl
// let min_r = Infinity, max_r = -Infinity
// let min_i = Infinity, max_i = -Infinity
// determined empirically..
// let min_r = -60.4894057005308
// let max_r = 107.23800966675353
// let min_i = -59.4894057005308
// let max_i = 108.23800966675353
let min_r = -def_min_r
let max_r = def_min_r
let min_i = -def_min_i
let max_i = def_min_i
let delta_r = max_r - min_r
let delta_i = max_i - min_i
let mean_r = 0
let mean_i = 0
let sum_mean_r = 0, sum_mean_i = 0
let real, imag
for (i = 0; i < spec_len; i++) {
col = data[i]
mean_r = 0
mean_i = 0
for (j = 0; j < half_fft_size; j++) {
u = (j * spec_len + i) * 4
v = j * 2
real = col[v]
imag = col[v+1]
mean_r += real
mean_i += imag
_r = clamp((real - min_r) / delta_r * 255, 0, 255)
_i = clamp((imag - min_i) / delta_i * 255, 0, 255)
// hsl = color.hsl2rgb((_i + 1) / 2, 1.0, 1 - Math.abs(_r / 10))
pixels[u+0] = _r
pixels[u+1] = _i
pixels[u+2] = 127 // hsl[2]
pixels[u+3] = 255
// min_r = Math.min(min_r, col[v])
// max_r = Math.max(max_r, col[v])
// min_i = Math.min(min_i, col[v]+1)
// max_i = Math.max(max_i, col[v]+1)
}
mean_r /= half_fft_size
mean_i /= half_fft_size
sum_mean_r += mean_r
sum_mean_i += mean_i
}
sum_mean_r /= spec_len
sum_mean_i /= spec_len
// console.log(sum_mean_r, sum_mean_i)
// console.log("r:", min_r, max_r)
// console.log("i:", min_i, max_i)
_scratchCtx.putImageData(imageData, 0, 0)
return { canvas: _scratch, imageData }
}
|