Files
Soundgen/PLAN.md
T
Emil c7d6c40683 Initial release: 8-bit sound synthesizer with LLM/MCP integration
Soundgen is a Rust workspace for generating 8-bit/chiptune sound effects,
UI sounds, and ambient textures for game audio assets. It features JSON-first
sound specs, an MCP server for LLM tool-use, an egui GUI editor, and a
runtime library with NES-authentic DAC emulation.

Features:
- 6 voice types: pulse, triangle, noise, DPCM, wavetable, FM
- Effects: ADSR envelope, frequency sweep, biquad filter, vibrato
- 13 built-in presets (SFX/UI/ambient) as JSON data files
- MCP server: list_presets, generate_sfx, render_sound tools
- Pattern-based sequencer (JSON song format)
- egui GUI: virtual keyboard, preset browser, channel editor, undo/redo
- Runtime: NES nonlinear DAC + SoundBank for game embedding
- 90 tests, 0 warnings

Crates:
- soundgen-core: synthesis engine (no I/O)
- soundgen-fmt: SoundSpec JSON schema + PresetRegistry
- soundgen-io: WAV writer + audio playback
- soundgen-seq: sequencer (patterns, songs)
- soundgen-cli: gen/render/render-song/list-presets
- soundgen-mcp: MCP server for LLM integration
- soundgen-gui: egui editor
- soundgen-runtime: NES DAC + SoundBank
2026-06-21 22:07:05 +03:00

238 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Soundgen — 8-bit синтезатор на Rust + LLM-интеграция
## Статус: Фазы 1-4 завершены
| Параметр | Значение |
|---|---|
| Язык | Rust |
| Игра | Rust + Vulkan (custom engine) |
| Генераторы | Свои, с нуля |
| GUI | egui (фаза 3) |
| MCP | Да, через `rmcp` (официальный Rust MCP SDK) |
| Звуки | SFX, UI sounds, Ambient |
| Генерация | Build time → WAV-ассеты |
| Лицензия | MIT |
## Архитектура Cargo workspace
```
soundgen/
├── Cargo.toml # [workspace], shared deps
├── LICENSE # MIT
├── README.md
├── crates/
│ ├── soundgen-core/ # чистый движок синтеза, без I/O
│ │ └── src/
│ │ ├── lib.rs # реэкспорты
│ │ ├── generator.rs # trait Generator, Voice, Param
│ │ ├── voice/
│ │ │ ├── pulse.rs # PulseChannel (duty 12.5/25/50/75%)
│ │ │ ├── triangle.rs # TriangleChannel (32-step)
│ │ │ ├── noise.rs # NoiseChannel (LFSR white/periodic)
│ │ │ ├── dpcm.rs # (фаза 2)
│ │ │ ├── wavetable.rs # (фаза 2, GB wave-style)
│ │ │ └── fm.rs # (фаза 2, 4-op FM)
│ │ ├── effect/
│ │ │ ├── envelope.rs # ADSR
│ │ │ ├── sweep.rs # freq sweep (linear/exponential)
│ │ │ ├── vibrato.rs # LFO (фаза 2)
│ │ │ └── filter.rs # biquad lowpass/highpass (свой)
│ │ ├── automation.rs # FrequencyAutomation, Arpeggiator
│ │ └── mixer.rs # Mixer: N голосов → стерео
│ │
│ ├── soundgen-fmt/ # декларативный формат + пресеты
│ │ └── src/
│ │ ├── lib.rs
│ │ ├── spec.rs # SoundSpec (serde JSON)
│ │ └── preset.rs # PresetRegistry, built-in presets
│ │
│ ├── soundgen-io/ # I/O слой
│ │ └── src/
│ │ ├── lib.rs
│ │ ├── wav.rs # hound: WAV writer (16/24-bit)
│ │ └── realtime.rs # cpal (фаза 3)
│ │
│ ├── soundgen-seq/ # секвенсер (фаза 2)
│ │ └── src/
│ │ ├── pattern.rs # Pattern, Row, Note
│ │ ├── song.rs # Song, Track
│ │ └── sequencer.rs # Sequencer
│ │
│ ├── soundgen-cli/ # CLI binary
│ │ └── src/
│ │ ├── main.rs
│ │ └── commands/
│ │ ├── gen.rs # gen --preset jump --out ...
│ │ ├── render.rs # render song.json --out ...
│ │ └── list.rs # list-presets
│ │
│ ├── soundgen-mcp/ # MCP server для LLM (фаза 2)
│ │ └── src/
│ │ ├── lib.rs
│ │ ├── server.rs # rmcp ServerHandler impl
│ │ └── tools.rs # generate_sfx, list_presets, render
│ │
│ └── soundgen-gui/ # egui GUI (фаза 3)
│ └── src/
│ ├── main.rs
│ ├── keyboard.rs # виртуальная клавиатура
│ ├── channel_panel.rs # регуляторы каналов
│ └── preset_browser.rs # браузер пресетов
├── presets/ # встроенная библиотека (JSON)
│ ├── sfx/
│ │ ├── jump.json
│ │ ├── explosion.json
│ │ ├── coin.json
│ │ ├── laser.json
│ │ ├── hit.json
│ │ └── powerup.json
│ ├── ui/
│ │ ├── click.json
│ │ ├── hover.json
│ │ ├── confirm.json
│ │ └── error.json
│ └── ambient/ # (фаза 2)
│ ├── wind.json
│ ├── rain.json
│ └── drone.json
├── examples/
│ ├── play_melody.rs # фаза 1: pulse+triangle+noise → WAV
│ ├── generate_sfx.rs # фаза 1: SFX из кода
│ └── render_song.rs # фаза 2: song.json → WAV
└── tests/
└── integration.rs # рендер WAV, проверка RMS/длительности
```
## Декларативный формат (JSON) — LLM-friendly
Пример `presets/sfx/jump.json`:
```json
{
"name": "jump",
"duration": 0.3,
"sample_rate": 44100,
"channels": [
{
"type": "pulse",
"duty": 50,
"frequency": { "start": 200, "end": 800, "curve": "exponential" },
"envelope": { "attack": 0.01, "decay": 0.15, "sustain": 0.0, "release": 0.14 },
"volume": 0.7
}
]
}
```
Пример `presets/sfx/explosion.json`:
```json
{
"name": "explosion",
"duration": 0.8,
"channels": [
{
"type": "noise",
"mode": "white",
"filter": { "type": "lowpass", "cutoff": { "start": 2000, "end": 200, "curve": "exponential" } },
"envelope": { "attack": 0.005, "decay": 0.7, "sustain": 0.0, "release": 0.095 },
"volume": 0.9
}
]
}
```
LLM генерирует такой JSON → CLI/MCP рендерит → WAV-ассет готов.
## MCP server — tools для LLM
Сервер на `rmcp` (stdio transport), expose 3 tool'а:
| Tool | Параметры | Возвращает |
|---|---|---|
| `list_presets` | `category?: "sfx"\|"ui"\|"ambient"` | JSON-список пресетов с описаниями |
| `generate_sfx` | `preset: string`, `params?: object`, `out_path: string` | Путь к WAV + метаданные (длительность, размер) |
| `render_sound` | `spec: object` (полный SoundSpec JSON), `out_path: string` | Путь к WAV + метаданные |
Workflow LLM при разработке игры:
1. LLM вызывает `list_presets` → видит доступные звуки
2. LLM вызывает `generate_sfx { preset: "jump", out_path: "assets/sfx/jump.wav" }` → WAV создан
3. Для кастомного звука: LLM пишет JSON-spec и вызывает `render_sound { spec: {...}, out_path: "assets/sfx/laser.wav" }`
4. LLM пишет Rust-код игры, загружающий WAV через `hound`/`rodio`
## Зависимости
```toml
# workspace
[workspace.dependencies]
hound = "0.5" # WAV I/O
serde = { version = "1", features = ["derive"] }
serde_json = "1"
# soundgen-io (фаза 3)
cpal = "0.15"
# soundgen-mcp (фаза 2)
rmcp = "1.7"
tokio = { version = "1", features = ["full"] }
# soundgen-cli
clap = { version = "4", features = ["derive"] }
# soundgen-gui (фаза 3)
eframe = "0.27"
egui = "0.27"
```
## Фазы разработки
### Фаза 1 — Core + CLI + Пресеты (MVP)
Цель: работающая библиотека, CLI, и набор готовых пресетов для SFX/UI.
- **soundgen-core**: `Generator`/`Voice`/`Param` трейты, `PulseChannel`, `TriangleChannel`, `NoiseChannel`, `Envelope` (ADSR), `Sweep` (linear/exponential), `FrequencyAutomation`, `Mixer`, простые biquad filters (lowpass/highpass — свой код)
- **soundgen-fmt**: `SoundSpec` (serde), `PresetRegistry` (загрузка JSON из `presets/`)
- **soundgen-io**: `wav::write(path, samples, sr, bit_depth)` через `hound`
- **soundgen-cli**: `gen --preset <name> [--param k=v]... --out <path>`, `gen --from <spec.json> --out <path>`, `list-presets [--category sfx|ui|ambient]`
- **Пресеты**: jump, explosion, coin, laser, hit, powerup (SFX); click, hover, confirm, error (UI)
- **Examples**: `play_melody`, `generate_sfx`
- **Тесты**: unit на duty cycle/частоту/envelope; интеграционный — рендер WAV, проверка длительности и RMS
### Фаза 2 — Extended synthesis + Sequencer + MCP
Цель: расширенный синтез, секвенсер для мелодий, MCP-сервер для LLM.
- **soundgen-core**: `DpcmChannel`, `WavetableChannel`, `FmChannel`, `Vibrato` (LFO)
- **soundgen-seq**: `Pattern`, `Song`, `Sequencer` (tempo, rows, note triggers)
- **soundgen-mcp**: rmcp-сервер, tools: `list_presets`, `generate_sfx`, `render_sound`
- **Ambient пресеты**: wind (filtered noise + slow LFO), rain (noise + highpass), drone (low freq sustained)
- **CLI**: `render song.json --out music.wav`
- **Example**: `render_song`
### Фаза 3 — GUI (egui)
Цель: интерактивный редактор для человека.
- egui app: виртуальная клавиатура (мышью/клавишами), панель каналов (duty, freq, envelope), браузер пресетов, pattern editor
- cpal realtime playback (ring buffer)
- Сохранение/загрузка проектов (JSON)
### Фаза 4 — Advanced (опционально)
- NES-authentic: нелинейный DAC, DPCM corruption, hardware-accurate mixing
- VST плагин через `nih-plug`
- Runtime library для прямой интеграции в Rust+Vulkan игру
## Ключевые принципы
- **Чистый core без I/O** — рендеринг в `Vec<f32>` в тестах без звуковой карты
- **Sample-accurate tick** — `Voice::tick() -> f32`, `Mixer` собирает буфер
- **Без allocations в hot path** — генераторы работают с `&mut self`, без `Vec` в audio thread
- **JSON-first для LLM** — каждый звук описывается JSON, LLM генерирует JSON естественно
- **Пресеты как data, не code** — JSON-файлы в `presets/`, расширяемые без перекомпиляции