| Crates.io | carmen-lang |
| lib.rs | carmen-lang |
| version | 0.1.2 |
| created_at | 2025-07-17 12:57:11.0267+00 |
| updated_at | 2025-07-31 20:54:51.335688+00 |
| description | A programming language for music composition |
| homepage | |
| repository | https://github.com/francescofarina/carmen-lang |
| max_upload_size | |
| id | 1757458 |
| size | 743,085 |
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.
if/else), and loops (for, while) to generate and manipulate musical material.T), inversion (I), normal/prime form calculation, and more..ly files)The easiest way to install Carmen is through Cargo, Rust's package manager:
cargo install carmen-lang
This will download, compile, and install the carmen executable from crates.io.
For development purposes or to use the latest unreleased features, you can build from source:
You will need to have the Rust programming language toolchain installed on your system.
git clone https://github.com/francescofarina/carmen-lang.git
cd carmen
cargo build --release
The compiled binary will be located at target/release/carmen.The carmen executable can be used to run scripts, start an interactive REPL, or export compositions.
To execute a script file, pass its path to the carmen executable:
carmen your_script.carmen
To experiment with the language, you can run carmen without any arguments to start the interactive Read-Eval-Print Loop (REPL).
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]];
carmen> theme |> transpose(2);
Use the --export flag to convert a .carmen file into other formats.
# 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
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.carmen --parse your_script.carmen
Here is a small example of a multi-staff piano part written in 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:
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:
lilypond example.ly
For a complete guide to the language syntax and features, please see the Language Manual.
// Simple melody with rests and dynamics
let melody = [
1/4 c4 mf,
1/8 d4,
1/8 e4,
1/2 f4 p,
1/4 ~
];
Carmen excels at complex multi-voice compositions. Here's an excerpt from Bach's BWV 147:
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;
};
};
};
// Define a theme and apply transformations
let theme = 1/4 [c4, d, e, f];
// Apply transformations
let transposed = theme |> transpose(7); // Transpose up a perfect fifth
// 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
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/ directory.
If you want to contribute to Carmen or work on the project for development purposes:
git clone https://github.com/francescofarina/carmen-lang.git
cd carmen
cargo build
cargo test
cargo run -- your_script.carmen
We welcome contributions! Please see our contributing guidelines for more information.
This project is dual-licensed under the terms of the MIT License and the Apache License 2.0. You may choose to use this software under the terms of either license.