Skip to content

tr-takatsuka/rlib-MML

Repository files navigation

Music Macro Language Compiler

日本語

Description

A class library that compiles (converts) MML into standard MIDI files. Implementation in C++17.

  • It is in a form that can be built as a command line application.
  • The MML grammar does not have a fixed standard, but it is implemented to follow something like an implicit standard.

Demo Page

https://rlib-mml.thinkridge.jp/

It summarizes the process from MML creation to playback on the browser.

Requirement

It can be compiled in a C++17 environment. The build requires boost.

We have confirmed the operation in the following environment.

  • linux g++
  • windows VisualStudio 2019,2022

WebAssembly

Experimental WebAssembly support is also available.

MML (Music Macro Language)

notes

notation description example
a~[+-][length] It is a note.
Immediately after, press +-to raise or lower a semitone (optional).
You can then specify the note length (optional).
"f4" → It is a quarter note F.
"cdefgab" → It is notes. The note length is the default value.
"a-16." → dotted quarter note B♭.
r[length] It is a rest. You can specify the note length immediately after it (optional). "r16" → 16th rest.
^[length] It's Tie. You can specify the note length immediately after it (optional).
Add the note length of the previous note. Same as rest if immediately preceding is not a note.
"c4^4^4" → It is the length of three quarter notes.
"c4 t50 ^4 t20 ^4" → It is the length of three quarter notes. However, the tempo is changed on the way. It is possible to write another instruction between the note and ^.
l[length] This is the default note length.
This value is used when the note length is omitted for notes and rests.
"l8 cde" → This is an 8th note CDE.
<
>
octave up(<) and down(>).
The range of one octave is 12 tones from C to B.
"c<c>c<c" → C and C one octave higher are repeated twice.
o[octave] Specify the octave. Values ​​are -2-8.
MIDI note number 60 is C3. Write "o3c"
"o3 cde" → MIDI note number 60(C3)、62(D3)、64(E3)
t[tempo] Specify the tempo. The value can be specified from 1.0 to 999.0. A small number can be written. "t120 cde" → CDE at tempo 120.
@[program no] Specify the program number (tone). Values ​​are 0-127. "@3 cde" → CDE atprogram number 3.
v[velocity] Specifies the velocity (the strength with which you hit the keyboard on a piano). Values ​​are 0-127. "v123 cde" → CDE at velocity 123.
'[switch chord mode] Switches to a mode where the current position is not advanced by notes. Use rests to advance the current position. Use when two or more notes are pronounced simultaneously, e.g. chords. "l8 'cegr dfar' "
→ 8th note C major chord and D miner chords.

length

  • This is how to specify the length of the note.
notation description example
1~192
note notation
Specify the value of the minute note.
It is also possible to write 12th notes and 24th notes.
"c4" → It is a quarter note C.
!1~!99999
Step number notation
Specify by the number of steps. The quarter note is 480. "c!240" → 8th note C.
.
point notation
It means a dotted point called a minute note.
By writing more than one, it becomes the meaning of a double-dotted note (add half of the previous note length).
"c4." → dotted quarter note C.
"c4..." → note length that is the sum of quarter notes, 8th notes, 16th notes, and 32th notes.
+ - length
subtraction of numerical note length
Adds or subtracts the note length value. "c8+4" → note length of 8th note plus quarter note.
"c32d32e1-32-32" → 32th note C and D, shortened by 2 32th notes from a whole note.

"d-4" → In this case, it is a quarter note D♭. be careful.

function

notation description example
CreatePort(
 name:[port name],
 instrument:[instrument name](optional),
 channel:[channel number],
)
Define (declare) the port
Channel numbers are 1-16.
"createPort(name:Piano, channel:3)"
→ Declare the port of MIDI channel 3 with the name "Piano".
instrument specifies the name of the instrument. If omitted, the default instrument is used.
Port([port name]) It is port switching "port(Piano) cde" → CDE at Port "Piano"
V([volume value])
ailias: volume
The volume. Values ​​are 0-127. "V(120) cde" → CDE at Volume 120.
Pan([pan value])
ailias: panpot
It is pan (panpot).
Values ​​range from 0 (far left) to 127 (far right), with 64 in the center.
"pan(0) cde" → CDE at Pan 0 (far left).
PitchBend([value]) Pitch bend.
Values range from -8192 (two notes down) to 8191 (two notes up), with the centre at 0.
"PitchBend(-4096) cde Pan(0) cde"
→ CDE lowered by a semitone and normal CDE.
CC([contorl change no],[value])
ailias: ContorlChange
Contorl change.
The first argument is the control number and the first argument is the value
"CC(0,10)CC(32,130)@2" Bank-selected programme change.
CreateSequence(
 name:[sequence name],
 mml:[MML],
)
Defined Sequence(sub Sequence).
Define songs (MML) as parts and call them in subsequent MMLs.
// Defined rhythm pattern
CreateSequence(name:drum, mml:"
 CreatePort(name:kick, channel:10) l8 o1 c^^c ^c^^
 CreatePort(name:snare, channel:10) l8 o1 ^^d^ ^^d^
")
Seq(
 [sequence name],
 length:[length(optional)]
)
ailias Sequence
Calls a predefined sequence (sub-sequence). // Defined rhythmic pattern is repeated three times.
// Only half-note minutes are used for the third round of the sequence.
Seq(drum) Seq(drum) Seq(drum,length:2)
Meta(
 type:[event type],
 [data]...
)
Meta Event.
type specifies the event type.
Specify data with a variable-length argument with no name. It is not necessary to describe the data length.
// title info
Meta(type:0x1,"The Lost King's Scepter")
// SMPTE offset
Meta(type:0x54,96,0,0,0,0)
DefinePresetFM(
 no:[program no],
 name:[name],
 [data]...
)
Sequencer specific meta event that defines FM sound tone in rlib-MML. DefinePresetFM(no:4,name:"piano",
// AR DR SR RR SL TL KS ML DT
29, 8, 0, 8, 3, 31, 2, 1, 3,
31, 3, 1, 6, 10, 0, 0, 2, 7,
29, 20, 0, 9, 2, 44, 0, 4, 2,
31, 7, 2, 6, 6, 0, 0, 1, 5,
// AL FB
4, 7,
)

string

Where a string is specified, the following formats can be used.

notation description example
○○○ This designation is possible in alphanumeric characters only. abcdefg
"○○○" " to " is a string. You can also use spaces and non-symbols.  "drum part"
R"**(○○○)**" It can also be used for whitespace and symbols.
If you are defining a sequence within a sequence, you can use ** as a unique string to deal with cases where you have a string definition within a string definition 
R"(drum)"

R"ch1( mml:R"(drum)" )ch1"

comments

notation description example
// ○○○ This is a one-line comment. // After that, the comment is up to the line break. // its comments.
/* ○○○ */ It is a range comment.
Comments are from / * to * /. Comments that span multiple lines are also possible.
/* its
comments. */

Licence

LICENSE