summaryrefslogtreecommitdiff
path: root/client/lib/spectrum.js
diff options
context:
space:
mode:
Diffstat (limited to 'client/lib/spectrum.js')
-rw-r--r--client/lib/spectrum.js89
1 files changed, 89 insertions, 0 deletions
diff --git a/client/lib/spectrum.js b/client/lib/spectrum.js
new file mode 100644
index 0000000..2b30792
--- /dev/null
+++ b/client/lib/spectrum.js
@@ -0,0 +1,89 @@
+import Tone from 'tone'
+
+import output from './output'
+
+const signalWindows = require('signal-windows').windows
+const FFTJS = require('fft.js')
+
+const fft_size = 2 << 10
+const fft_overlap = fft_size / 4
+const half_fft_size = fft_size / 2
+
+const fft = new FFTJS(fft_size)
+
+function toSpectrum(pcm, sr){
+ sr = sr || 44100
+ const ham = signalWindows.construct('ham', fft_size)
+ const pcm_in = new Array(fft_size)
+ const pcm_length = pcm.length
+ const pcm_q_length = Math.ceil(pcm_length / fft_size) * fft_size
+ let i, j, fft_out, data = [];
+ for (i = -fft_size; i < pcm_q_length; i += fft_overlap) {
+ for (j = 0; j < fft_size; j++) {
+ pcm_in[j] = pcm[i+j] * ham[j] || 0
+ }
+ fft_out = fft.createComplexArray()
+ fft.realTransform(fft_out, pcm_in)
+ fft.completeSpectrum(fft_out)
+ data.push(fft_out)
+ }
+ return {
+ data,
+ sr,
+ fft_size,
+ fft_overlap,
+ }
+}
+
+function fromSpectrum(spec){
+ const data = spec.data
+ const sr = spec.sr
+ const fft_size = spec.fft_size
+ const fft_overlap = spec.fft_overlap
+ const spec_len = data.length
+
+ const ham = signalWindows.construct('ham', fft_size)
+ const out = fft.createComplexArray()
+ const pcm_length = fft_overlap * spec_len
+
+ const audioBuffer = Tone.context.createBuffer(1, pcm_length, sr)
+ const pcm = audioBuffer.getChannelData(0);
+
+ let i, j, u, v, _r, _i, col
+
+ for (i = 0; i < spec_len; i++) {
+ col = data[i]
+ fft.inverseTransform(out, col)
+ u = i * (fft_overlap)
+ // for (j = fft_size * 1/4; j < fft_size * 3/4; j++) {
+ // pcm[u+j] = out[j*2] / ham[j] || 0
+ // }
+ for (j = 0; j < fft_size; j++) {
+ pcm[u+j] += out[j*2] * ham[j] || 0
+ }
+ }
+
+ fadeInOut(pcm, fft_size)
+
+ return audioBuffer
+}
+
+function fadeInOut(pcm, fade_size){
+ const pcm_length = pcm.length
+ let fade = 0, i
+ for (i = 0; i < fade_size; i++) {
+ fade = i / (fade_size)
+ fade *= fade
+ pcm[i] *= fade
+ pcm[pcm_length - i] *= fade
+ }
+}
+function fadeOut(pcm){
+
+}
+
+export default {
+ toSpectrum,
+ fromSpectrum
+}
+