Anti examples Keys Click anywhere to arm sound
example / keys

Typing, and taking it back.

Every character speaks at its own pitch. Backspace is the only sound in the grammar that runs backwards.

01

Type into it

Then hold backspace and hear the difference. Enter commits; escape rejects and clears.

Last eventnone
Rung-
const pitch = (ch) => {
  const c = ch.toLowerCase()
  // a is the bottom rung, z the top
  if (c >= 'a' && c <= 'z') return (c.charCodeAt(0) - 97) / 25
  if (c >= '0' && c <= '9') return (c.charCodeAt(0) - 48) / 9
  // space and punctuation are the gaps between
  // words, so they sit low and stay out of the way
  return 0.15
}

// A character arrives: the positional micro event,
// quieter and shorter than a grab. It is the most
// fired sound in any real interface.
Anti.play('tick', { value: pitch(ch) })

// A character leaves: fired at the pitch of the
// character being removed, not the one left behind.
Anti.play('undo', { value: pitch(removed) })
02

Why undo is its own event

Ten of the eleven events attack, then decay. Undo runs the other way: it swells in slowly, bends down an octave (both endpoints on the ladder), and seats fast, so a deletion reads as an insertion in reverse.

No forward sound can say "taken back". Buttons, layers, forms, motion, and voice all map onto existing events; typing needed a new one.

The same rung, forwards and backwards: same length, similar loudness, the energy at opposite ends.

// tick:  attack, then decay.
// undo:  swell, bend down an octave, seat.
//
// One is the time mirror of the other, which is
// why a deletion does not need a new metaphor:
// it is the insertion, run the other way.

Anti.play('tick', { value: 0.6 })
Anti.play('undo', { value: 0.6 })