Musa-DSL
A Ruby framework and DSL for algorithmic sound and musical thinking and composition.
Description
Musa-DSL is a programming language DSL (Domain-Specific Language) based on Ruby designed for sonic and musical composition. It emphasizes the creation of complex temporal structures independently of the audio rendering engine, providing composers and developers with powerful tools for algorithmic composition, generative music, and musical notation.
Who is it for?
- Composers exploring algorithmic composition
- Musicians interested in generative music systems
- Developers building music applications
- Researchers in computational musicology
- Live coders and interactive music performers
Key Features
- Advanced Sequencer - Precise temporal control for complex polyrhythmic and polytemporal structures
- Transport & Timing - Multiple clock sources (internal, MIDI, external) with microsecond precision
- Audio Engine Independent - Works with any MIDI-capable, OSC-capable or any other output hardware or software system
- Series-Based Composition - Flexible sequence generators for pitches, rhythms, dynamics, and any musical parameter
- Generative Tools - Markov chains, combinatorial variations (Variatio), formal grammars (GenerativeGrammar), and genetic algorithms (Darwin)
- Matrix Operations - Mathematical transformations for musical structures
- Scale System - Comprehensive support for scales, tuning systems, and chord structures
- Neumalang Notation - Intuitive text-based and customizable musical (or sound) notation
- Transcription System - Convert musical gestures to MIDI and MusicXML with ornament transcription expansion
Getting Started
Recommended Editor: RubyMine
RubyMine provides the best experience for MusaDSL development: intelligent autocomplete of methods and parameters, hover documentation, and type inference help you discover the API as you write.
Free licenses available:
- Non-commercial use β for learning, hobbies, open-source, content creation
- Students and Teachers/Researchers β with institutional email
VSCode with the Ruby LSP extension also works well, though Ruby autocomplete and hover documentation are less complete.
Framework Installation
Add to your Gemfile:
gem 'musa-dsl'Or install directly:
gem install musa-dslRequirements:
- Ruby ~> 3.4
Examples
Two complete, runnable examples included here. Pedagogical learning is covered separately in the musadsl-demo repository.
- Sequencer DSL with interacting voices β multiple voice lines coordinated through shared state, demonstrating the sequencer DSL and timing primitives.
- Neuma notation β composing melodies with grade-based Neuma notation and the parser.
Demo Projects
A collection of 22+ working demo projects covering the full spectrum of Musa DSL capabilities:
- Basic concepts: Setup, series, neumas, canon
- Generative tools: Markov chains, Variatio, Darwin, Grammar, Matrix
- DAW integration: MIDI sync, live coding, clock modes
- External protocols: OSC with SuperCollider and Max/MSP
- Advanced patterns: Event architecture, parameter automation, multi-phase compositions
Each demo is a complete, runnable project with documentation explaining the concepts demonstrated.
MusaDSL Ecosystem
MusaDSL is a comprehensive ecosystem consisting of a core framework (musa-dsl) and associated projects for communication, development, and integration.
Core Framework:
- musa-dsl - Main DSL framework for algorithmic composition and musical thinking
MIDI Communication Stack (used internally by musa-dsl for MIDI I/O):
- midi-events - Low-level MIDI event definitions and protocols
- midi-parser - MIDI file parsing and analysis
- midi-communications - Cross-platform MIDI I/O abstraction layer
- midi-communications-macos - macOS-specific MIDI native implementation
MusaDSL Architecture
The musa-dsl framework is organized in modular layers. Each component has its own detailed documentation.
1. Foundation Layer
- core-ext - Ruby refinements and metaprogramming utilities: Arrayfy, Hashify, ExplodeRanges, DeepCopy, DynamicProxy, AttributeBuilder.
- logger - Structured logging system with severity levels.
2. Temporal & Scheduling Layer
- sequencer - Event scheduling engine with musical time (bars/beats), microsecond-precise tick-based timing, and a DSL for temporal composition. Tick-based (quantized) and tickless (continuous) modes; series playback with automatic duration management; polyrhythms and polytemporal structures.
- transport - Comprehensive timing infrastructure connecting clock sources to the sequencer. Supports multiple clock types (TimerClock, InputMidiClock, ExternalTickClock, DummyClock), BPM management, tempo changes, and the start/stop/pause/continue playback lifecycle.
3. Notation & Parsing Layer
- neumas + neumalang - Compact text-based musical notation system with parser and interpreter for converting notation to structured musical data, with DSL support.
4. Generation & Transformation Layer
- series - Lazy functional sequence generators with map/filter operations, numeric generators, buffering, quantization, and timed merging. Transpose, repeat, and combination operations; infinite and finite series support.
- generative - Algorithmic composition tools: Markov chains (probabilistic sequence generation), Variatio (Cartesian product parameter variations), GenerativeGrammar (formal grammar-based generation), and Darwin (genetic algorithms for evolutionary composition).
- matrix - Matrix operations for musical gestures: matrix-to-P (point sequence) conversion for sequencer playback, gesture condensation and transformation. Treats sonic gestures as geometric objects.
5. Output & Communication Layer
- transcription - Musical event transformation system with ornament expansion (trills, mordents, turns), GDV to MIDI/MusicXML conversion, and dynamic articulation rendering. Expansion for MIDI or preservation as notation symbols for MusicXML.
- musicxml - MusicXML score generation. Hierarchical structure, multiple voices, multi-part scores, articulations, dynamics, tempo, and notation directives. Standard MusicXML 3.0 output.
- midi - MIDI voice management with polyphonic voice allocation, channel management, note-on/note-off scheduling, automatic note tracking, and MIDI input recording with precise timestamping.
6. Musical Knowledge Layer
- music - Scales, tuning systems, intervals, and chord structures. Equal temperament and just intonation support; modal scales (major, minor, chromatic, etc.); chord definitions, harmonic analysis, and chord navigation.
- datasets - Type-safe musical event representations: GDV (Grade-Duration-Velocity, scale-relative), PDV (Pitch-Duration-Velocity, absolute), PS, P, V. Conversions, validation, Score container (timeline-based multi-track composition), and advanced queries.
7. Development & Interaction Layer
- repl - Interactive Read-Eval-Print Loop for live composition. TCP-based server for real-time code evaluation and error handling. Consumed by external REPL clients (editor extensions, custom evaluators).
Where to start
The layers above are the order the framework is BUILT in, bottom-up by dependency. It is not the order to read it in. These are:
New to MusaDSL? Start with one of the examples and the architecture above, then read in this order β which cuts across the layers on purpose, because output is the fastest way to hear that something works:
- midi β getting a sound out
- sequencer β putting it in time
- series β generating the material
- datasets β what an event is made of
Want to compose?
- neumas β the notation
- music β scales and chords
- generative β Markov, Variatio, grammars, Darwin
- musicxml-builder β if the piece has to be read on paper
- The 22 demo projects, which are complete pieces rather than snippets
Live coding?
- repl β the server your editor talks to
- A MusaLCE client (VSCode, Bitwig, Live)
- sequencer β its DSL is what you type live
- transport β syncing to a DAW's clock
Extending the DSL? These two are the foundation the framework is written on, and they are the last thing to read rather than the first:
- core-extensions β the refinements and metaprogramming everything else assumes
- datasets β read as an extension point: how a Hash becomes a musical event, and how to add your own
Writing a whole piece rather than a snippet? project structure is how a musa-dsl project is laid out β the split between infrastructure and score, reaching one from the other, stopping cleanly, and shaping form as events rather than as absolute positions. Conventions, not API: none of it is enforced, and all of it follows from something that is.
Looking for a name you half remember? vocabulary is every name the guides above teach, on one page, by subsystem. It answers what is there β the one question you cannot look up β and it is generated from the published API and the guides themselves, so it cannot drift from either.
And one that is not a stage of any of them. idioms is for the moment of writing, whichever path brought you there: it is organised by the SHAPE of the problem, and each entry names a reflex β something a competent programmer writes before asking what MusaDSL calls it. The reflex always works, which is the problem: it produces code that runs, sounds right, passes every test, and is foreign to the framework. Read it from the symptom, when you are about to make the mistake rather than after.
Documentation
The subsystem guides linked above are the conceptual documentation: when each
one is the answer, how to think about it, and the traps. Every Ruby block in
them is executed by tools/doc-examples.rb, and every output they declare is
compared with what the code actually returns -- so a page that has drifted fails
the suite rather than misleading a reader.
The API reference is generated from the inline YARD documentation, whose
@example blocks are held to the same standard:
bundle exec yard doc
bundle exec yard serverThen open http://localhost:8808.
Contributing
Contributions are welcome. Fork the repository, create a feature branch, make your changes with tests, and open a pull request.
Repository: https://github.com/javier-sy/musa-dsl
Examples & Works
Listen to compositions created with Musa-DSL: yeste.studio
Author
- Javier SΓ‘nchez Yeste -- javier (at) yeste.studio
Special thanks to JetBrains for providing an Open Source project license for RubyMine during several years.
License
Musa-DSL Copyright (c) 2016-2026 Javier SΓ‘nchez Yeste, licensed under LGPL 3.0 License