carmen-lang

Crates.iocarmen-lang
lib.rscarmen-lang
version0.1.2
created_at2025-07-17 12:57:11.0267+00
updated_at2025-07-31 20:54:51.335688+00
descriptionA programming language for music composition
homepage
repositoryhttps://github.com/francescofarina/carmen-lang
max_upload_size
id1757458
size743,085
Francesco Farina (francescofarina)

documentation

README

Carmen - Programmatic Music Composition

Crates.io Documentation License

Table of Contents

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:

cargo install carmen-lang

This will download, compile, and install the carmen executable from 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 toolchain installed on your system.

  1. Clone the repository:
    git clone https://github.com/francescofarina/carmen-lang.git
    cd carmen
    
  2. Build the project:
    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:

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).

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);

Exporting a Score

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

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.
carmen --parse your_script.carmen

Carmen Language Quick Start

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.

Examples

Basic Melody

// 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:

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

// 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

Multi-Staff Piano Score

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.

Development

If you want to contribute to Carmen or work on the project for development purposes:

  1. Clone the repository:
    git clone https://github.com/francescofarina/carmen-lang.git
    cd carmen
    
  2. Build in debug mode:
    cargo build
    
  3. Run tests:
    cargo test
    
  4. Run with your changes:
    cargo run -- your_script.carmen
    

We welcome contributions! Please see our contributing guidelines for more information.

Community

License

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.

Commit count: 0

cargo fmt