8个版本 (5个重大更新)
0.5.1 | 2024年5月12日 |
---|---|
0.5.0 | 2023年11月17日 |
0.4.1 | 2023年11月17日 |
0.3.0 | 2023年11月17日 |
0.0.0 | 2023年11月8日 |
194 在 音频 中
每月下载 31 次
在 2 crates 中使用
37KB
686 行
LMML
LMML (LMML Music Macro Language) 是MML的一种方言。
演奏示例
https://github.com/yuma140902/lmml/assets/23431077/dfad8777-ade5-4591-8804-a3968a2e14ea
; Bad Apple!! feat. nomico
t320 l4
@0 v15
<ab>cd e.r8ag e.r8<a.r8> edc<b>
<ab>cd e.r8dc <bab>c <bagb>
<ab>cd e.r8ag e.r8<a.r8> edc<b>
<ab>cd e.r8dc <b.r8>c.r8 d.r8e.r8
@1 v10
<ab>cd e.r8ag e.r8<a.r8> edc<b>
<ab>cd e.r8dc <bab>c <bagb>
<ab>cd e.r8ag e.r8<a.r8> edc<b>
<ab>cd e.r8dc <b.r8>c.r8 d.r8e.r8
@3 v25
gaed e.r8de gaed e.r8
dedc <bga.r8 gab>c de<a.r8>
egga ede.r8 dega ede.r8
dedc <bga.r8 gab>c de<a.r8>
@4 v30
egga ede.r8 dega ede.r8
dedc <bga.r8 gab>c de<a.r8>
egga ede.r8 dega ede.r8
ab>c<b age.r8 dedc <bga.r8>
@0 v15
egga ede.r8 dega ede.r8
dedc <bga.r8 gab>c de<a.r8>
egga ede.r8 dega ede.r8
dedc <bga.r8 gab>c de<a.r8>
egga ede.r8 dega ede.r8
dedc <bga.r8 gab>c de<a.r8>
egga ede.r8 dega ede.r8
ab>c<b age.r8 dedc <bga.r8
LMML教程
演奏方法
要演奏LMML代码,最简单的方法是使用lmml-cli的交互模式。
cargo install lmml-cli
安装lmml-cli,
lmml repl
然后启动交互模式。
语法
LMML有一些命令。这些命令的集合构成了LMML程序。
要了解严格的语法,请参考下面的“LMML语言语法”。
音符命令
C
~B
的字母分别表示C到B的音。加上+
表示升高半音,加上-
表示降低半音。
音符命令后可以跟一个表示音长度的数字。四分音符为4,八分音符为8,等等。数字越大,音的长度越短,请注意。
如果省略了数字,则使用最后执行的L
命令的值。如果不存在L
命令,则使用4。
此外,可以在数字后加上.
。.
表示附点音符。
示例
c4
- C的四分音符c+8
- C#的八分音符d4.
- D的附点四分音符d+4.
- D#的附点四分音符
休符命令
R
表示休止符。与音符命令一样,可以跟一个表示长度的数字和.
。
和弦
通过用[
和]
括起来表示和弦。音符请按照根音顺序、从低到高书写。
示例
[ceg]
- C Major[ace]
- A Minor[ga+df]
- Gm7
; カノン進行 C/G - G - Am/E - Em - F/C - C - F/C - G/D
@4t40 [gce][gbd][eac][egb][cfa][ceg][cfa][dgb]
https://github.com/yuma140902/lmml/assets/23431077/9f5b72ed-5317-4cdf-bf3a-d028d05c7cd5
L
命令
设置音符的长度。如果没有在音符命令后跟数字,则使用此命令的值。有关详细信息,请参考下面的“LMML语言的详细规格”。
O
命令
设置八度值。初始值为4,值越大,音越高。八度4的A为440Hz。
>
命令
增加八度值。
<
命令
减少八度值。
N
命令
通过MIDI音符编号(0~127)指定音符。LMML不依赖于MIDI,但它使用MIDI兼容的格式处理音符。
※LMML不依赖于MIDI,但它使用MIDI兼容的格式处理音符。
V
命令
设置音量。初始值为20,值越大,音越大。100为0dB,0为-∞ dB。
T
命令
设置节奏。值表示每分钟四分音符的次数。初始值为120。
@
命令
使用0~4的数字设置波形。默认值是0。
数字 | 波形 |
---|---|
0 | 锯齿波 |
1 | 矩形波 |
2 | 脉冲波 |
3 | 三角波 |
4 | 正弦波 |
:
命令
LMML有16个通道,编号为0~15,可以同时演奏这些通道。
例如写作:0
,则后续的命令将作用于通道0。
示例
https://github.com/yuma140902/lmml/assets/23431077/6f76011c-c638-4741-a067-14986da3178d
; 少女さとり ~ 3rd eye (東方地霊殿より)
; (最初の2小節のみ)
:0 @3 v20 t60 o4
:1 @3 v20 t60 o3
:2 @3 v30 t60 o2
:3 @4 v50 t60 o2
:4 @4 v20 t60 o4
:5 @4 v40 t60 o1
:0 l8
<b4.>c+16d16f+ <b>df+g<b>c+gf+2
:1 l2
f+1 gf+
:2 l2
f+1 gf+
:3 l32
crrrrrrr rrrrrrrr [d+g]rrrrr[d+g]r rrrr[d+g]rrr
<<[bg+f]rrrrrrr rrrr[bg+f]rrr >[g+f]<rrrrrrr rrrrrrrr>>
:4 l2
[bf+]1[bg][bf+]
:5 l2
[bf+]1[bg][bf+]
LMML语言的语法
<lmml> := <command>*
<command> := <note-cmd>
| <chord>
| <n-cmd>
| <rest-cmd>
| <set-octave>
| <set-length>
| <set-volume>
| <set-tempo>
| <set-wave>
| <set-channel>
| <inc-octave>
| <dec-octave>
<note-cmd> := <note-char> <modifier>? <number>? <dot>?
<note-char> := 'C' | 'D' | 'E' | 'F' | 'G' | 'A' | 'B'
| 'c' | 'd' | 'e' | 'f' | 'g' | 'a' | 'b'
<modifier> := '+' | '-'
<rest-cmd> := 'R' <number>? <dot>? | 'r' <number>? <dot>?
<chord> := '[' (<note-char> <modifier>?)+ ']' <number>? <dot>?
<dot> := '.'
<n-cmd> := 'N' <number> | 'n' <number>
<set-ocatve> := 'O' <number> | 'o' <number>
<set-length> := 'L' <number> <dot>? | 'l' <number> <dot>?
<set-volume> := 'V' <number> | 'v' <number>
<set-tempo> := 'T' <number> | 't' <number>
<set-wave> := '@' <number>
<set-channel> := ':' <number>
<inc-octave> := '>'
<dec-octave> := '<'
<number> := <digit>+
<digit> := '0' | '1' | '2' | '3' | '4'
| '5' | '6' | '7' | '8' | '9'
基本上不区分大小写,忽略空白和换行。
以;
开头的行被视为注释并忽略。
LMML语言的详细规范
长度指定
音符命令、休符命令、L
命令中省略数字或.
时的行为如下表所示。预期行为可能因人而异的部分用粗体表示。
最后一个L 命令的数字 |
. 是否存在 |
音符・休符命令的数字 | . 是否存在 |
长度 |
---|---|---|---|---|
L 命令无 |
N/A | 省略 | 无 | 四分音符 |
L 命令无 |
N/A | 省略 | 有 | 附点四分音符 |
L 命令无 |
N/A | n | 无 | n分音符 |
L 命令无 |
N/A | n | 有 | 附点n分音符 |
m | 无 | 省略 | 无 | m分音符 |
m | 无 | 省略 | 有 | 附点m分音符 |
m | 无 | n | 无 | n分音符 |
m | 无 | n | 有 | 附点n分音符 |
m | 有 | 省略 | 无 | 附点m分音符 |
m | 有 | 省略 | 有 | 附点m分音符 |
m | 有 | n | 无 | n分音符 |
m | 有 | n | 有 | 附点n分音符 |
音高
音符命令转换为频率的过程分为两个阶段。
首先,将其转换为称为音符编号的内部形式。$n
$是音符命令的类型,$m
$是升号、降号等的指定,$o
$是当前的八度。
base = if n == C then 0
if n == D then 2
if n == E then 4
if n == F then 5
if n == G then 7
if n == A then 9
if n == B then 11
modifier = if m == '+' then 1
if m == '-' then -1
else 0
N = base + modifier + ((o + 1) * 12)
然后,将音符编号$N
$转换为频率$f
[Hz]。
f = 440 \times 2 ^ { \frac{N - 69}{12} }
音衰减
一个音符在响起瞬间音量最大,然后逐渐减小。具体来说,如果用V
命令指定的音量为$v_0
,音长为$T
,音响起后的经过时间为$t
,则$t
时刻的音量$v(t)
$是
v(t) = \frac{v_0 (T-t)}{T}
。
目前没有改变衰减方式的方法。
数值范围
八度的值
上限和下限都没有,但假设在-1到9的范围内使用。另外,由于在O
命令中只能指定非负值,因此如果要指定负的八度,请使用<
命令。
音量
下限是0,上限没有。但是,由于100对应于0dB,因此指定比100更大的值可能会导致音质受损。0时音完全不出。
N
命令的值
下限是0,上限没有。但是,假设在0到127的范围内使用。
节拍
下限是1,上限没有。
通道号
下限是0,上限是15。
LMML实现的详细规范
精度
使用44.1kHz、32bit-float进行波形合成。
各个crate
lmml
crate
包含LMML的AST和波形合成处理的crate。
lmml-parser
crate
LMML的解析器。
use lmml::{LmmlAst, LmmlCommand, NoteChar, NoteModifier};
use lmml_parser::parse_lmml;
pub fn main() {
let ast = parse_lmml("t80 c+ d e8. r8").unwrap();
assert_eq!(ast, LmmlAst(vec![
LmmlCommand::SetTempo(80),
LmmlCommand::Note {
note: NoteChar::C,
modifier: NoteModifier::Sharp,
length: None,
is_tied: false,
},
LmmlCommand::Note {
note: NoteChar::D,
modifier: NoteModifier::Natural,
length: None,
is_tied: false,
},
LmmlCommand::Note {
note: NoteChar::E,
modifier: NoteModifier::Natural,
length: Some(8),
is_tied: true,
},
Lmmlcommand::Rest {
length: Some(8)
is_tied: false,
},
]));
}
lmml-cli
crate
用于交互式演奏LMML或将其转换为其他格式的命令行工具。
安装方法
cargo install lmml-cli
使用方法
播放文件。
lmml load ファイル
启动交互模式。
lmml repl
依赖项
~1–33MB
~443K SLoC