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

10 KiB
Raw Blame History

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:

{
  "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:

{
  "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

Зависимости

# 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 tickVoice::tick() -> f32, Mixer собирает буфер
  • Без allocations в hot path — генераторы работают с &mut self, без Vec в audio thread
  • JSON-first для LLM — каждый звук описывается JSON, LLM генерирует JSON естественно
  • Пресеты как data, не code — JSON-файлы в presets/, расширяемые без перекомпиляции