memol language overview

XXX: The documentation is very incomplete and already has many differences from the latest implementation.

memol is a music description language which features:

Essentially, memol describes a score as recursive composition of two constructs only: group "[...]" and chord "(...)".
Some musical elements like scale, chord and backing pattern can be described independently and composite them each other. "with" syntax enables (some of) them in a unified form. Separate descriptions of expressions (note velocity, control change, ...) are also planned.
Focused on musical composition
Language design and implementation help trial-and-error of musical composition well (in the future).

memol does not aim to have:

Complete ability to describe sheet music
Sheet music generation may be implemented in the future, but memol never will be a complete sheet music description language. Lilypond is awesome for this purpose (In fact, the sheet musics in this page are rendered by Lilypond!).

Although the core idea of the language is considered for many years, the development begun recently so both the language specification and the implementation are still in a very early stage. Currently they lack many features for practical use.

Build, install and run

Although any platform that run Rust and JACK are potentially supported, the main development platform is Linux. Please make sure that following programs are installed before building.

Using rustup is an easiest way to install Rust nightly and Cargo. Building and installing memol are quite simple thanks to Cargo; Just type

hg clone
cd memol-rs/memol
cargo install

and everything should be done. Note that Windows target must be *-gnu, not *-msvc due to JACK DLL linking issue.

Current implementation of memol is a simple command line program which emits MIDI messages to JACK.

memol [-c JACK_PORT] FILE

memol keeps watching the change of the file and reflects it immediately. If 'out.begin, 'out.end (see below) are specified, memol automatically seeks and starts playing each time the file has changed.

Since memol supports JACK transport, start/stop/seek operations are synced with other JACK clients (Currently Timebase is not supported). Personally I use Carla to manage JACK connections, LinuxSampler, LV2 plugins, etc. Many JACK supported DAW like Ardour can be used, of course.

JACK_PORT can be specified multiple times and then the memol output port is being connected to them.

Hello, twinkle little star

score 'out.0 = { c c G G | A A g _ | f f e e | d d c _ }

[image of music]

memol language structure is roughly divided into two layers: inside {...} and outside.



Newline and whitespace characters have no meanings except before and after some registerd words, symbol names and numbers.

score 'out = {
	[(cEGB)//] |
	(c E G B)


/* This is a comment */


memol has a mechanism to avoid annoying octave changing. If you write a note in upper case, it has higher pitch than previous one within a octave. If in lower case, it has lower pitch within a octave. "<" and ">" can be used to make the current octave +1 and -1 respectively.

score 'out.0 = { c D E d | > D E < c _ }

[image of music]


Sharp and flat pitches are represented as "+", "-" respectively. they must specified every time. A key signature can be specified with "with" syntax explained later.

score 'out.0 = { c D+ E++ F- }

[image of music]


Grouping is one of the unique features of memol. Unlike other language, absolute duration values are never specified in memol. Grouping is noted as "[...]" and it divides the duration equally into child notes and serializes them. Group notation can be nested oneself and other notation. Each child note have an optional number prefix, which represents a relative ratio. For example, "[3e 2c]" gives the duration 3/5 to "e" and 2/5 to "c".

score 'out.0 = { c | c c | c c c | c [c c c c] [3c c] [2c 3c [c c]] }

[image of music]


Chord is noted as "(...)" and child notes are located in parallel. Chord can be nested oneself and other notation. The note pitch used to determine the octave of next note is the first child of the chord, not the last child.

score 'out.0 = { (c E G) | (c E G [B C b]) (c E F A) }

[image of music]


Tie is noted by adding "^" after the note which the tie begins. Composite notes such as group and chord also can be tied. A tied chord means all child notes are tied. A tied group means the last note is tied.

score 'out.0 = { [3c c]^c [3c c^] c | (c E G)^(c E G) | (c^ E^ G) (c E G) | c^ E^ G^ (c E G) }

[image of music]


"/" is semantically equivalent to the previous note, the most recent simple note or chord in postordered depth-first traversal. The ties of child notes are inherited if a target is composite (the tie attached to itself is not inherited).

score 'out.0 = { (c E G) / | (c [E /]) | ([3c E]) / }

[image of music]

Score level composition

XXX: parallel, sequence, stretch, repeat, ...

score 'out.0 = [ 2:{ c D E d } ( { E F G A | c c c c } 3/4 { D E F } ) ]

Score symbols

Score symbols probably works as you expected. It is possible to use symbols defined after their location. Defining the same name symbol more than once causes error.

score 'part_a = { e F G A }
score 'part_b = { c D E F }
score 'out.0 = ('part_a 'part_b)

"with" syntax

"with" syntax is one of the unique feature of memol that enables high level music description.


score 'chord   = { (c E G B) (D F G B) | (c E G B) }
score 'pattern = { [$q0 Q1 Q2 q1] ($q0 Q1 Q2 Q3) }
score 'out.0   = 2:'pattern with q = 'chord

[image of music]

score 'a_major = { (c+DEF+G+AB) }
score 'out.0   = { ... } with _ = 'a_major

Value track

XXX: Specification/implementation is not completed.

value 'out.0.velocity = { [3 4] 3 2 | 2..4 3 } / {4}
value 'out.0.offset = gaussian / {128}
value 'out.0.cc11 = { 3..4 | 3..1 } / {4}

Articulation, arpeggio, sustain pedal

XXX: Not implemented yet.

Some special syntax for articulation, arpeggio, sustain pedal may be added in the future.

  @N(XXX) : arpeggio
       X~ : legato
(default) : non-legato
       X' : staccato

MIDI channels

Although this is out of the language specification, current implementation maps the score to MIDI outputs by variable names: 'out.0 .. 'out.15 are mapped to MIDI channel 1 .. 16.

Begin/end position


'out.begin = { 0}
'out.end   = {24}
Yasuhiro Fujii <y-fujii at>