// The surface where to tap const ttt = document.querySelector("#ttt") // The input to store a sequence const s = document.querySelector("#s") let series = [] let initial = null // The function of a tap const tap = () => { if (initial == null) { initial = new Date() series.push(0) } else { series.push((new Date() - initial)) } ttt.innerHTML = series } const stap = () => { if (initial == null) return // insert the final value series.push((new Date() - initial)) // copy the series let sequence = series // reset series and initial date series = [] initial = null return sequence } const audioContext = new AudioContext() const gain = new GainNode(audioContext, { value: 0.05 }) const playNoise = (bandHz=1000, time=0) => { let noiseDuration = 0.05 const bufferSize = audioContext.sampleRate * noiseDuration const noiseBuffer = new AudioBuffer({ length: bufferSize, sampleRate: audioContext.sampleRate }) const data = noiseBuffer.getChannelData(0) for (let i=0; i { const osc = new OscillatorNode(audioContext, { type: "sine", frequency: freq }) osc.connect(gain).connect(audioContext.destination); osc.start() osc.stop(audioContext.currentTime + 0.1) } const seq = (sequence, fn) => { if (!sequence.length) return setTimeout(fn, sequence[0]) let copy = [...sequence] copy.shift() seq(copy,fn) } ttt.addEventListener("click", () => tap()) s.addEventListener("click", () => { let sequence = stap(); let period = sequence.pop() let freq = Math.random() * 1000 seq(sequence, ()=> playOsc(freq)) setInterval(seq, period, sequence, ()=>playOsc(freq)) })