Skip to content

鼓点类型的基本语法

Rainbow Dreamer edited this page May 21, 2022 · 13 revisions

目录

新增鼓点类型的支持,以及一套全新的写鼓点的语法

在2021年的5月初加入了鼓点类型,是一个全新的乐理类型,可以读取一个遵循特定语法规则的字符串并且转换为鼓点。

我自己设计了一套写作鼓点节奏的全新的语法,并且已经成功地写出了解释器函数,可以成功地解析符合这种语法的字符串,转换为MIDI文件的鼓点音符。接下来我用代码来为大家讲解这套用来鼓点节奏的语法。

首先,你可以自己定义数字或者字母或者特殊字符映射到不同的MIDI的鼓点音符的字典,我有在database里面先定义好了一个默认的鼓点映射字典。

这里的数字,字母,特殊字符的长度可以大于1,也就是说可以写多位数,单词和多个特殊字符作为一个整体进行映射。 这个是目前的默认的鼓点映射字典。

drum_mapping = {
    '0': 36, # Electric Bass Drum
    '1': 42, # Closed Hi-hat
    '2': 40, # Electric Snare
    '3': 38, # Acoustic Snare
    '4': 46, # Open Hi-hat
    '5': 44, # Pedal Hi-hat
    '6': 39, # Hand Clap
    '7': 35, # Acoustic Bass Drum
    '8': 57, # Crash Cymbal 2
    '9': 49  # Crash Cymbal 1
}

这里不同的数字的字符串映射到的值是MIDI的鼓点音符的值,不同的值代表不同的音高,在鼓点的情况下就表示不同种类的鼓点。比如0映射到的36就对应着MIDI的Electric Bass Drum,1映射到Closed Hi-hat,2映射到Electric Snare,我在database里也有写不同的值映射到的鼓点名称,可以看drum_types这个字典。简单来说,0,1,2现在分别对应着大鼓,踩镲,小鼓,现在我们可以写一个乐理类型drum,它的第1个参数是一个字符串,这个字符串里你可以按照我设计的鼓点语法来写鼓点,非常简洁而且功能很强大,可以玩很多宏的极简操作。

我设计的鼓点编写语法总共有12条规则,还有一些特殊情况。

规则1

单音模式,以,表示先后进行演奏 (比如大鼓,hihat,小鼓,hihat,大鼓,hihat,小鼓,hihat)

'0,1,2,1,0,1,2,1'  

规则2

同时有多个不同的鼓点演奏的模式,以;表示进行同时演奏,使用逗号隔开的音符还是先后进行演奏

'0,0;1,2,1,0,0;1;5,1;2,1'

规则3

如果两个鼓点之间(鼓点可以是单音或者多音)有间隔,以[n]的形式表示,n可以是任意整数,小数或者分数,单位为小节。

'0,[1],2,1,[1],0,2,1'

规则4

为每个鼓点设置长度,间隔和音量,每一个鼓点之后都可以跟上一个[长度;间隔;音量大小]的设置区块,同时也包括同时演奏的鼓点(以;进行连接的鼓点),如果第2个参数与第1个一样,那么也可以像和弦高级语法那样写.来省略,音量默认为100,也可以在鼓点类型的构建函数里把长度列表,间隔列表,音量大小列表传进去构建。

'0[1/4],1[1/4],2[1/4],1[1/4],0[1/4],1[1/4],2[1/4],1[1/4]'

设置区块里,如果有不想设置的参数,可以写n表示不设置,用来之后如果有批量设置的语句可以设置到。请注意批量设置的语句会覆盖掉每个鼓点的区块的设置,除非写了n表示不设置。

'0[1/4;n;80],1[1/4;1/2],2[1/4;1/8],1[1/4];2[1/8]'

请注意,如果是同时演奏的鼓点(以;进行连接的鼓点)进行设置区块的设置,请放在最后一个音的后面。

 '0[1/4;.],1[1/4;1/2],2[1/4;1/8],1;2[1/4;1/8],0[1/4],1[1/4;1/8;80],2[1/4],1[1/4]'

规则5

批量设置所有的鼓点的长度,间隔与音量大小,在!之后可以有1到3个参数,也是与同时演奏的鼓点的语法类似,使用;连接。

如果只写了1个参数,那么只批量设置全部的鼓点的长度,写了2个则设置全部的鼓点的长度和间隔,第3个参数为全部的鼓点的音量大小。

请注意,在这里多个鼓点同时演奏的部分的间隔不会进行设置,也就是说原本写的多个鼓点同时演奏的部分还是同时演奏(间隔为0)。

只有设置的长度和音量大小会进行设置,只有同时演奏的鼓点里的最后一个音的间隔会进行设置,因为是和下一个鼓点之间的间隔。

这个批量设置的语句只能放在开头或者结尾,也就是第1个鼓点的位置或者最后一个鼓点的位置。

如果有不想设置的参数(想按照默认的来或者想按照每一个单独设置好的来),可以写n表示不设置,写.表示和前一个参数设置的值一样。另外,这里的3个参数除了数字之外,也可以是列表。

'0,0;1,2,1,0,0;1;5,1;2,1,!1/4;1/4;1/4'
'!1/4;1/4;1/4,0,0;1,2,1,0,0;1;5,1;2,1'

规则6

如果不进行任何设置,默认的鼓点长度为1/8,鼓点间隔为1/8(同时演奏的语法里的中间的间隔都为0),鼓点的音量大小为100。默认的持续长度、间隔和音量可以在初始化鼓点实例时设置,也可以在区块中指定,如{de:duration;interval;volume},这将为上一个区块和当前区块之间的每个鼓点设置默认的持续长度、间隔和音量。下面的例子将鼓点的默认持续长度设置为1/16小节,默认间隔设置为1/16小节。

'0,[.16],1,1,2,[.16],0,[.16],0,1,0,0,2,[.16],0,[.16],{de:.16;.}'

规则7

想重复同一个鼓点n次,可以在一个鼓点后面加上(n),也可以加在加上了设置区块的鼓点后面, 或者后面也可以跟着设置区块,无论哪种情况,都会先把这个鼓点按照设置区块设置好,然后再重复n次 对于多个鼓点同时演奏的语法,无论有没有设置区块或者批量设置,都只需要在最后加上(n)即可表示重复n次

'0,1(3),2,1(3)'
'0,1(3)[1/4;1/4],2,1(3)[1/4;1/4]'
'0,1[1/4;1/4](3),2,1[1/4;1/4](3)'
'0,1;2(3),2,1;2[1/4;1/8](3),1;2[1/4;1/4;80](3)'

规则8

如果想把其中一段鼓点批量处理或者重复n次,可以使用{!1/4;1/4}{n},只需要当作一般的鼓点的写法写在一段鼓点之后就行了,会按照开头到这个截段语句或者上一个截段语句来作为需要批量处理的鼓点段落,{}的里面可以写批量处理语句。

如果只写一个数字则表示重复这个鼓点段落n次,如果想要两种结合使用,可以使用|连接,比如{!1/4;1/4|2}就表示批量设置指定的鼓点段落之后重复2次,两种设置的顺序可以随便来。

'0,1[1/4;1/4](3),2,1[1/4;1/4](3),{2},0,1[1/4;1/4](2),3,2,1[1/4;1/4](2),3,{2}'

规则9

如果想对一段鼓点进行编号,或者说取名字,那么可以在截段语句里写$n,其中n为编号,可以是数字或者字母,长度可以大于1,同样也可以与另外两种设置结合使用,在后面的鼓点中如果想要使用这段已经编号的鼓点,可以当做一般的鼓点写$n进行使用。

'0,1[1/4;1/4](3),2,1[1/4;1/4](3),{$1},0,1[1/4;1/4](2),3,2,1[1/4;1/4](2),3,{$2},$1,$2'

编号语句在定义之后调用时,可以当做一般鼓点来使用,同样也可以使用设置区块,重复语句,比如

'$1[1/4;1/4]' # 这时的设置区块表示对$1进行批量设置,参数可以参考第5种情况
'$1(2)' # 重复编号1的鼓点段落2遍

注意事项

  1. 请注意,参数为列表的时候,在对于多个同时演奏的鼓点进行设置的时候(或者批量设置全体鼓点的时候),必须以|作为间隔,在截段语句中必须以`作为间隔,在这两种情况中,三个参数之间的间隔都可以使用;
  2. 请注意,在多个鼓点同时演奏的语法下,使用对于每个鼓点的设置区块是不合语法的,比如'1[1/4;1/4];2[1/8;1/8]'这样写是不合语法的
  3. 如果想要对于多个鼓点同时演奏的每个鼓点进行长度的设置,请把设置区块放在最后一个鼓点的后面,参数可以使用列表,这种情况下使用列表必须省略括号([]),如果是在截段语句里批量处理或者批量设置全体鼓点使用列表作为参数,则可以使用[]
  4. 你可以放置任意的空格与换行,它们不会影响解析器转换后的内容,因此你可以把鼓点代码写的更加漂亮,有层次感。
  5. 音符长度和间隔的设置也可以使用语法糖,使用.n表示1/n,也就是n分音符。

鼓点类型的构建与用法介绍

鼓点类型(drum)的构成类似于和弦类型,同样都有一个音符列表,也同样可以进行重复n遍,合并,设置整体音符参数等语法操作,也可以直接播放,请注意在使用play函数(无论是使用鼓点类型内置函数还是使用全局函数)播放鼓点类型的时候,会自动把鼓点类型编入一个乐曲类型,并且将MIDI通道数设置为9(从0开始算作第1个,也就是MIDI的第10个通道,专门给鼓轨用的)。

请注意,鼓点类型本身并不包含速度,也就是tempo,或者说bpm,因为鼓点类型在设计时是与和弦类型放在同一个层面上来看的,鼓点类型(drum)与和弦类型(chord)都不包含速度的参数,乐曲类型(piece)和音轨类型(track)包括。

鼓点类型在构建时,可以传入一个字符串,也可以传入一个和弦类型,其中默认的第1个参数位置是字符串,也可以用pattern关键字参数指定,如果想传入和弦类型,可以用notes关键字参数指定。如果传入的是字符串,在鼓点类型的构建时就会对传入的字符串进行鼓点语法的解析,并且转换为一个和弦类型储存在鼓点类型中。鼓点类型可以用name关键字参数为你写的鼓点取名字,可以用mapping关键字参数指定字符映射到鼓点值的字典,在这里鼓点值的意思是general MIDI里的不同鼓点对应的数字,我在database里的drum_types有写不同鼓点对应的是哪些数字。

你可以使用i关键字参数来设定鼓组的音色,可以参考general MIDI的鼓组音色对应的数字。

另外,对于和弦类型也可以使用translate函数,使用和编写鼓点同样的一套语法来写和弦类型或者一段曲子,只需要把自定义的字符换成音符名称就可以了。

鼓点类型的构成

drum(pattern='',
     mapping=drum_mapping,
     name=None,
     notes=None,
     i=1,
     start_time=None)
  • pattern: 用来解析为鼓点的字符串
  • mapping: 鼓点映射的字典,可以自定义,默认值为drum_mapping
  • name: 鼓点的名字
  • notes: 鼓点的和弦类型,可以直接传入作为鼓点,默认为None,也就是按照pattern进行转换作为鼓点
  • i: 鼓点的乐器类型,对应General MIDI的打击乐器编号
  • start_time: 鼓点的开始时间,如果为None,则使用鼓点的和弦类型的开始时间
drum_example = drum('0,1,2,1,0;1,0;1,2,1,{2}')
# 这是一段鼓点的例子,前面4个单音鼓点,然后是2个双音鼓点,然后是2个单音鼓点,最后整段重复2遍,
# 其中0,1,2分别表示大鼓,踩镲和小鼓,因此0;1表示的就是大鼓和踩镲同时演奏
play(drum_example, 150) # 以150bpm的速度播放这段鼓点
>>> print(drum_example)
[drum] 
[C2, F#2, E2, F#2, C2, F#2, C2, F#2, E2, F#2, C2, F#2, E2, F#2, C2, F#2, C2, F#2, E2, F#2] with interval [0.125, 0.125, 0.125, 0.125, 0, 0.125, 0, 
0.125, 0.125, 0.125, 0.125, 0.125, 0.125, 0.125, 0, 0.125, 0, 0.125, 0.125, 0.125]

# 如果在乐曲类型把鼓点类型作为音轨,必须要提取鼓点类型的notes属性作为和弦类型,并且把对应的channel设置为9
piano1 = C('Cmaj7') % (1, 1/8)
piece_example = P([piano1, drum_example.notes], [1, 1], channels=[0, 9])
play(piece_example)
Clone this wiki locally