# tunes
A standalone Rust library for music composition, synthesis, and audio generation. Build complex musical pieces with an intuitive, expressive API — no runtime dependencies required.
Perfect for algorithmic music, game audio, generative art, and interactive installations.
## Features
- **Music Theory**: Scales, chords, patterns, progressions, and transposition
- **Composition DSL**: Fluent API for building musical sequences
- **Sections & Arrangements**: Create reusable sections (verse, chorus, bridge) and arrange them
- **Synthesis**: FM synthesis, filter envelopes, wavetable oscillators
- **Sample Playback**: Load and play WAV files with pitch shifting
- **Rhythm & Drums**: Drum grids, euclidean rhythms, 808-style synthesis, and pattern sequencing
- **Instruments**: Pre-configured synthesizers, bass, pads, leads, and more
- **Effects, Automation and Filters**: Delay, reverb, distortion, chorus, modulation, tremolo, autopan, gate, limiter, compressor, bitcrusher, eq, phaser, flanger, saturation, filters
- **Musical Patterns**: Arpeggios, ornaments, tuplets, classical techniques
- **Algorithmic Sequences**: Primes, Fib, 2^x, Markov, L-map, Collatz, Euclidean, Golden ratio, random/bounded walks, Thue-Morse, Recamán's, Van der Corput, L-System, Cantor, Shepherd, Cellular Automaton, and many more
- **Tempo & Timing**: Tempo changes, time signatures (3/4, 5/4, 7/8, etc.), key signatures with modal support
- **Key Signatures & Modes**: Major, minor, and all 7 Greek modes (Dorian, Phrygian, Lydian, etc.)
- **Real-time Playback**: Cross-platform audio output via cpal
- **WAV Import/Export**: Load samples and render compositions to WAV files
- **MIDI Export**: Export compositions to Standard MIDI Files with proper metadata
## Installation
Add this to your `Cargo.toml`:
```toml
[dependencies]
tunes = "0.1.0"
```
### Platform Requirements
**Linux users** need ALSA development libraries:
```bash
# Debian/Ubuntu
sudo apt install libasound2-dev
# Fedora/RHEL
sudo dnf install alsa-lib-devel
```
**macOS and Windows** work out of the box with no additional dependencies.
## Quick Start: Super simple!!
### Real-time Playback
```rust
use tunes::prelude::*;
fn main() -> Result<(), anyhow::Error> {
let engine = AudioEngine::new()?;
let mut comp = Composition::new(Tempo::new(120.0));
let eighth = comp.tempo().eighth_note(); //getting this value to use in the next example
// This is where you can do everything.
// Notes and chords can be input as floats with frequencies in hz or using or by prelude constants
// Durations can be input as a duration of seconds as a float or using durations inferred by tempo
comp.instrument("piano", &Instrument::electric_piano())
.note(&[C4], 0.5) //plays a c4 for half a second
.note(&[280.0], eighth); //plays 280.0 hz note for half a second
//continue chaining methods after the second note if you want.
engine.play_mixer(&comp.into_mixer())?;
Ok(())
}
```
### Export to WAV
```rust
use tunes::prelude::*;
fn main() -> Result<(), anyhow::Error> {
let mut comp = Composition::new(Tempo::new(120.0));
// Create a melody with instruments and effects
comp.instrument("lead", &Instrument::synth_lead())
.filter(Filter::low_pass(1200.0, 0.6))
.notes(&[C4, E4, G4, C5], 0.5);
// Export to WAV file
let mut mixer = comp.into_mixer();
mixer.export_wav("my_song.wav", 44100)?;
Ok(())
}
```
### Sample Playback
```rust
use tunes::prelude::*;
fn main() -> Result<(), anyhow::Error> {
let mut comp = Composition::new(Tempo::new(120.0));
// Load samples (drums, vocals, any WAV file)
comp.load_sample("kick", "samples/kick.wav")?;
comp.load_sample("snare", "samples/snare.wav")?;
// Use samples in your composition
comp.track("drums")
.sample("kick") // Play at normal speed
.sample("snare")
.sample("kick")
.sample_with_rate("snare", 2.0); // Double speed (pitch up)
// Mix samples with synthesis
comp.instrument("bass", &Instrument::sub_bass())
.notes(&[C2, C2, G2, G2], 0.5);
let mixer = comp.into_mixer();
let engine = AudioEngine::new()?;
engine.play_mixer(&mixer)?;
Ok(())
}
```
### MIDI Export
```rust
use tunes::prelude::*;
fn main() -> Result<(), anyhow::Error> {
let mut comp = Composition::new(Tempo::new(120.0));
// Create a composition
comp.instrument("melody", &Instrument::synth_lead())
.notes(&[C4, E4, G4, C5], 0.5);
comp.track("drums")
.drum_grid(16, 0.125)
.kick(&[0, 4, 8, 12])
.snare(&[4, 12]);
// Export to MIDI file
let mixer = comp.into_mixer();
mixer.export_midi("song.mid")?;
Ok(())
}
```
## Comparison with Other Music Programming Libraries
`tunes` occupies a unique position in the music programming landscape:
| **Type safety** | No | No | No (Clojure) | Partial (TS) | **Yes (Rust)** | No |
| **Real-time audio** | Yes | Yes | Yes (Overtone) | Yes (Web Audio) | **Yes** | No |
| **Sample playback** | Yes | Yes | Yes (Overtone) | Yes | **Yes** | No |
| **WAV export** | Yes (manual) | No | Via Overtone | No (browser) | **Yes (easy)** | Yes |
| **MIDI export** | Yes | No | No | No | **Yes** | Yes |
| **Easy to learn** | No | Yes | Medium | Yes | **Yes** | Yes |
| **No dependencies** | No (needs SC) | No (needs Ruby) | No (Clojure+SC) | No (browser/Node) | **Yes** | No |
| **Algorithmic patterns** | Yes | Yes | Yes | Yes | **Yes** | Yes |
| **Music theory** | Manual | Manual | Yes | Some | **Yes (built-in)** | Yes |
| **Standalone binary** | No | No | No | No | **Yes** | No |
| **Embeddable** | No | No | No | No | **Yes** | No |
### When to use `tunes`
**tunes excels at:**
- Building Rust applications with music generation (games, art installations, tools)
- Algorithmic composition with type-safe APIs
- Offline music generation and batch processing
- Learning music programming without complex setup
- Prototyping musical ideas with immediate feedback
**Use alternatives if you need:**
- **SuperCollider**: Extreme synthesis flexibility and live coding ecosystem
- **Sonic Pi**: Classroom-ready live coding with visual feedback
- **Leipzig**: Functional composition with Clojure's elegance
- **Strudel**: Browser-based collaboration and live coding
- **Music21**: Academic music analysis and score manipulation
### tunes' unique position
`tunes` is the only **standalone, embeddable, type-safe** music library with synthesis + sample playback. It compiles to a single binary with no runtime dependencies, making it ideal for:
- Rust game developers (Bevy, ggez, etc.)
- Desktop music applications
- Command-line music tools
- Embedded audio systems
## Documentation
Run `cargo doc --open` to view the full API documentation with detailed examples for each module.
## Testing
```bash
cargo test
```
* [ ] The library includes **607 comprehensive tests and 178 doc tests** ensuring reliability and correctness.
## Examples
Run the included **50 examples** to hear the library in action:
```bash
# Sample playback (WAV file loading and playback)
cargo run --release --example sample_playback_demo
# Export to WAV file
cargo run --release --example wav_export_demo
# Synthesis showcase (FM, filters, envelopes)
cargo run --release --example synthesis_demo
# Theory and scales
cargo run --example theory_demo
# Effects and effect automation (dynamic parameter changes over time)
cargo run --example effects_showcase
cargo run --example automation_demo
# And many more...
```
**Note:** Use `--release` for examples with complex synthesis to avoid audio underruns.
## License
MIT OR Apache-2.0
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.