<p align="center">
<img width="300" height="300" src="docs/assets/logo.svg">
</p>
# Carmen - Programmatic Music Composition
[](https://crates.io/crates/carmen-lang)
[](https://docs.rs/carmen-lang)
[](https://github.com/francescofarina/carmen-lang#license)
## Table of Contents
- [Features](#features)
- [Prerequisites](#prerequisites)
- [Installation](#installation)
- [Usage](#usage)
- [Examples](#examples)
- [Carmen Language Quick Start](#carmen-language-quick-start)
- [Development](#development)
- [Community](#community)
- [License](#license)
**Carmen** is a novel, programmatic language designed for music composition. It provides a flexible and expressive syntax to define musical structures, from simple melodies to complex multi-movement scores. It is built with a focus on clarity, modularity, and control, allowing composers and developers to create music through code.
## Features
- **Expressive Musical Notation:** Define pitches, durations, chords, rests, and dynamics with a clear and concise syntax.
- **Hierarchical Structure:** Organize your music into sequences, multi-voice parts, staves, timelines, movements, and scores.
- **Programmatic Control:** Use variables, functions, conditionals (`if/else`), and loops (`for`, `while`) to generate and manipulate musical material.
- **Powerful Transformations:** Leverage built-in functions for music theory operations like transposition (`T`), inversion (`I`), normal/prime form calculation, and more.
- **Context Management:** Control tempo, time signatures, key signatures, and clefs at any point in the score.
- **Extensible and Modular:** Define reusable musical patterns with functions and extend musical parts to build complex compositions from simpler blocks.
- **Multiple Export Formats:** Export your compositions to various formats, including plain text summaries and **LilyPond** for beautiful sheet music engraving.
- **Developer Tools:** Includes tools for tokenizing, parsing, and inspecting the Abstract Syntax Tree (AST) of Carmen code for debugging and analysis.
## Prerequisites
- **Rust toolchain** (for installation via cargo or building from source)
- **LilyPond** (optional, for generating beautiful sheet music from exported `.ly` files)
## Installation
### Using Cargo (Recommended)
The easiest way to install Carmen is through Cargo, Rust's package manager:
```bash
cargo install carmen-lang
```
This will download, compile, and install the `carmen` executable from [crates.io](https://crates.io/).
### Building from Source
For development purposes or to use the latest unreleased features, you can build from source:
You will need to have the [Rust programming language](https://www.rust-lang.org/tools/install) toolchain installed on your system.
1. **Clone the repository:**
```bash
git clone https://github.com/francescofarina/carmen-lang.git
cd carmen
```
2. **Build the project:**
```bash
cargo build --release
```
The compiled binary will be located at `target/release/carmen`.
## Usage
The `carmen` executable can be used to run scripts, start an interactive REPL, or export compositions.
### Running a Script
To execute a script file, pass its path to the `carmen` executable:
```bash
carmen your_script.carmen
```
### Interactive REPL
To experiment with the language, you can run `carmen` without any arguments to start the interactive Read-Eval-Print Loop (REPL).
```bash
carmen
```
```
carmen Language REPL
Type 'exit' or press Ctrl+C to quit
carmen> 1/4 c4;
carmen> let theme = [1/8 [c4, d, e, f, g, a, b, c5]];
### Exporting a Score
Use the `--export` flag to convert a `.carmen` file into other formats.
```bash
# Export to LilyPond format
carmen --export lilypond your_score.carmen score.ly
# Export to a plain text summary
carmen --export text your_score.carmen summary.txt
```
### Debugging
Carmen provides flags to inspect the compilation process, which is useful for debugging.
- `--tokenize`: Shows the stream of tokens from the lexer.
- `--parse`: Displays the Abstract Syntax Tree (AST).
- `--inspect`: Provides a more detailed, human-readable view of the AST.
```bash
carmen --parse your_script.carmen
```
## Carmen Language Quick Start
Here is a small example of a multi-staff piano part written in Carmen.
```carmen
// File: example.carmen
score "Simple Piano Piece" {
@composer "Jane Doe";
@tempo 120;
timeline {
part "Piano" {
staff 0 { // Right hand
@clef "treble";
[1/4 c5, 1/8 d5, 1/2 e5];
};
staff 1 { // Left hand
@clef "bass";
[1/4 c3, 1/8 g3, 1/2 e4];
};
};
};
};
```
To compile this and generate a LilyPond file for sheet music:
```bash
carmen --export lilypond example.carmen example.ly
```
Once you have the `example.ly` file, you can generate a PDF of the sheet music using [LilyPond](http://lilypond.org/):
```bash
lilypond example.ly
```
For a complete guide to the language syntax and features, please see the [**Language Manual**](docs/language_manual.md).
## Examples
### Basic Melody
```carmen
// Simple melody with rests and dynamics
let melody = [
1/4 c4 mf,
1/8 d4,
1/8 e4,
1/2 f4 p,
1/4 ~
];
```
### Multi-Voice Bach Chorale
Carmen excels at complex multi-voice compositions. Here's an excerpt from Bach's BWV 147:
```carmen
let voice_1 = [
1/12 [~, g4, a, b, d5, c, c, e, d, d, g, fs, g, d, b4, g, a, b, c5, d, e, d, c, b4, a, b, g],
1/12 [fs4, g],
3/12 a4,
1/12 [g4, c5, b4, a],
];
let voice_2 = [
1/12 [~, b3, d4],
1/4 [d4, e, g, e, b3, a, d4],
1/2 c4,
1/4 [a3, fs4]
];
score "BVW 147" {
@composer "J S Bach";
@title "BVW 147";
@key_signature "G";
@time_signature 3/4;
@tempo 100;
timeline {
part "Violin" {
@clef "treble";
voice_1;
};
part "Violin 2" {
@clef "treble";
voice_2;
};
};
};
```
### Musical Transformations
```carmen
// Define a theme and apply transformations
let theme = 1/4 [c4, d, e, f];
// Apply transformations
// Pitch class set analysis
let chord_set = {0, 4, 7}; // C major triad as pitch classes
let normal = chord_set |> normal_form(); // Get normal form
let prime = chord_set |> prime_form(); // Get prime form
let ic_vec = chord_set |> ic_vector(); // Get interval class vector
let inverted = chord_set |> invert(2); // Get inversions
```
### Multi-Staff Piano Score
```carmen
score "Piano Piece" {
@composer "Carmen User";
@tempo 120;
@time_signature 4/4;
timeline {
part "Piano" {
staff 0 {
@clef "treble";
[1/4 c5, 1/8 d5, 1/2 e5];
};
staff 1 {
@clef "bass";
[1/4 c3, 1/8 g3, 1/2 e4];
};
};
};
};
```
For more examples, see the [`examples/`](examples/) directory.
## Development
If you want to contribute to Carmen or work on the project for development purposes:
1. **Clone the repository:**
```bash
git clone https://github.com/francescofarina/carmen-lang.git
cd carmen
```
2. **Build in debug mode:**
```bash
cargo build
```
3. **Run tests:**
```bash
cargo test
```
4. **Run with your changes:**
```bash
cargo run -- your_script.carmen
```
We welcome contributions! Please see our [contributing guidelines](CONTRIBUTING.md) for more information.
## Community
- **Issues & Bug Reports**: [GitHub Issues](https://github.com/francescofarina/carmen-lang/issues)
- **Documentation**: [Language Manual](docs/language_manual.md)
- **Crate Documentation**: [docs.rs/carmen-lang](https://docs.rs/carmen-lang)
## License
This project is dual-licensed under the terms of the [MIT License](LICENSE.MIT) and the [Apache License 2.0](LICENSE.Apache). You may choose to use this software under the terms of either license.