Skip to content

鼓点类型的基本语法

Rainbow Dreamer edited this page Mar 13, 2023 · 13 revisions

目录

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

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

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

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

请注意,这里映射到-1(默认为0)的字符串将被解释为休止符,为前一个音符增加额外的间隔,映射到-2(默认为-)的字符串将被解释为延续符号,增加前一个音符的间隔并延长持续长度。

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

这个是目前的默认的鼓点映射字典,一共有两套模板可以选择使用,也可以自定义鼓点映射字典。

drum_mapping = {
    'K': 36,  # Electric Bass Drum
    'H': 42,  # Closed Hi-hat
    'S': 40,  # Electric Snare
    'S2': 38, # Acoustic Snare
    'OH': 46, # Open Hi-hat
    'PH': 44, # Pedal Hi-hat
    'HC': 39, # Hand Clap
    'K2': 35, # Acoustic Bass Drum
    'C': 57,  # Crash Cymbal 2
    'C2': 49, # Crash Cymbal 1
    '0': -1,  # rest
    '-': -2   # the continuation of last note
}

drum_mapping2 = {
    '0': 36,
    '1': 42,
    '2': 40,
    '3': 38,
    '4': 46,
    '5': 44,
    '6': 39,
    '7': 35,
    '8': 57,
    '9': 49,
    'x': -1,
    '-': -2
}

这里不同的数字的字符串映射到的值是MIDI的鼓点音符的值,不同的值代表不同的音高,在鼓点的情况下就表示不同种类的鼓点。现在我们可以写一个乐理类型drum,它的第1个参数是一个字符串,这个字符串里你可以按照我设计的鼓点语法来写鼓点,可以比较简洁地表示复杂的鼓点。

单个鼓点,以,为间隔,表示先后进行演奏 (比如大鼓,hihat,小鼓,hihat,大鼓,hihat,小鼓,hihat)。

'K, H, S, H, K, H, S, H'  

同时有多个不同的鼓点演奏,以;为间隔,表示进行同时演奏。这样组合起来的鼓点可以称为音符组

'K, K;H, S, H, K, K;H;PH H;S, H'

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

'K, i:1, S, H, i:1, K, S, H'

每一个鼓点之后都可以跟上一个设置区块,同时也包括同时演奏的鼓点(以;进行连接的鼓点)。设置区块只作用于它附属的音符或者音符组。

'K[l:1/4]'

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

'K[l:1/4;i:n;v:80]'

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

 'H;S[l:1/4;i:1/8]'

关键字头可以对其作用范围内的鼓点实现各种不同的功能,鼓点会以关键字头或者小节线|进行分段,每个关键字头都会作用于上一个关键字头或者小节线与它之间的鼓点。例如,K, H, S, H, r:2,这里r:2将前一部分重复两次。

一部分关键字头可以放在设置区块里,以;进行分隔。

这里介绍一下每一个关键字头的功能:

关键字 外部功能 设置区块内的功能
r:n 重复鼓点n次 重复鼓点n次, 设置区块作用的音符当有分配到的固定长度时,每个音符的长度和间隔根据重复的次数平分
R:n 重复鼓点n次,有分配到的固定长度时,每个音符的长度和间隔不进行平分
d:l;i;v 设置默认长度l,间隔i,音量v,也可以分别使用dl, di, dv
a:l;i;v 设置全部统一长度l,间隔i,音量v,也可以分别使用al, ai, av
t:n 设置区间的总长度为n,区间里的每个音符的长度为总长度除以区块音符的数量,可以使用空音符(鼓点映射里值为-1的字符)和延续音符(鼓点映射里值为-2的字符)进行占位,比如 K, H, S, H, 0, K, S, H, K, -, S, H, K, K, S, H, t:2 这一段就是每个音符都是占1/8个小节, 0是空拍, -是前一个音符的延续 与外部功能相同
b:n 当有设定总长度时,将区间内的节拍数设置为n个节拍,这将为每个鼓点单元分配一个单位长度 如果在设置区块中设置,则将长度设置为单位长度 * n
B:n 在设置区块里使用,功能与b的全局情况相同,当设置区块里有设定总长度时有效
i:n 音符中间插入间隔n小节 设置音符的间隔为n小节
l:n 设置音符长度为n小节
v:n 设置音符音量为n
n:name 设置区间的鼓点的名字为name
u:name 按照名字name使用区间鼓点
s:T 音符组是否同时演奏(T/F),为否的时候鼓点在固定总长度时会以一个鼓点的长度来进行平分
cm:n 仅用于单个延续符号,将延续模式设置为n,值可以是0或1,如果值为0,只延长上一个音符的时长,如果值为1,当前一个音符为一组时,延长组中所有音符的时长;如果没有设置延续模式,延续符号的默认动作是只延长前一个音符,除非前一个音符为一组,并且设置为同时播放,在这个情况下延长组中所有的音符
cs:T 当你用和弦类型作为鼓点时,和弦的音符是否同时演奏(T/F)
!keyword !与关键字头结合表示批量设置目前全部的音符,比如: K, H, S, H | K, K, S, H, !r:2

当设置区块中没有指定关键词时,其值与初始化和弦时的设置区块相同,即[长度;间隔;音量]

注意事项

  1. 请注意,在设置区块里,参数为列表的时候,需要单独设置一个设置区块,使用;分隔列表的元素,可以多个设置区块放在一起。
  2. 你可以放置任意的空格与换行,它们不会影响解析器转换后的内容,因此你可以把鼓点代码写的更加漂亮,有层次感。
  3. 音符长度和间隔的设置也可以使用语法糖,使用.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,
     default_duration=1 / 8,
     default_interval=1 / 8,
     default_volume=100,
     translate_mode=0)
  • pattern: 用来解析为鼓点的字符串
  • mapping: 鼓点映射的字典,可以自定义,默认值为drum_mapping
  • name: 鼓点的名字
  • notes: 鼓点的和弦类型,可以直接传入作为鼓点,默认为None,也就是按照pattern进行转换作为鼓点
  • i: 鼓点的乐器类型,对应General MIDI的打击乐器编号
  • start_time: 鼓点的开始时间,如果为None,则使用鼓点的和弦类型的开始时间
  • default_duration: 默认的鼓点长度
  • default_interval: 默认的鼓点间隔
  • default_volume: 默认的鼓点音量
  • translate_mode: 设置为0以鼓点解析,设置为1以和弦解析
drum_example = drum('K, H, S, H, K;H, K;H, S, H, r:2')
# 这是一段鼓点的例子,一开始是kick, hi-hat, snare, hi-hat, 然后是2个kick和hi-hat同时演奏,然后是1个snare和1个hi-hat,最后整个部分重复2次。
#其中K,H,S分别表示kick, hi-hat和snare,所以K;H表示kick和hi-hat同时演奏
play(drum_example, 150) # 以150bpm的速度播放这段鼓点
>>> print(drum_example)
[drum] 
chord(notes=[C2, F#2, E2, F#2, C2, F#2, C2, F#2, E2, F#2, ...], interval=[1/8, 1/8, 1/8, 1/8, 0, 1/8, 0, 1/8, 1/8, 1/8, ...], start_time=0)

# 如果在乐曲类型把鼓点类型作为音轨,必须要提取鼓点类型的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