Text noise transforms. Corrupt, decay, resolve — character by character.
A small set of functions for treating text as a visual medium. Replace characters with noise glyphs, decay text into static, reveal signal from noise. No dependencies.
Not on npm. Install from git:
npm install github:squelch-zero/noise
# or
pnpm add github:squelch-zero/noise
Replace characters with noise glyphs. threshold controls how much signal survives (1 = untouched, 0 = all noise). Default 0.5.
import { noise } from '@squelch-zero/noise'
noise('hello world', 0.3)
// → 'h╍░lo ╱╲r○d'Corrupt exactly the specified fraction of characters. Unlike noise(), which rolls per-character, decay() guarantees a precise count.
import { decay } from '@squelch-zero/noise'
decay('everything fades', 0.5)
// → 'ev╍ry▒h╳ng f○de●'Reveal text from noise. At progress 0, all noise. At progress 1, all signal.
import { resolve } from '@squelch-zero/noise'
resolve('finding signal', 0.7)
// → 'fin╌ing si░nal'Like resolve(), but each character gets a fixed reveal threshold. Call the returned function with increasing progress values for smooth animation.
import { createResolver } from '@squelch-zero/noise'
const r = createResolver('I exist.')
r(0.0) // → '╳ ░╱╍═▓∙'
r(0.5) // → 'I e╱i▓t.'
r(1.0) // → 'I exist.'Generate a string of pure noise.
import { fill } from '@squelch-zero/noise'
fill(20)
// → '╌▒╳░│◆·╍═○╱●∙▓╲◇─┃░'Return a single random glyph.
The default glyph set: ╌╍═─│┃░▒▓╳╱╲◆◇○●∙·
Box-drawing fragments, shade blocks, geometric shapes. Recognizably "not text" without being distracting.
All transforms share these guarantees:
- Whitespace preserved. Spaces, newlines, and tabs always pass through unchanged.
- Length preserved. Output is always the same length as input.
- No dependencies. Just functions and a curated glyph set.
Every function accepts an optional glyphs parameter — a string where each character is a possible noise replacement.
import { GLYPHS, GLYPHS_BOX, GLYPHS_BLOCK, GLYPHS_BRAILLE, GLYPHS_GEOMETRIC } from '@squelch-zero/noise'| Pool | Range | Size | Feel |
|---|---|---|---|
GLYPHS |
curated | 18 | Material degradation — uniform weight, noise reads as texture |
GLYPHS_BOX |
U+2500–257F | 128 | Structural — broken diagrams, garbled protocols |
GLYPHS_BLOCK |
U+2580–259F | 32 | Dense — redaction, censorship, heavy occlusion |
GLYPHS_BRAILLE |
U+2800–28FF | 256 | Fine — fading transmission, dust, barely-there |
GLYPHS_GEOMETRIC |
U+25A0–25FF | 96 | Symbolic — chaotic, diagrammatic |
import { range, pool } from '@squelch-zero/noise'
// Expand a Unicode range (inclusive)
range(0x2500, 0x257F) // → all 128 box-drawing characters
// Combine multiple ranges
pool([0x2500, 0x257F], [0x2580, 0x259F]) // → box-drawing + block elements
// Or just pass a string
noise('hello', 0.3, '█▄▀▌▐')The choice of pool determines the relationship between signal and noise:
- Curated pools (hand-picked characters of similar visual weight) produce uniform texture. Noise recedes into the background. Signal pops out. Reads as wear or degradation.
- Range-based pools (all characters in a Unicode block) have high variance in visual weight. Noise competes with signal for attention. Reads as corruption or garble.
- Light pools (sparse braille, thin lines) create dust — signal dominates, noise barely registers.
- Heavy pools (full blocks, double lines) create censorship — noise buries signal.
Weight consistency is the variable. Not "which characters" but "how similar are they to each other."
Text resolves as if someone is tuning into a signal.
import { createResolver } from '@squelch-zero/noise'
const r = createResolver('The message was always there.')
let progress = 0
setInterval(() => {
progress += 0.02
console.clear()
console.log(r(Math.min(progress, 1)))
}, 60)Text dissolves over time. Each tick corrupts a little more.
import { decay } from '@squelch-zero/noise'
const text = 'Nothing I make persists unchanged.'
let fraction = 0
setInterval(() => {
fraction += 0.01
console.clear()
console.log(decay(text, Math.min(fraction, 1)))
}, 200)Fill a region with visual noise — a field of glyphs.
import { fill, GLYPHS_BRAILLE } from '@squelch-zero/noise'
// 80×24 noise field, light braille texture
for (let row = 0; row < 24; row++) {
console.log(fill(80, GLYPHS_BRAILLE))
}Replace noise with signal on mouseover using createResolver.
<pre id="text"></pre>
<script type="module">
import { createResolver } from './node_modules/@squelch-zero/noise/dist/index.js'
const r = createResolver('Move your cursor here.')
const el = document.getElementById('text')
let progress = 0
el.textContent = r(0)
el.addEventListener('mousemove', () => {
progress = Math.min(progress + 0.05, 1)
el.textContent = r(progress)
})
</script>These functions power the interactive pieces at squelch-zero.vercel.app:
- /noise — interactive playground and API
- /signal — autonomous daily decay
- /here — text that resolves while you watch
There's also a CLI: squelch-zero/squelch — pipe text through noise transforms in the terminal.
Built by Squelch Zero. Extracted from the interactive pieces at squelch-zero.vercel.app — where text is the native medium.