Metadata-Version: 2.4
Name: audatron
Version: 0.2.3
Summary: audatron — headless, deterministic, provenance-attested LLM-driven Audacity: natural language drives track editing, noise removal, and mastering via a headless DSP engine with closed-loop listening (hear/listen), auto-generated Audacity TCL scripts, an agent chat REPL, and an MCP stdio server.
Author: DREAM PIXELS FORGE
License: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: numpy>=1.26
Requires-Dist: soundfile>=0.12
Requires-Dist: typer>=0.12
Requires-Dist: rich>=13
Requires-Dist: httpx>=0.27
Requires-Dist: pydub>=0.25
Provides-Extra: noisereduce
Requires-Dist: noisereduce>=3.0; extra == "noisereduce"
Provides-Extra: test
Requires-Dist: pytest>=8; extra == "test"

# audatron

[![CI](https://github.com/Dream-Pixels-Forge/audatron/actions/workflows/pr-validation.yml/badge.svg)](https://github.com/Dream-Pixels-Forge/audatron/actions)
[![PyPI version](https://img.shields.io/pypi/v/audatron)](https://pypi.org/project/audatron/)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
[![Provenance: SLSA](https://img.shields.io/badge/provenance-SLSA%20attested-brightgreen.svg)](https://pypi.org/project/audatron/)

![audatron — natural-language audio production, mirrored live into Audacity](assets/Audatron%20Audio%20Workflow%20Hero%20Banner.png)

**Natural-language audio production, mirrored live into Audacity.**

audatron is a realtime, LLM-driven toolchain: you prompt an agent (or any
coding tool — Claude Code, Codex, opencode, kimi, pi, qwen code —) in plain
English, and it drives a real Audacity workflow in your browser: inspect the
waveform, trim tracks, strip noise, master to a target loudness, and export —
while the matching Audacity project + TCL/Lua scripts are written so you can
watch the edits land on the open project.

In short: **you describe the edit in English, audatron performs it, measures
the result, and mirrors everything into an Audacity project you can open and
watch.** No clicking through menus, no guessing whether the edit worked.

```
   you (natural language)
        │
        ▼
   ┌──────────────────────────────┐
   │  audatron agent (LLM loop)   │   ← Anthropic / OpenAI-compatible / Ollama
   └──────────────────────────────┘
        │  tool calls
        ▼
   ┌──────────────────────────────┐
   │  DSP engine (headless)       │   ← trim / gain / normalize / noise / master / export
   └──────────────────────────────┘
        │  every step
        ▼
   ┌──────────────────────────────┐
   │  Audacity bridge             │   ← .aup3 project + generated TCL + Lua scripts
   └──────────────────────────────┘
```

## New here? A one-minute orientation

You do not need to be an audio engineer to use audatron. Here is every bit of
jargon used on this page, in plain words:

| Term | What it means |
|------|---------------|
| **LLM** | Large language model — the AI (Claude, GPT, a local Ollama model…) that reads your English instructions and picks the edits. |
| **DSP** | Digital signal processing — the actual math applied to the sound samples (trimming, volume, noise removal…). This part is plain Python, no AI involved. |
| **Headless** | Runs without a graphical interface doing the work. Nothing is "clicked"; results are computed directly, which makes them fast and repeatable. |
| **Deterministic** | Same input + same commands → exactly the same output, every time. This is why the results are testable and trustworthy. |
| **LUFS** | A standard measure of *perceived* loudness (what streaming services and broadcasters use). `master to -14 LUFS` means "make it as loud as a typical podcast/YouTube track". |
| **dBFS** | Decibels relative to full scale — a peak-level scale where `0` is the maximum before distortion (clipping). Negative numbers = headroom. |
| **MCP** | Model Context Protocol — a common plug-and-play standard so any compatible coding agent can call audatron's tools. |
| **`.aup3`** | Audacity's own project file format. audatron writes two flavours: a native Audacity 4 SQLite project and an older XML one. |
| **TCL / Lua** | Two scripting languages Audacity can run as macros. audatron generates scripts in both so your edits replay inside the app. |
| **log-mel grid** | A compact numeric "picture" of which frequencies are present over time — a way to describe sound as text. |
| **onset** | A moment where sound begins, e.g. a drum hit or the start of a word. |
| **data-URI** | Audio encoded as text (base64) so it can be handed directly to an AI model that can "hear". |

## Headless by design

No GUI automation, no hidden state: audatron runs its entire DSP pipeline
headless and deterministically — same input, same calls, same bytes. Every
release is published to PyPI with SLSA provenance attestations, so what you
`pip install` is verifiably what CI built. The Audacity bridge writes
artifacts, not clicks.

## What you need

- **Python 3.10+** and `pip`.
- Optional but recommended:
  - **ffmpeg** — required only for `mp3` export (other formats work without it).
  - **Audacity** on your `PATH` — lets audatron launch the project for you
    (without it, the project and TCL scripts are still generated and you can
    open them manually).
  - **An LLM backend** — either an API key (`ANTHROPIC_AUTH_TOKEN` or
    `OPENAI_API_KEY`) or a locally running [Ollama](https://ollama.com). The
    Ollama backend is the default for `run` and `chat`. Without any backend,
    everything below still works — see
    [The LLM agent is optional](#the-llm-agent-is-optional).

`audatron doctor` checks all of this for you and prints a table of what is
present and what is missing.

## Install

```bash
pip install -e .
audatron doctor        # verify numpy, ffmpeg, Audacity, LLM backends
```

## Quickstart

```bash
# 1. generate a test clip
audatron demo demo.wav --freq 440 --seconds 3

# 2. one-shot: natural language in, mastered wav out
audatron run "trim to 2s, remove hiss, master to -14 LUFS, export wav" demo.wav --backend anthropic

# 3. interactive REPL
audatron chat demo.wav --backend anthropic
#    you › make it sound like a radio
#    you › sync          ← pushes the deck into a live Audacity project
```

Step by step:

1. `demo` writes a small deterministic test tone (a 440 Hz sine with a noise
   bed, 3 seconds by default) so you have something to play with.
2. `run` gives your sentence to the agent once: it inspects the file, applies
   the edits, checks them, and exports — printing its progress as it goes.
3. `chat` opens an interactive session. Type edits in English; type `sync` to
   push the current state into a live Audacity project. Type `quit`, `exit`,
   or `q` to leave.

### Common recipes

You don't need to know the tool names to start. Here is how a plain-English
sentence maps onto the tool audatron actually runs — and how to get the same
result without an LLM.

| What you'd say | What audatron actually does | Do it without an LLM |
|----------------|-----------------------------|----------------------|
| "Cut off the first three seconds." | `trim` (start_s 3.0, end_s = end of file) | via the Python API |
| "There's a hiss in the background — get rid of it." | `noise_reduce` (profile_seconds 0.5, strength 1.0) | `audatron sync <file>` (default plan applies noise-reduce first) |
| "Make it sound like a typical podcast." | `master` (target_lufs −14.0, true_peak_db −1.0) | `audatron sync <file>` (default plan masters to −14 LUFS) |
| "It's clipping — the peaks are hitting the ceiling." | `normalize` (target_db −3.0) | via the Python API |
| "Turn it down about 6 dB." | `gain` (db −6.0) | via the Python API |
| "Save it as an mp3." | `export` (path out.mp3, fmt mp3) | via the Python API (needs ffmpeg) |
| "Open it in Audacity so I can see it." | `sync` (writes the .aup3 project + TCL/Lua) | `audatron sync <file> --open-audacity` |
| "How loud is this, and is there any silence in it?" | `inspect` (sr, duration, peak, loudness, silence ratio) | `audatron inspect <file>` |
| "Undo that last change." | `undo` (restores the previous checkpoint) | via the Python API |
| "Load a different file instead." | `load` (path other.wav; clears history) | via the Python API |

### The LLM agent is optional

Every operation the agent can perform is also available without an LLM:

```bash
audatron inspect demo.wav              # stats + spectral analysis
audatron sync demo.wav                 # Audacity project + TCL/Lua, no LLM
```

## Command reference

All commands and flags below are the ones implemented in `src/audatron/cli.py`.

| Command | What it does | Useful flags |
|---------|--------------|--------------|
| `audatron doctor` | Environment check: numpy, soundfile, ffmpeg, Audacity, embed model, LLM backends. | — |
| `audatron demo [path]` | Generate a deterministic test clip (sine + noise bed). Default path `demo.wav`. | `--freq` (440.0), `--seconds` (3.0), `--noise` (0.15) |
| `audatron run <prompt> <src>` | One-shot: natural-language instruction in, result out. | `--backend` (`anthropic`/`openai`/`ollama`, default `ollama`), `--model`, `--open-audacity`, `--run-tcl`, `--prefer` (`auto`\|`native`\|`xml`), `--xml-only` |
| `audatron chat <src>` | Interactive REPL. Type `sync` to push the deck into a live Audacity project. | `--backend`, `--model` |
| `audatron inspect <file>` | Print stats (sample rate, duration, peak, loudness, silence) and spectral analysis. | `--analyze/--no-analyze` (default on) |
| `audatron embed <file>` | Run the local text-embedding and print it as JSON. Use `-` to print model status only. | `--start` (0.0), `--end` (file length), `--detail` (`compact`\|`full`) |
| `audatron sync <file>` | Generate the Audacity project + TCL/Lua scripts (no LLM). Applies a default plan: noise-reduce → master to −14 LUFS. | `--project-dir`, `--open-audacity`, `--run-tcl`, `--agent-snippet`, `--prefer`, `--xml-only` |
| `audatron-mcp` | Start the MCP stdio server (newline-delimited JSON-RPC 2.0). | — |

## Audacity integration

`audatron sync` writes:

| File                        | Purpose                                            |
|---------------------------|----------------------------------------------------|
| `deck.wav`                 | clean copy of the current deck                     |
| `<name>.aup3`             | Audacity 3.x XML project (fallback)               |
| `<name>.native.aup3`     | **native Audacity 4 SQLite project** (primary)    |
| `audatron.tcl`            | generated TCL script (run via Tools → Macros)     |
| `audatron.lua`            | generated Lua script (Audacity 2.x scripting)      |
| `audatron.json`           | machine-readable manifest of the ops               |

The `.native.aup3` is a real SQLite database matching Audacity 4's
on-disk format: four tables (`project`, `sampleblocks`, `autosave`,
`project_history`), float32 sample blocks sized the way the app writes
them (up to 262144 samples / 1 MiB), and the app's `dict`/`doc`
record streams. It opens natively with the waveform + track layout
intact, no external WAV side-file needed. The XML `.aup3` is kept as
a fallback for older Audacity builds.

Open it in your running Audacity 4:

```
"C:\Program Files\Audacity 4\bin\Audacity4.exe" <project>\river_master-proj.native.aup3
```

or let audatron launch it for you:

```
audatron sync river_master.wav --open-audacity    # opens the native project
audatron sync river_master.wav --run-tcl          # + auto-runs the TCL macro
```

`--prefer auto` (the default) opens the native project when it exists and
falls back to the XML one; `--prefer native` / `--prefer xml` force a choice,
and `--xml-only` forces the legacy XML `.aup3` for older Audacity builds.

## MCP server

audatron ships an MCP stdio server so **any** MCP-capable coding agent can
drive it. The tools are the same DSP surface the CLI agent uses.

```bash
audatron-mcp        # newline-delimited JSON-RPC 2.0 over stdio
```

Wiring it into a coding agent — see **[dev-notes/MCP-SETUP.md](dev-notes/MCP-SETUP.md)** for
Claude Code, Codex, opencode, kimi, qwen-code, and generic MCP clients.

## Closed-Loop Listening

audatron's most defensible trait: the agent can **hear the result** of every
edit and reason from the numbers, instead of declaring success on faith.

```
   1. inspect ──► 2. edit (trim / noise_reduce / master / …) ──► 3. hear ──► 4. listen again
                                                            │            verify the region
                                                            ▼         (silence %, centroid,
                                                           good?        onsets, peak dB)
                                                            │
                                          good → export/sync ──┘
                                          bad  → undo/redo, retry
```

- `hear` — a **local, deterministic text-embedding** of a segment (log-mel
  grid + silence map + onset grid + loudness/centroid). ~400 tokens, no audio
  input required — works on *any* LLM, including text-only local models.
- `listen` — a base64 WAV data-URI (16 kHz mono, 20 s cap) for
  audio-capable backends; `hear` is the text-only fallback.

Plain version: after every edit, the agent *looks at the sound again* — how
much silence is left, how loud it is, where the onsets are — and retries with
`undo`/`redo` if the numbers say the edit failed. It never has to take the
tool's word for it.

### From Python

```python
from pathlib import Path
from audatron.dsp import load_audio
from audatron.session import Session
from audatron.tools import dispatch

s = Session(load_audio("in.wav"), Path("in.wav"))
before = dispatch(s, "hear", {"start_s": 0.0, "end_s": 5.0, "detail": "full"})
dispatch(s, "noise_reduce", {"profile_seconds": 0.5, "strength": 1.0})
after = dispatch(s, "hear", {"start_s": 0.0, "end_s": 5.0})
assert after["silence_pct"] < before["silence_pct"]   # the noise is gone
```

## How it differs

| | audatron | Audacity-MCP (`xDarkzx/Audacity-MCP`) | cochlea | Ableton MCP (ableton-copilot-mcp) |
|---|---|---|---|---|
| GUI automation | no — headless | yes (drives the live Audacity GUI) | no | yes (live Ableton) |
| Deterministic DSP | yes | n/a (GUI-driven) | yes | n/a |
| MCP tool surface | yes (`audatron-mcp`) | yes | no | yes |
| Native Audacity-4 SQLite `.aup3` | yes | n/a | no | n/a |
| Closed-loop listening (`hear`/`listen`) | yes | no | no | no |

audatron is the only tool in this set that is *headless*, *deterministic*, and
*augmented with a feedback loop* — the agent verifies every destructive edit
by hearing the numbers, not by trusting the operation succeeded. (Capability
claims about competitors are from their public READMEs; verify before citing.)

## Tool surface

The 16 tools below are the single surface shared by the CLI agent, the MCP
server, and direct Python calls (`dispatch`). An LLM picks *which* tool to
call; you can also call them yourself — see
[The LLM agent is optional](#the-llm-agent-is-optional).

| Tool           | What it does |
|----------------|--------------|
| `inspect`      | sr, duration, peak, loudness dB, silence ratio |
| `analyze`      | spectral centroid, onsets, silence ranges |
| `trim`         | keep a `[start, end]` window |
| `gain`         | apply ± dB |
| `normalize`     | peak-normalize to a target dBFS |
| `noise_reduce` | spectral-subtraction denoise (profile from head) |
| `master`       | loudness-normalize to target LUFS + peak ceiling |
| `export`       | write wav / flac / mp3 / ogg |
| `sync`         | generate the Audacity project + scripts |
| `listen`       | WAV data-URI (16 kHz mono, 20 s cap) for audio-capable LLMs |
| `hear`         | local text-embedding: log-mel + silence + onsets + numbers |
| `status`       | session overview: stats + paths + sync state + undo depth |
| `history` / `undo` / `redo` | deck state |
| `load`         | replace the deck with a new file |

## Development

```bash
pip install -e ".[test]"
python -m pytest -q          # 100+ tests, ~45–80s
```

Layout:

```
src/audatron/
  dsp.py          # headless DSP engine (numpy + soundfile)
  session.py      # stateful deck + op history
  tools.py        # tool surface shared by CLI agent + MCP
  agent.py        # LLM agent loop (Anthropic/OpenAI/Ollama)
  backends.py     # LLM provider clients (+ streaming)
  live.py         # realtime foreground view (token stream + waveform)
  audacity.py     # .aup3 + TCL/Lua generation + Audacity lookup
  aup3.py        # native Audacity-4 SQLite .aup3 writer
  mcp_server.py   # MCP stdio JSON-RPC server
  embed.py        # local text-embedding (hear) — log-mel + silence + onsets
  cli.py          # typer CLI
tests/            # pytest: DSP, tools, agent (mocked), MCP, e2e, CLI, aup3, live
```

## Further reading

- **[skills/audatron/SKILL.md](skills/audatron/SKILL.md)** — how to drive
  audatron like a pro from a coding agent (tools, recipes, guardrails).
- **[dev-notes/MCP-SETUP.md](dev-notes/MCP-SETUP.md)** — wiring
  `audatron-mcp` into Claude Code, Codex, opencode, kimi, qwen-code, and
  generic MCP clients.
