emotune

Send a feeling, hear a melody. Generative chiptune mood daemon in Rust.

Rust MIT created updated
readme · slastra/emotune

emotune

Send a feeling, hear a melody. A tiny generative chiptune daemon: one cheap shell call plays a short synthesized melody matching the moment.

emotune "tests are green"      # cheerful ascending run
emotune "build failed"         # low womp
emotune "should I deploy?"     # unresolved rise

Keywords in the phrase map to a mood (success, big_success, error, warning, question, thinking, progress, hello, goodbye, info), and each mood improvises a fresh melody from a recipe: a scale, a drift direction, a note-count range, a resolution degree. Same feeling, never the same tune.

It also performs composed pieces. emotune play score.toml plays an exact multi-track score with drums (kick, snare, hat), an FM bell, an LFO wobble bass, and per-score echo and reverb settings. Scores are plain TOML data, which makes them a friendly target for LLM composition: have a model write a score, validate it with emotune play --check, and nothing it hallucinates can do worse than fail parsing. See docs/score.md.

How it works

A single Rust binary. The daemon holds a cpal audio stream and listens for OSC over UDP on port 57120; the client classifies the phrase and sends it. All synthesis is in-process: chip-style pulse, triangle, and FM voices with a ping-pong echo into a small Schroeder reverb. No SuperCollider, no samples, no runtime dependencies beyond an audio server.

Install

cargo install --path .
emotune daemon        # or run it under a service manager

A systemd user unit is the intended home:

[Unit]
Description=emotune mood-melody daemon
After=pipewire.service

[Service]
ExecStart=%h/.local/bin/emotune daemon
Restart=on-failure

[Install]
WantedBy=default.target

With the unit installed, emotune start|stop|restart|status wraps systemctl.

Customizing

Mood recipes live in recipes.toml (compiled in). Recipes in ~/.config/emotune/recipes.toml merge over them at startup: the same name replaces a built-in, a new name adds a mood. emotune restart to reload, no rebuild. Timbres and effects are in src/synth.rs.

License

MIT