← Creative Lab
Personal R&D — 2025

SIMP

A DJ instrument built on YouTube's public player, with nothing downloaded

A browser-based DJ sampler built entirely on YouTube's public player — cue points, bar-quantized loops, tap tempo, and a BPM warp engine. The platform doesn't provide raw audio, so nothing is downloaded.

10,102
Lines (Live Build)
6
Generations Built
0
Frames Downloaded
The hard part

Seven fixed YouTube playback rates treated as the whole tempo space — the warp engine snaps to the nearest one and reports the residual instead of pretending it's exact.

Client
Personal R&D
Role
Creator / Developer Instrument Design / Audio-Timing Engineering
Timeline
2025
Live

Load a Track, Start Playing

The actual instrument. Paste a YouTube URL, tap a tempo, fire cues on the number keys — nothing is downloaded, and the player underneath is the stock embed.

The problemsampling without ripping

Every obvious way to sample YouTube is a policy violation. Download the audio and you have broken the terms before the first cue point. The IFrame API is the one sanctioned door, and it hands over almost nothing: play, pause, seek, and a fixed menu of playback rates. No audio buffer. No waveform. No Web Audio graph — architecturally impossible, not just unbuilt.

So the instrument had to be built out of the controls a video player is willing to give you. Seeking became cue points. Rate became tempo. A timer became the sequencer. The player never knows it joined a band.

Six generationsthe same idea, five failed bodies

The folder archaeology, straight from the archive README. Which build was actually live was established by hash — the bundle the site serves was matched against every SIMP folder on disk and appears in exactly one dist/.

GenerationStackFateWhy it died
SIMP v01Chrome extensionarchivedmanifest-v3 sandbox couldn't hold the instrument
SIMP v02Python + yt-dlparchivedworked perfectly — and could never ship. It downloads the audio.
simpCreate React ApparchivedCRA was already deprecated under it
simp-backupCRA copyarchiveda checkpoint, never a direction
simp-newCRA + TS migrationarchivedmigrating a dead scaffold instead of leaving it
simp-v2 ← liveVite + React + TS + Tailwindshippedpolicy-compliant by construction: IFrame API only

v02 is the interesting corpse: the version that solved the problem by ignoring the constraint. It sounded best and was unshippable. The live build is the answer to “what survives if the constraint is taken seriously?”

BPM warptempo, through a menu of seven rates

Ableton-style warping needs a continuous playback rate. YouTube offers seven fixed ones. So bpmWarp.ts computes the ideal rate, snaps it to the nearest entry in the menu, and — instead of pretending — shows you the residual: the BPM you asked for versus the BPM you actually got. Try it:

96BPM
1.25×
effective 120.0 BPM · 0.0 off

The same math the tool runs: rate = target / source, snapped to YouTube's supported list. Green pill = the rate the player will actually be set to. The residual line is the honesty: at most tempos, you don't land exactly.

Two artifactsverbatim from the source
// bpmWarp.ts — the constraint, then the
// author arguing with himself in comments
export const YOUTUBE_SUPPORTED_RATES =
  [0.25, 0.5, 0.75, 1, 1.25, 1.5, 2];

// Example: A 7.5 second loop that is 4 beats
// - BPM = (4 * 60) / 7.5 = 32 BPM...
//   wait that's wrong
// Wait, let me recalculate:
// - At 128 BPM: 128/60 = 2.133 beats/sec
// - 4 beats / 2.133 = 1.875 seconds
// So: sourceBPM = (loopBeats * 60) / duration
the menu, and the math — seven rates is the whole tempo space. The worked-out-loud comments shipped as-is; the reasoning is part of the record.
// tsconfig.json — the gate that lied
{
  "files": [],
  "references": [
    { "path": "./tsconfig.app.json" },
    { "path": "./tsconfig.node.json" }
  ]
}
// `tsc --noEmit` reads this, finds no files,
// checks nothing, reports zero errors.
// The real gate is `tsc -b`. 32 errors
// accumulated behind the fake green.
the false negative — vite dev never typechecks either, so the app ran fine for months while the production build was broken. Found the day it had to ship.
What's real and what isn'tthe honest ledger

Real

Ten cue points on keys 1–9 and 0. Loop lengths in beats, not seconds — 8 divisions, bar-snapped. Tap tempo. A step sequencer whose interval recomputes when the BPM moves. A metronome. BPM warp with the residual readout above.

And the ship path: sync-simp.sh rebuilds the app, embeds it into this site, and verifies every asset reference resolves before deploying.

Decorative, or unbuilt

The waveform is a sum of four sines — the file says so in a comment. With no audio buffer there is nothing to draw, so it's set dressing, labelled as such.

SoundCloud and Spotify providers exist only as types. The auto-detect-BPM button is three-quarters written: handler, icon and estimator all exist; the button was never added.

Scope

Project Elements

Instrument DesignTiming & Quantization MathCanvas RenderingConstraint-Driven EngineeringPolicy-Compliant DesignKeyboard-First UX
Next Project
QUARRY →

Have a Project in Mind?

Animation direction, VFX and creative technology. Message me on LinkedIn or get in touch.