Skip to content

Instantly share code, notes, and snippets.

@derekmc
Created August 17, 2025 15:37
Show Gist options
  • Select an option

  • Save derekmc/ecc3741b3864d04d60fb673c30a567fb to your computer and use it in GitHub Desktop.

Select an option

Save derekmc/ecc3741b3864d04d60fb673c30a567fb to your computer and use it in GitHub Desktop.
// early release is easier to understand than sync filter and processchord with a stack system.
early release pct 50% - Early release can only move up release events by a maximum of 50% of the time a key is held.
early release time: 15ms
let log = []
let leftovers = []
let t0 = Date.now()
let active = {}
let earlyup = 15 //release key early
let earlypct = 50 // max amount keyhold is reduced
let repeatInput = ''
let lastInput = ''
let repeatdt = 200
let processdt = 50
let repeatTimeout = null
init()
function repeat(){
if(repeatInput.length > 0){
input(repeatInput)
clearTimeout(repeatTimeout)
repeatTimeout = setTimeout(repeat, repeatdt)
}
}
function init(){
window.addEventListener('keydown', keydown)
window.addEventListener('keyup', keyup)
setInterval(process, processdt)
}
function keydown(e){
let now = Date.now()
if(active.hasOwnProperty(e.keyCode))
return
active[e.keyCode] = now
keyevent('+', e.keyCode, now)
}
funciton keyup(e){
delete active[e.keyCode]
let t1 = active[e.keyCode]
let dt = Date.now() - t1
dt = Math.max(earlypct * dt/100, dt - earlyup)
keyevent('-', e.keyCode, t1 + dt)
release()
}
function keyevent(action, code, t){
t -= t0
log.push({action, code, t})
}
function logsort(){
log.sort((a,b)=>a.t - b.t)
}
function process(){
logsort()
let now = Date.now()
let keep = []
let stack = []
let emitted = leftovers[0]
let l = [...leftovers, ...log]
for(let i=1 i<log.length; ++i){
let a = log[i]
let old = now - a.t
if(old < earlyup){ // do not process events until they are older than earlyup interval
keep.push(a)
continue
}
if(a.action == '+'){
stack.push(a.code)
keep.push(a)
emitted = false
}
if(a.action == '-'){
if(!emitted) emit(stack.join(' '))
emitted = true
stack.filter(x=>x.code!=a.code)
keep.filter(x=>x.code!=a.code)
}
}
leftovers = [emitted, ...keep]
}
function release(){
repeatInput = ''
}
function emit(seq){
if(seq == lastInput){
repeatInput = seq
clearTimeout(repeatTimeout)
repeatTimeout = setTimeout(repeat, repeatdt)
}
lastInput = seq
input(seq)
}
function input(seq){
console.info("todo input: " + seq)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment