Code songs, render audio.
A declarative TypeScript/JSX music framework — write a song as a component tree,
render a listenable .wav/.mp3, and read an analysis report to self-correct.
Explore the authoring API »
View Examples
·
Report Bug
·
Request Feature
Table of Contents
Codesong turns a song into a TypeScript/JSX file. You write a component tree that
default-exports a <Song>; the framework compiles it to a music IR, synthesizes it on a Web
Audio graph, auto-masters the mix, and writes an audio file plus a JSON analysis report
(key detection, loudness, clipping, per-track note counts, issues). Components in, sound out.
export default (
<Song title="Sunny Backroads" tempo={124} keySignature="G major">
<Section name="verse" bars={8}>
<Track instrument="acoustic-guitar" reverb={0.18} loop>
<Progression chords={["G", "C", "G", "D"]} dur="1n" strum="down" />
</Track>
<Track instrument="bass" octave={2} loop>
<Progression chords={["G", "C", "G", "D"]} dur="1n" voicing="root5" />
</Track>
<Track instrument="drums" loop>
<Pattern steps="bd ~ sd ~ bd bd sd ~" dur="8n" />
</Track>
</Section>
</Song>
);$ codesong render song.tsx -o out.wav
♪ Sunny Backroads — 124 BPM, 4/4, key G major
duration 41.2s | peak -1.0 dBFS | RMS -12.1 dBFS
detected key: G major (conf 0.985) ✓
sections: intro → verse → chorus
no issues ✓
Why it exists:
- Authoring, not DSP. It is thin orchestration over proven open source — the value is the declarative model and a tight, agent-friendly feedback loop, not hand-rolled signal processing.
- Self-contained. No sample packs or native binaries to install — instruments are synthesized directly on the Web Audio graph, so it renders out of the box at ~9× real time.
- Deterministic. A
seeddrives all humanization and procedural synthesis, so the same song always renders the same audio — diffable, reproducible, CI-friendly. - Built for agents. The analysis report exists so a tool (or a human) can read what's wrong and re-render — components in, sound out, repeat.
- node-web-audio-api — offline Web Audio rendering
- tonal — music theory helpers (keys, chords, scales)
- ffmpeg-static — MP3 encoding
-
Node.js 18+ (the renderer targets ES2022 and the Web Audio API).
-
npm (ships with Node).
node --version # v18.0.0 or newer
The fastest path — scaffold a new project, then render the starter song:
npx create-codesong@latest my-song
cd my-song
npm run render # song.tsx -> out.wav + out.report.jsonOr add Codesong to an existing TypeScript project:
-
Install the package.
npm install codesong
-
Point JSX at Codesong's runtime in your
tsconfig.json(no React needed). -
(Optional) Install the CLI globally to use
codesonganywhere.npm install -g codesong codesong init my-song # scaffold song.tsx + CODESONG.md codesong presets # list the available instruments
The mental model is small: <Section>s play sequentially, <Track>s inside a section play
in parallel, and same-named tracks across sections merge into one part. Time is musical —
durations are note values ("1n", "4n", "8n.", "8nt") and pitches are "C4", "G#3", or raw MIDI.
Create a song.tsx that default-exports a <Song>. Components compose, and you can extract
reusable parts as plain function components:
import { Song, Section, Track, Progression, Pattern } from "codesong";
function CountryBeat() {
return (
<Track instrument="drums" loop>
<Pattern steps="bd ~ sd ~ bd bd sd ~" dur="8n" velocity={0.9} />
<Pattern steps="hh hh hh hh hh hh hh hh" dur="8n" velocity={0.5} />
</Track>
);
}
export default (
<Song title="Sunny Backroads" tempo={124} keySignature="G major" seed={7}>
<Section name="verse" bars={8}>
<Track instrument="acoustic-guitar" reverb={0.18} loop>
<Progression chords={["G", "C", "G", "D"]} dur="1n" strum="down" />
</Track>
<CountryBeat />
</Section>
</Song>
);codesong render song.tsx -o out.wav # WAV + out.report.json
codesong render song.tsx --mp3 # MP3 insteadRead the printed report, fix anything it flags (out-of-key notes, clipping, silent tracks), re-render, then listen. Want the full component and instrument reference? See CODESONG.md — the complete authoring guide.
Renders are humanized by default (seeded micro-timing, dynamics, and swing), and you can drop
insert effects inside any <Track>:
<Song swing={0.55} room="room">
<Section name="loop" bars={8}>
<Track instrument="electric-piano" reverb={0.35} loop>
<Effect type="filter" mode="lowpass" cutoff={2400} />
<Effect type="chorus" rate={0.8} depth={5} mix={0.35} />
<Progression chords={["Am7", "Dm7", "Gmaj7", "Cmaj7"]} dur="1n" />
</Track>
<Track instrument="drums" bus="beat" loop>
<Pattern steps="bd ~ ~ ~ sd ~ ~ bd" dur="8n" />
</Track>
</Section>
</Song>| Effect | What | Key params (defaults) |
|---|---|---|
delay |
Echoes | time ("8n"), feedback (0.3), mix (0.3) |
chorus |
Thickening / width | rate Hz (1.2), depth ms (4), mix (0.4) |
drive |
Overdrive / warmth | amount (0.4), mix (0.6) |
tremolo |
Amplitude wobble | rate Hz (5), depth (0.5) |
filter |
Tone shaping | mode (lowpass), cutoff Hz (1200), q (1) |
More runnable songs live in examples/ — country, lo-fi, blues piano, and an
epic-minor theme.
song.tsx ─compile→ ScoreIR ─schedule→ Web Audio graph ─render→ AudioBuffer ─→ WAV/MP3
└→ report.json (analysis)
| Module | Responsibility |
|---|---|
src/core |
JSX runtime (no React), music IR, tonal-backed theory, compile(), the humanize pass |
src/instruments |
Data-driven synth presets, a synthesized drum kit, insert effects, convolution reverb |
src/renderer |
engine.ts schedules a score onto any Web Audio context (shared by Node and the browser preview); render.ts masters, normalizes, and encodes |
src/analyze |
Symbolic validation + audio features (loudness, clipping, key estimate) → the report |
src/cli |
render / presets / init |
src/preview |
Vite studio: live playback, transport, section map, hot reload |
Develop the repo itself:
npm install
npm run render -- examples/cheerful-country/song.tsx -o out.wav # render + report
npm run preview # live studio at :5174
npm test # unit + render integration
npm run build # build dist/ for publishing- Declarative TS/JSX authoring + full render pipeline
- Analysis / feedback report loop
- Humanization, swing, and per-instrument feel
- Per-track insert effects + convolution reverb + auto-master bus
- Karplus-Strong physically-modeled guitars
- Live browser studio (Vite) sharing the render engine
- SoundFont / SFZ sampler backend (FluidSynth / sfizz) for acoustic realism
- MIDI / MusicXML export
- Loudness-normalized MP3 export
- More genre presets
- Optional vocals plugin (DiffSinger / NNSVS)
See the open issues for a full list of proposed features and known issues.
Contributions make the open source community an amazing place to learn and create. Any contributions you make are greatly appreciated.
If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement".
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/amazing-feature) - Commit your Changes (
git commit -m 'feat: add some amazing feature') - Push to the Branch (
git push origin feature/amazing-feature) - Open a Pull Request
Please keep tests green (npm test) and the build clean (npm run typecheck) before opening a PR.
Distributed under the MIT License. See LICENSE for more information.
Mehmet Akif — @devmehmetakifv — mehmetakifvrdr@gmail.com
Project Link: https://github.com/devmehmetakifv/codesong
- tonal — music theory primitives
- node-web-audio-api — Web Audio in Node
- ffmpeg-static — bundled FFmpeg for MP3
- tsx — on-the-fly TS/TSX loading for the CLI
- Best-README-Template — this README's structure
{ "compilerOptions": { "jsx": "react-jsx", "jsxImportSource": "codesong" } }