summaryrefslogtreecommitdiff
path: root/app/client/audio/lib/draw.js
blob: e523b6ad73572e9a25fdcf14b18eef3bb0408c7f (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
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 }
}