> ## Documentation Index
> Fetch the complete documentation index at: https://songbird.studiocollective.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# songbird-export

# songbird-export

Offline audio rendering — master export, stem export, track bounce, and `.bird`-file rendering.

This crate renders audio from the engine graph to WAV files without real-time constraints. It processes the entire timeline (or a time range) as fast as possible and writes the result to disk.

## Module Map

```
songbird-export/src/
├── lib.rs          — ExportConfig, StemMode, write_wav, export_master, export_stem, export_all_stems, trim_silence_file
├── render.rs       — internal offline render loop (graph.process in a tight loop)
├── bounce.rs       — BounceConfig, bounce_track, FreezeManager, FrozenTrack
└── bird_render.rs  — Render a `.bird` source string end-to-end (used by songbird-cli)
```

## Public API (top-level functions)

* `export_master(path, &mut graph, &mut transport, &ExportConfig, progress)` — full mixdown to a stereo WAV.
* `export_stem(path, &mut graph, &mut transport, &StemExportConfig, progress)` — solo a node, render to WAV, restore solo.
* `export_all_stems(output_dir, &mut graph, &mut transport, &ExportConfig, &[NodeId], StemMode)` — one WAV per node.
* `bounce::bounce_track(&mut graph, &mut transport, NodeId, name, &BounceConfig, progress)` — per-track bounce, optional normalization.
* `trim_silence_file(input, output, threshold)` — post-process trim of an existing WAV.
* `bird_render::render_bird_to_wav(&source, output_str, &BirdRenderConfig, progress)` — full session build + render from `.bird` text.
* `write_wav` / `write_wav_dithered` — TPDF dither when reducing to 16/24-bit; bypass for 32-bit float.

## How it's wired

The sync engine calls into this crate via `EngineBackend` methods on `AppState`:

| Sync command              | Backend method            | Renders via                                        |
| ------------------------- | ------------------------- | -------------------------------------------------- |
| `export.master`           | `export_master_mix`       | `export_master`                                    |
| `export.master_with_lane` | `export_master_with_lane` | `export_master` (with `swap_audition_lanes` first) |
| `export.stem`             | `export_stem`             | `export_stem`                                      |
| `export.all_stems`        | `export_stems`            | `export_stem` per track                            |
| `export.bounce_track`     | `bounce_track`            | `bounce_track`                                     |

Progress and completion are emitted on the `notifications` channel
(`notifications:export_progress`, `notifications:export_done`).

## Known limitation: take-lane filtering during offline export

The two render entry points work differently:

* `bird_render::render_bird_to_wav` runs the full pipeline — `session.scheduler.schedule(...)` then `session.graph.process_with_clips(...)` — so clips on the timeline are dispatched correctly. This is the path `songbird-cli render` uses.
* `export_master` (used by all `export.*` channel commands today) calls `graph.process` directly without driving the scheduler. It only renders signals already flowing through the live graph (running synths, monitored input).

Because the offline export does not currently invoke the scheduler, the per-track audition state set by `controller.swap_audition_lanes(...)` has **no effect on the rendered file** today. `export.master_with_lane` is fully wired (snapshot, swap, restore), produces a uniquely-named output file, and is correct on the IPC seam — but the audio inside that file is the same as `export.master` until the offline export gains scheduler integration.

When the offline export path is upgraded to drive the scheduler, lane variations and stem-from-clips will start producing distinct content with no API changes.

## Tests

```bash theme={null}
cargo test -p songbird-export
```

Tests use deterministic output verification (RMS, peak, fingerprints) against synthesised graphs — no audio hardware required.
