Case study
KLATS — Four Everyday Sounds Become a Beat
A mobile app that records four sounds from whatever is around you — a mug, a clap, keys, a voice — gives them musical roles and renders a finished beat with a vertical video. Analysis, arrangement and encoding all happen on the phone.

Overview
Project overview
KLATS turns four short recordings into a 10–20 second track and a 9:16 video, without an account, a server or a single upload. The DSP core is a TypeScript library that also runs as a desktop CLI: the algorithm is debugged where an iteration takes seconds, and the phone imports that same file through Metro rather than a copy of it. The app is Expo SDK 57; the only native code is the video encoder, because no JavaScript package can write an MP4.
ROLE
End-to-end product engineering: DSP core (TypeScript), Expo app, native video module (Kotlin + Swift), monetisation and store release
TIMELINE
2026
FOCUS
- One core, shared — the CLI and the phone run the same file
- Recordings stay on the device — no account, no server
- Bit-exact determinism: one seed, one beat
- A render that never freezes the interface
- Monetisation rules decided at export, in one function
Story
Problem → Solution → Outcome
PROBLEM
Making a beat means owning a DAW and knowing what BPM, a key and a compressor are. The people who fill TikTok, Reels and Shorts have none of that — but they do have a mug, a set of keys and a phone, and no way to turn the sound of them into music worth posting.
SOLUTION
KLATS asks for four taps and nothing else. The core cleans each recording, measures twenty features, scores every permutation of roles and builds an arrangement around what it actually heard: the root note comes from the user’s own voice, the kick from whatever had the low end. The staged renderer keeps the interface alive while it works, a native module encodes the vertical clip from a storyboard computed in TypeScript, and a single function decides resolution and watermark at the moment of export.
OUTCOME
A person with no musical training gets a finished track and a 9:16 clip in under a minute, from sounds that are still recognisably theirs. The recordings never leave the phone, there is no backend to run, and the algorithm that carries the product is one tested file shared by the desktop CLI and both mobile platforms.
Highlights
What we built
Key systems shipped end-to-end — designed for reliability, conversion, and scale.
One core, two runtimes
The algorithm lives in one place and is debugged where iteration is cheap.
- Metro resolves @klats/core to the CLI project — an alias, not a copy.
- A change is heard in the CLI in seconds, then runs on the phone unchanged.
- Golden tests therefore guard the phone, not just the prototype.
A render that yields
Generating a beat is seconds of arithmetic on the JS thread — so it hands the thread back.
- renderBeatStaged is a generator with 65 yield points; the engine releases the thread between them.
- The longest uninterrupted chunk is 8 % of the work instead of 100 %.
- A test compares the staged render to the synchronous one sample by sample — the sound is identical.
Density on purpose
The first version sounded thin, and that was a list of systemic gaps rather than bad luck.
- A dedicated bass part and a root note taken from the user’s own recording.
- Ghost notes, rolls, flams and a variation every fourth bar: 88 events became 137, and 235 in DnB.
- Stereo by groups with the low end centred — the clip is judged on a single phone speaker.
Monetisation decided at export
Quality and watermark are one function in the core, not a setting read from disk.
- Free exports 720×1280 and always carries the mark; Pro unlocks 1080×1920 and can drop it.
- A “1080p” chosen while Pro cannot survive a refund — the rule is applied at export time.
- Ads never block a save: if the SDK is missing or the show fails, the clip is still written.
Pipeline
How it works
What happens to a frame, step by step.
- 01Clean-upanalysis/preprocess
DC offset, a 40 Hz high-pass and a quality score for every take.
- 02Onset & trimanalysis/onset
Finds the attack, keeps 45 ms of run-up and ends the sample on the energy decay.
- 03Featuresanalysis/features
Twenty features per take: spectrum, envelope, pitch and whether a voice is in there.
- 04Role scoringroles/classify
Heuristic scores for kick, snare, hat and hook — the same labels a model would later learn.
- 05Assignmentroles/assign
All 24 permutations are scored, and a low end and a mid are guaranteed whatever was recorded.
- 06Harmonycomposer/harmony
The root note comes from the user’s own pitched take; bass and hook follow the progression.
- 07Instrumentsinstruments/build · bass
Layered hits — a kick is body, sub and click — plus a real bass part on a sub oscillator.
- 08Arrangementcomposer/arrange
Patterns, ghost notes, rolls, swing and humanisation, with a pause two sixteenths before the drop.
- 09Spaceeffects/reverb · delay
One mono reverb network decorrelated into stereo by an all-pass, plus a tempo-synced ping-pong delay.
- 10Mix & mastermix/master
Role EQ, sidechain, parallel compression, −14 LUFS and a true-peak ceiling; the low end stays centred.
- 11Videovideo/edl + MediaCodec / AVAssetWriter
The storyboard is computed in TypeScript and tested there; the native module only draws frames and encodes.
Challenges
Technical challenges
The hard parts — and the solutions that made the system stable.
Results
Impact
Measured outcomes and operational wins.
The whole path — four takes, analysis, arrangement, render, saved clip — runs offline; the only thing that reaches the network is the ad SDK in the free tier.
Measured on a Samsung Galaxy S26 Ultra: 470 ms analysis, 3850 ms beat, 210 ms WAV — 4530 ms against a 5000 ms budget.
Loudness holds at −14.4…−14.3 LUFS across eight seeds and the drop always lands before the fifth second.
Six styles cut the same four recordings differently — Phonk and DnB stay free, together with the whole main scenario.
Store graphics and the icon are generated by code, so a colour change is one file and one command instead of ten redrawn images.
The privacy policy and terms are published as real pages and mirrored by an in-app screen, because a store listing needs links that work without the network.
Availability
Where it runs
One codebase, every surface it ships on.
Android
Own build with the native encoder, AdMob and Play Billing wired, release signing via a config plugin.
iOS
Same codebase and the same core; the AVAssetWriter encoder is written and waits for a macOS build.
Desktop CLI
The same core runs as a Node CLI — analyse, render, batch — which is where the algorithm is actually debugged.
Stack
Tech stack used
Tools and patterns used on this build.
Mobile app
- Expo SDK 57
- React Native 0.86
- TypeScript
- React Navigation
- Zustand
- react-native-svg (all UI graphics)
DSP core
- TypeScript (shared with the CLI)
- Own FFT + onset detection
- Heuristic role classifier
- mulberry32 PRNG (bit-exact)
- 24-bit WAV codec
Video
- EDL computed in TypeScript
- Kotlin + MediaCodec + OpenGL ES
- Swift + AVAssetWriter
- AAC via MediaMuxer
- 9:16, 720p / 1080p
Capture & storage
- expo-audio (48 kHz mono PCM)
- expo-camera
- expo-sqlite (single source of truth)
- expo-file-system
- fflate (.klats ZIP container)
Monetisation
- Google AdMob (banner + interstitial)
- react-native-iap
- Play Billing / StoreKit 2
- One-time klats_pro_lifetime
Build & release
- EAS Build
- Expo config plugins
- Gradle release signing
- Play App Signing
- Store assets generated from code
Metrics
Impact metrics
Taps to a finished beat
4recordings, no settings
Generation on device
4.5s against a 5 s budget
Recordings uploaded
0bytes leave the phone
Styles
6from the same four sounds
Next
Next case study
Keep browsing the system.
Voxnera — Real-Time Voice Translation for Any Call
A Windows application that sits between the headphones and whatever the call is running in. You speak your language, the other person hears theirs — both directions at once, each with its own voice, and both written down as text you can search.