cawtooth
v0.2.0
Published
A library for playing back retro chiptune music formats
Maintainers
Readme
cawtooth
A TypeScript + WebAssembly library for playing retro chiptune music formats in the browser, using vendored cycle-accurate chip emulators behind a uniform player API.
Supported formats
| Family | Formats | Chip / machine |
| ------------ | ------------------------------------------ | ----------------------------- |
| AdLib OPL | IMF/WLF, DRO, HERAD (HSQ/SQX/AGD/HA2) | Yamaha OPL2/OPL3 (Nuked-OPL3) |
| Commodore 64 | PSID / RSID (multi-SID, Songlengths) | MOS 6581/8580 (reSID) + 6502 |
| AY family | PSG, VTX, YM (digidrums), ASC, VGM | AY-3-8910 / YM2149 (Ayumi) |
| ZX trackers | PT3, PT2, STC, TS (TurboSound 2×AY) | AY-3-8910 (Ayumi) |
| Atari ST | SNDH (ICE!-packed too) | Musashi 68000 + YM2149 |
| ZX Spectrum | AY (ZXAYEMUL, beeper + Amstrad CPC) | Z80 + AY-3-8912 |
| NES | NSF, NSFe / NSF2 (all six expansion chips) | Ricoh 2A03 (Nes_Apu) + 6502 |
| SNES | SPC (ID666) | SPC700 + S-DSP |
| Atari 8-bit | SAP (types B and C) | POKEY + 6502 |
| Game Boy | GBS (MBC banking) | LR35902 + Game Boy APU |
| PC Engine | HES | HuC6280 + PSG |
Executable formats (PSID, SNDH, .ay, NSF, SAP, GBS, HES) run the
original replay code on an emulated CPU; register-dump and tracker
formats feed the chips directly. SPC is neither — it is a snapshot of
APU RAM that resumes mid-song.
Install
npm install cawtoothThe package ships ESM + CJS bundles, .d.ts types, eleven bundled
AudioWorklet processors (cawtooth/worklet/ plus opl, sid, psid,
nsf, spc, sap, gbs, hes, ay, sndh, zxay), and the eleven
WebAssembly chip emulators (cawtooth/wasm/*.wasm). Browser bundlers
resolve the assets with the ?url import suffix.
Quick start
import { CawtoothPlayer } from 'cawtooth';
import oplWorkletUrl from 'cawtooth/worklet/opl?url';
import oplWasmUrl from 'cawtooth/wasm/nuked-opl3.wasm?url';
const factory = await CawtoothPlayer.init({
formats: {
opl: { workletUrl: oplWorkletUrl, wasmUrl: oplWasmUrl },
},
});
// bytes: ArrayBuffer from fetch() or <input type="file">.
const player = await factory.load(bytes, { filename: 'song.dro' });
player.output.connect(player.audioContext.destination);
await player.resumeAudio(); // needs a user gesture in most browsers
player.play();Formats auto-detect from magic bytes (or the filename for the few
without any). Every player shares one transport surface — play(),
pause(), stop() — plus onProgress, onEnded, and onChannels
per-voice PCM taps for oscilloscopes. Subsong formats add
selectSong().
Offline (no AudioWorklet) rendering, WAV export, and cross-format transcoding helpers are exported too — see the repository docs.
React
@cawtooth/react
wraps this library in hooks, primitives, and a drop-in
<CawtoothPlayer /> component.
Browser support
AudioWorklet + WebAssembly + ES2022: Chrome 94+, Safari 15.4+, Firefox 93+.
Documentation
Byte-level format references — including exactly what each parser
handles and deliberately skips — live in the repository under
docs/formats/.
License
GPL-3.0-or-later. The vendored emulators keep their own licenses; see the repository README's acknowledgements.
