Skip to content

KN-86 Voice Bark Recording Guide

Architecture note (ADR-0017): The v1.0 guide described packing bark samples as 4-bit/8kHz data for playback through the YM2149’s Channel C amplitude register. That model is obsolete. ADR-0017 moved YM2149 synthesis to the Pico 2 coprocessor; the MAX98357A receives 16-bit PCM over I2S directly. The kn86bark tool now outputs 16-bit signed PCM at 22,050 Hz. Recording and delivery guidance below remains valid; only the encoding pipeline and storage format differ from v1.0. See docs/software/runtime/pcm-voice-bark.md section 2 for the full technical revision.


The kn86bark tool converts WAV files into 16-bit PCM data for playback through the Pico 2 coprocessor’s I2S audio path (MAX98357A DAC/amplifier). This guide covers how to record voice barks and sound effects that sound right at 22 kHz / 16-bit.

The lo-fi aesthetic is a choice, not a constraint — the Pico/I2S path can deliver clean speech. Lean into the gritty character deliberately.


Terminal window
# Build the tool
cd kn86-emulator/build && cmake .. && make kn86bark
# Convert a WAV (outputs 22 kHz / 16-bit PCM)
./bin/kn86bark ../assets/barks/breach.wav breach.pcm --normalize --preview

This produces:

  • breach.pcm — raw signed 16-bit little-endian PCM at 22,050 Hz
  • A TOML snippet for inclusion in the cartridge’s audio/barks/barks.toml index

  • Microphone: Any USB condenser or dynamic mic. An SM58 is fine. Even a laptop mic works for prototyping.
  • Software: Audacity (free), GarageBand, Logic, Ableton, or any DAW that exports WAV.
  • Room: Quiet room, close-mic distance (4-6 inches). Don’t worry about room treatment — the character of the 28mm speaker through the Pelican case will dominate anyway.

The Cipher voice is a “competent colleague” — terse, clipped, authoritative. Think military radio operator or air traffic controller.

Do:

  • Bark the word. Short, punched, declarative.
  • Use hard consonants: B, D, K, T, CH, P
  • Keep it between 0.3 and 0.7 seconds. If you can’t say it in under a second, pick a shorter word.
  • Speak with conviction. The voice should sound like it has authority.

Don’t:

  • Don’t use a friendly or conversational tone.
  • Don’t whisper — even at 16-bit you need amplitude to punch through a small speaker.
  • Avoid sibilants: S, SH, F, TH — these are less punched through a 28mm speaker. Hard consonants are still preferred.
  • Avoid words that start with soft sounds. “SURFACE” works (hard S attack); “seven” doesn’t (soft S + low vowel).

Words that work best at 22 kHz through a 28mm speaker:

GreatOkayAvoid
BREACHSURFACESHIFT
CLEANLAUNCHFINISH
BURNEDEXITASSESS
CONTACTVOIDTHESIS
DEPTHMATCHFRESH
TRACEDAUDITSOFT
BLOCKEDROUTEFEATHER
PATROLFLAGGEDWHISPER

The pattern: plosive consonants (B, D, K, T, P) at word boundaries, strong vowels in the middle, short duration.

SettingValue
Sample rate44.1 kHz or 48 kHz
Bit depth16-bit or 24-bit
ChannelsMono (or stereo — kn86bark will mixdown)
FormatWAV (uncompressed)

Apply these effects in order before exporting:

  1. Trim silence. Leave ~50ms of silence at head and tail. Remove breaths.
  2. Normalize to -1dB. Get the signal hot without clipping.
  3. High-pass filter at 200Hz. Removes room rumble, plosive pops, and low-frequency mud.
  4. Compress hard.
    • Ratio: 8:1 or higher (limiting)
    • Attack: fast (1-5ms) — catch the transient
    • Release: fast (50-100ms)
    • Threshold: set so you get 6-10dB of gain reduction
    • This squashes the dynamic range so the bark punches through the 28mm speaker’s limited SPL range.
  5. Optional: bitcrush / distortion. Apply a light bitcrush (8-bit or 6-bit) in the DAW if you want the lo-fi aesthetic. This is a deliberate aesthetic choice — kn86bark outputs 16-bit and does not add quantization noise.
  6. Export as WAV. 44.1kHz/16-bit mono.
Terminal window
kn86bark voice.wav voice.pcm --normalize --preview
  • --normalize scales the peak to the full signed 16-bit range. Always use this for voice.
  • --preview plays back through your speakers so you can hear the result immediately.

The feedback loop is:

  1. Record a take in Audacity
  2. Apply processing chain, export WAV
  3. Run kn86bark with --preview
  4. Listen. Is the word recognizable?
  5. If not: try a different delivery (more punch, harder consonants), adjust compression, or pick a different word
  6. Repeat

The success criteria from the spec: “recognizable as the word on first hearing, without accompanying text.”


The kn86bark pipeline converts any WAV to 16-bit/22kHz PCM. Voice barks are the primary use case, but the format works well for mechanical, electronic, and percussive sound effects.

Modem handshake / data transmission

  • Record a real modem dialing sequence, or synthesize one (carrier tones at 1200/2400 Hz, FSK modulation). Audacity’s “Generate > Chirp” can approximate carrier negotiation.
  • The 16-bit path is honest — if you want authentic digital grit, use --bitcrush in your DAW before export rather than relying on quantization noise.
  • Best duration: 0.5-1.0 seconds of the initial handshake screech. Not the full negotiation — just the iconic opening burst.

Hard drive seeking / knocking

  • Option A: Put a contact microphone on an old spinning hard drive and record seek operations. Copy a large directory to trigger sustained seek activity.
  • Option B: Synthesize it. Short noise bursts (10-30ms) with a resonant bandpass filter around 800-1200 Hz, repeated at irregular intervals. Audacity’s noise generator + envelope tool can do this.
  • The clicking, mechanical character survives the 22 kHz path cleanly — these sounds are already bandwidth-limited and transient.
  • Best duration: 0.3-0.5 seconds of seek chatter.

Relay clicks / switching

  • Record a physical relay (toggle a power strip on/off near a mic) or use a short noise transient with fast envelope.
  • These are already nearly single-sample events — they map cleanly to any sample rate.
  • Duration: 0.1-0.2 seconds.

CRT degauss / power-on hum

  • Record a CRT monitor being powered on (the “thunk” of the degauss coil).
  • Or synthesize: 60Hz hum (or 50Hz for PAL regions) with a decaying envelope, mixed with a short low-frequency impulse.
  • Duration: 0.3-0.5 seconds.

Dot matrix printer

  • Record or find a sample of a dot matrix head chattering across a page.
  • The rhythmic, mechanical pattern translates well at 22 kHz.
  • Duration: 0.5-1.0 seconds.

Typewriter / mechanical keyboard

  • Record individual key strikes on a mechanical keyboard (Cherry MX Blue switches are great for this).
  • Each strike is a sharp transient — ideal for PCM playback.
Sound TypeWhy It Fails
Music / melodiesUse the PSG’s tone generators for music — they’re the right tool.
Sustained pads / dronesDuration mismatch: barks are capped at 1.0 second by design.
Speech sentencesToo long, too much tonal variation. Barks are single words for a reason.
Delicate / quiet soundsThe 28mm speaker and the Pelican case will flatten subtle dynamics regardless of bit depth.
Sounds relying on ultrasonic content22 kHz means nothing above 11 kHz is reproduced; most relevant content is well below this.
  • Skip the high-pass filter for SFX that have important low-frequency content (relay thunks, drive motor rumble). The 200Hz HPF is for voice clarity.
  • Use bitcrush in your DAW for digital/electronic sounds if you want quantization grit as an aesthetic — don’t rely on the pipeline to add it at 16-bit.
  • Use a gentle fade-in/out on organic/mechanical sounds (drive seeks, relay clicks) where you want smooth boundaries.
  • Try different sample rates. --rate 44100 gives maximum fidelity; --rate 11025 gives something closer to the old 4-bit character (very lo-fi, potentially interesting for some SFX).
Terminal window
# Modem handshake
kn86bark modem.wav modem.pcm --normalize --preview
# Hard drive seeks
kn86bark hdd_seek.wav hdd_seek.pcm --normalize --preview
# Relay click
kn86bark relay.wav relay.pcm --normalize --preview
# Extra lo-fi
kn86bark modem.wav modem_lo.pcm --normalize --rate 11025 --preview

Part 3: Using Converted Barks in Cartridges

Section titled “Part 3: Using Converted Barks in Cartridges”
[[bark]]
label = "BREACH"
file = "audio/barks/breach.pcm"
rate = 22050
vol = 1.0
[[bark]]
label = "CLEAN"
file = "audio/barks/clean.pcm"
rate = 22050
vol = 1.0
[[bark]]
label = "MODEM"
file = "audio/barks/modem.pcm"
rate = 22050
vol = 0.8
(on-event :node-compromised
(fn (node)
(bark-play "BREACH")
(text-puts 0 12 "> NETWORK COMPROMISED")))

Bark files live as sidecar .pcm files on the cartridge SD filesystem alongside cart.kn86. There is no flash-region constraint (ADR-0019 replaced the on-cart flash model with USB-MSC SD storage).

ContentDurationSize at 22 kHz / 16-bit
Voice bark0.5 sec~22 KB
Modem screech1.0 sec~44 KB
HDD seek burst0.3 sec~13 KB
Relay click0.1 sec~4 KB
8 barks typical0.5 sec avg~176 KB total

At these sizes, storage budget is not a concern — any SD card has headroom to spare. See docs/software/runtime/pcm-voice-bark.md section 2D for the full filesystem layout.


Word is unrecognizable:

  • Try a harder delivery. More punch on the initial consonant.
  • Pick a word with stronger consonants (BREACH instead of FREEZE).
  • Check your compression — if the dynamics aren’t squashed, the quiet parts get lost under the speaker’s background noise floor.
  • Try --rate 44100 for the full sample rate if 22 kHz sounds insufficient.

Too much noise / hiss:

  • Your source recording has a low signal-to-noise ratio. Re-record closer to the mic.
  • Apply noise reduction in your DAW before export.
  • Make sure --normalize is on.

Clicks or pops at boundaries:

  • Ensure ~50ms silence at head/tail of the WAV. Hard cuts at non-zero crossings cause clicks.
  • Apply a 5ms fade-in and fade-out in your DAW.

Preview doesn’t play / crashes:

  • SDL3 audio initialization issue. Check SDL_GetError() output.
  • Some audio backends don’t support 22kHz natively — SDL3 should resample internally, but try --rate 44100 if 22kHz fails.