sonoscript turns a block of plain text into concrete edits on a waveform. The data flows in one direction:
text ──► tokenizer ──► parser ──► commands ──► Editor ──► AudioClip
│
└──► EditManifest ──► evaluate
Everything is mono float32 audio in memory, and the only third-party
dependency is NumPy.
| Module | Responsibility |
|---|---|
clip |
AudioClip, the immutable mono buffer, plus slicing / gain / fades. |
io_wav |
Read and write 16-bit PCM WAV with the standard-library wave. |
synth |
Deterministic signal generators (sine, square, noise, ADSR, chirp). |
palette |
A registry mapping names (bell, siren, …) to rendered sounds. |
dsl |
The instruction language: tokenizer, timespec, parser, commands. |
editor |
Compiles commands into waveform surgery and an EditManifest. |
manifest |
Provenance of an edited clip: which samples were kept vs. inserted. |
detection |
Energy-based onset/offset detection, used to resolve label targets. |
evaluate |
Quality metrics that read the manifest to line the clips back up. |
The key design decision is that every edit is expressed against the original
clip's timeline. An insert at 3s and a delete from 5s to 6s in the same
script do not shift each other, because none of them are applied until
Editor.render() runs.
render() walks the sorted edits once, left to right:
- Copy the untouched original audio up to the next edit.
- Splice in synthesised audio for inserts and replacements.
- Skip the removed span for deletes and replacements.
- Stitch neighbouring segments with a short equal-power crossfade so the seams do not click.
While it does this, it records each stretch of the output as a Segment in the
EditManifest, tagged as kept-from-original (with its source span) or inserted.
That record is what lets evaluate measure how faithfully the untouched regions
survived and how smooth the seams are.
Shipping audio assets would make the package heavy and the tests non-deterministic. Instead the palette renders every sound from seeded signal generators, so a given instruction always produces byte-identical output. That keeps the whole pipeline reproducible and offline.