Skip to content

squelch-zero/noise

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

noise

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.

Install

Not on npm. Install from git:

npm install github:squelch-zero/noise
# or
pnpm add github:squelch-zero/noise

Functions

noise(text, threshold?, glyphs?)

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'

decay(text, fraction, glyphs?)

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●'

resolve(target, progress, glyphs?)

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'

createResolver(target, glyphs?)

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.'

fill(length, glyphs?)

Generate a string of pure noise.

import { fill } from '@squelch-zero/noise'

fill(20)
// → '╌▒╳░│◆·╍═○╱●∙▓╲◇─┃░'

glyph(set?)

Return a single random glyph.

GLYPHS

The default glyph set: ╌╍═─│┃░▒▓╳╱╲◆◇○●∙·

Box-drawing fragments, shade blocks, geometric shapes. Recognizably "not text" without being distracting.

Properties

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.

Glyph pools

Every function accepts an optional glyphs parameter — a string where each character is a possible noise replacement.

Presets

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

Building your own

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, '█▄▀▌▐')

Curated vs. range-based

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."

Recipes

Typing reveal

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)

Slow decay

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)

Texture background

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))
}

Hover reveal (browser)

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>

See it live

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.

About

Built by Squelch Zero. Extracted from the interactive pieces at squelch-zero.vercel.app — where text is the native medium.

About

Text noise transforms. Corrupt, decay, resolve — character by character.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors