You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
132 lines
2.8 KiB
JavaScript
132 lines
2.8 KiB
JavaScript
const audioContext = new AudioContext();
|
|
|
|
const tap = document.querySelector('.container')
|
|
const address = document.querySelector('#address').innerHTML
|
|
|
|
const socket = new ReconnectingWebSocket(
|
|
location.origin.replace(/^http/, "ws") + address
|
|
|
|
);
|
|
|
|
socket.onopen = (event) => {
|
|
socket.send(JSON.stringify({ type: "hello" }));
|
|
console.log("Connected as destination!");
|
|
};
|
|
|
|
|
|
|
|
|
|
let noiseDuration = 0.05
|
|
const playNoise = (bandHz = 1000, time = 0) => {
|
|
|
|
const bufferSize = audioContext.sampleRate * noiseDuration
|
|
|
|
// Create an empty buffer
|
|
const noiseBuffer = new AudioBuffer({
|
|
length: bufferSize,
|
|
sampleRate: audioContext.sampleRate,
|
|
})
|
|
|
|
// Fill the buffer with noise
|
|
const data = noiseBuffer.getChannelData(0);
|
|
for (let i = 0; i < bufferSize; i++) {
|
|
data[i] = Math.random() * 2 - 1;
|
|
}
|
|
|
|
// Create a buffer source from data
|
|
const noise = new AudioBufferSourceNode(audioContext, {
|
|
buffer: noiseBuffer,
|
|
})
|
|
|
|
// Filter the output
|
|
const bandpass = new BiquadFilterNode(audioContext, {
|
|
type: "bandpass",
|
|
frequency: bandHz
|
|
})
|
|
|
|
noise.connect(bandpass).connect(audioContext.destination);
|
|
noise.start(time);
|
|
|
|
}
|
|
|
|
|
|
const playPulse = (freq=440, lfoFreq=30, duration=1, time=0) => {
|
|
|
|
const osc = new OscillatorNode(audioContext, {
|
|
type: "square",
|
|
frequency: freq
|
|
})
|
|
|
|
const amp = new GainNode(audioContext, {
|
|
value: 0
|
|
})
|
|
|
|
const lfo = new OscillatorNode(audioContext, {
|
|
type: "sine",
|
|
frequency: lfoFreq
|
|
})
|
|
|
|
lfo.connect(amp.gain)
|
|
osc.connect(amp).connect(audioContext.destination)
|
|
lfo.start()
|
|
osc.start(time)
|
|
// osc.stop(time + duration)
|
|
|
|
}
|
|
|
|
|
|
const spawnGradient = (x, y) => {
|
|
const gradient = document.createElement('div')
|
|
gradient.classList.add('gradient')
|
|
gradient.style.translate = `${x}px ${y}px`
|
|
gradient.style.scale = 0
|
|
|
|
let red = x / tap.clientWidth * 255
|
|
let green = y / tap.clientHeight * 255
|
|
let blue = 0
|
|
|
|
gradient.style.background = `radial-gradient(circle, rgba(${red},${green},${blue},1) 0%, rgba(${red},${green},${blue},0) 25%)`
|
|
|
|
tap.appendChild(gradient)
|
|
grow(gradient)
|
|
|
|
}
|
|
|
|
const grow = (el) => {
|
|
let scale = Number(el.style.scale) || 0
|
|
el.style.scale = scale + 0.1
|
|
requestAnimationFrame(()=> grow(el))
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const emit = (x, y) => {
|
|
playPulse(x, y * 0.01)
|
|
spawnGradient(x, y)
|
|
}
|
|
|
|
|
|
const join = document.querySelector('#join')
|
|
join.addEventListener('click', ()=>{
|
|
playNoise()
|
|
})
|
|
|
|
|
|
|
|
|
|
socket.onmessage = (event) => {
|
|
let message;
|
|
try {
|
|
message = JSON.parse(event.data);
|
|
} catch (e) {}
|
|
|
|
console.log("received a message! ", message)
|
|
if (message?.type == 'pulse'){
|
|
emit(message.x, message.y)
|
|
}
|
|
};
|
|
|
|
|