diff options
Diffstat (limited to 'client')
| -rw-r--r-- | client/draw.js | 73 | ||||
| -rw-r--r-- | client/index.js | 7 | ||||
| -rw-r--r-- | client/lib/color.js | 31 |
3 files changed, 87 insertions, 24 deletions
diff --git a/client/draw.js b/client/draw.js index a9c182d..3dab322 100644 --- a/client/draw.js +++ b/client/draw.js @@ -1,6 +1,10 @@ +import Tone from 'tone' + +import output from './lib/output' + import { browser, requestAudioContext, - randint, randrange, clamp, + randint, randrange, clamp, mod, } from './lib/util' import mouse from './lib/mouse' @@ -49,7 +53,7 @@ function triangle(px,py,r){ function tri(px, py, r) { ctx.save() ctx.globalCompositeOperation = 'multiply' - ctx.fillStyle = color((px+py)/(w+h), 0, 1, 1) + ctx.fillStyle = color.color((px+py)/(w+h), 0, 1, 1) function p(){ let theta = randrange(0, Math.PI*2) let x = px + Math.cos(theta) * r @@ -118,7 +122,9 @@ function waveform(pcm, sr, pos, zoom){ const signalWindows = require('signal-windows').windows const FFTJS = require('fft.js') -const fft_size = 1024 +const fft_size = 2048 +const fft_overlap = fft_size / 4 +const half_fft_size = fft_size / 2 const fft = new FFTJS(fft_size) function toSpectrum(pcm){ @@ -126,19 +132,40 @@ function toSpectrum(pcm){ 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, spec = []; - for (i = 0; i < pcm_q_length; i += fft_size/4) { + for (i = 0; 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) spec.push(fft_out) } - return spec } +function fromSpectrum(spec, sr){ + const spec_len = spec.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 = spec[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 + } + } + const player = new Tone.Player(audioBuffer) + player.connect(output) + player.start(Tone.now() + pcm_length / sr) + // console.log(Tone.now() + pcm_length / sr) + return audioBuffer +} function spectrum(pcm, sr){ sr = sr || 44100 const spec = toSpectrum(pcm) @@ -147,29 +174,32 @@ function spectrum(pcm, sr){ const scratch = document.createElement('canvas') scratch.width = spec.length - scratch.height = fft_size + scratch.height = half_fft_size const scratchCtx = scratch.getContext('2d') var imageData = ctx.createImageData(scratch.width, scratch.height) var data = imageData.data - let i, j, u, v, _r, _i, col, spec_len = spec.length + let i, j, u, v, _r, _i, col, hsl, spec_len = spec.length for (i = 0; i < spec_len; i++) { col = spec[i] - for (j = 0; j < fft_size; j++) { - u = (j * spec_len + i) * 4 + + for (j = 0; j < half_fft_size; j++) { + u = ((half_fft_size - j) * spec_len + i) * 4 v = j * 2 _r = col[v] - _i = col[v+1] + _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 - data[u] = _r * 127 + 127 - // green - imag part - data[u+1] = _i * 127 + 127 - // blue - magnitude - data[u+2] = Math.sqrt(Math.pow(_r, 2) + Math.pow(_i, 2)) * 128 + 127 - // data[u] = 128 - // data[u+1] = 128 - data[u+2] = 128 + // data[u] = _r * 127 + 127 + // // green - imag part + // data[u+1] = _i * 127 + 127 + // // blue - magnitude + // data[u+2] = Math.sqrt(Math.pow(_r, 2) + Math.pow(_i, 2)) * 128 + 127 + // data[u+3] = 255 + data[u] = hsl[0] + data[u+1] = hsl[1] + data[u+2] = hsl[2] data[u+3] = 255 } } @@ -180,7 +210,7 @@ function spectrum(pcm, sr){ var pixels_per_second = 1024 const width = Math.round(pcm_length / sr * pixels_per_second) // ok not really this - const height = Math.floor(h*3/4) + const height = Math.floor(h*2/3) const x0 = 0 const y0 = Math.floor(h/4) + 20 @@ -188,6 +218,9 @@ function spectrum(pcm, sr){ ctx.drawImage(scratch, x0, y0, width, height) ctx.restore() + + const new_pcm = fromSpectrum(spec, sr) + console.log(new_pcm) } export default { diff --git a/client/index.js b/client/index.js index b1351fc..7a01b55 100644 --- a/client/index.js +++ b/client/index.js @@ -6,6 +6,7 @@ import draw from './draw' import keys from './lib/keys' import color from './lib/color' import mouse from './lib/mouse' +import output from './lib/output' import { Hall } from './lib/hall' @@ -60,13 +61,13 @@ function redraw(){ keys.listen(index => { // trigger(Math.random(), ((index+7) % SPEAKER_COUNT) / SPEAKER_COUNT, 0, samplers.smash) - const sample = samplers.smash.choice() - const buf = sample.players[0]._buffer.get() + const sample = samplers.smash.play(100, Tone.now(), output) + console.log(Tone.now()) + const buf = sample._buffer.get() if (! buf) return const pcm = buf.getChannelData(0) const sr = buf.sampleRate const duration = buf.duration - console.log(buf) console.log(duration.toFixed(2) + " s.") draw.clear() draw.waveform(pcm) diff --git a/client/lib/color.js b/client/lib/color.js index 5f873b3..4299c4b 100644 --- a/client/lib/color.js +++ b/client/lib/color.js @@ -30,4 +30,33 @@ function color (t, add, mul, alpha) { return 'rgba(' + rgb + ',' + alpha + ')' } -export default color +function hsl2rgb (H, S, L) { + var R,G,B; + var var_1, var_2; + if ( S == 0 ) { //HSL from 0 to 1 + R = L * 255 //RGB results from 0 to 255 + G = L * 255 + B = L * 255 + } + else { + if ( L < 0.5 ) var_2 = L * ( 1 + S ) + else var_2 = ( L + S ) - ( S * L ) + + var_1 = 2 * L - var_2 + + R = 255 * hue2rgb( var_1, var_2, H + ( 1 / 3 ) ) + G = 255 * hue2rgb( var_1, var_2, H ) + B = 255 * hue2rgb( var_1, var_2, H - ( 1 / 3 ) ) + } + return [R,G,B] +} +function hue2rgb( v1, v2, vH ) { + if ( vH < 0 ) vH += 1 + if ( vH > 1 ) vH -= 1 + if ( ( 6 * vH ) < 1 ) return ( v1 + ( v2 - v1 ) * 6 * vH ) + if ( ( 2 * vH ) < 1 ) return ( v2 ) + if ( ( 3 * vH ) < 2 ) return ( v1 + ( v2 - v1 ) * ( ( 2 / 3 ) - vH ) * 6 ) + return ( v1 ) +} + +export default { color, hsl2rgb } |
